ベクトル化とは、配列全体に1回で計算すること
ベクトル化とは、ループで1つずつ計算する代わりに、配列全体へ1回の演算をかけることです。同じ計算を大量のデータにかける仕事では、書き方で速さが大きく変わります。
配列とは、同じ種類の数を並べた入れ物です。NumPy(ナムパイ)は、Pythonで配列をまとめて計算するライブラリです。GPUも、この考え方の延長にあります。
このレッスンのゴール
メモ
ループで書いた計算を、配列全体への1回の演算に置き換えられる。
重要な言葉
| ことば | いみ | れい |
|---|---|---|
| 配列 | 同じ種類の数を、順に並べた入れ物 | [120, 300, 80] |
| ベクトル化 | ループをやめて、配列全体に1回の演算をかけること | |
| 要素ごとの演算 | 2つの配列の、同じ位置どうしを計算すること | |
| 内積 | 同じ位置どうしを掛けて、全部を足した数 | |
| NumPy | Pythonで配列をまとめて計算するライブラリ |
学生が入力するセルは、このプレビューでは空白です。
ループは1つずつ、ベクトル演算は全体に
5つの値段に送料の50円を足すとき、ループは足し算を5回書きます。ベクトル化なら、「配列に50を足す」と1回書くだけです。
計算そのものの数は同じです。変わるのは、Pythonが1つずつ命令を読む回数です。1回の命令が、速い機械語のコードで配列全体を処理します。
ループで1つずつ足す
# 全部の値段に、送料の50円を足します。
prices = [120, 300, 80, 450, 60]
operations = 0
totals = []
for price in prices:
totals.append(price + 50)
operations = operations + 1
print(totals)
print("足し算を書いた回数:", operations)
# prices に値段を1つ増やして、回数がどう変わるか見ましょう。
2つの配列は、同じ位置どうしで計算する
値段の配列と個数の配列を掛けると、同じ位置どうしが掛かります。これが要素ごとの演算です。
掛けた結果を全部足すと、売上の合計になります。この「掛けて足す」を内積と呼びます。機械学習でも、画像処理でも、何度も出てきます。
値段と個数から、売上を出す
| 商品 | 値段 | 個数 | 値段 × 個数 |
|---|---|---|---|
| ノート | 120円 | 3 | 360円 |
| リュック | 300円 | 2 | 600円 |
| 消しゴム | 80円 | 10 | 800円 |
| 合計 (内積) | 1760円 |
学生が入力するセルは、このプレビューでは空白です。
位置どうしを掛けて足す
# 値段と個数の、同じ位置どうしを掛けて、売上を出します。
prices = [120, 300, 80]
quantities = [3, 2, 10]
sales = []
for i in range(len(prices)):
sales.append(prices[i] * quantities[i])
print(sales)
print("売上の合計:", sum(sales), "円")
# quantities の最後を 10 から 5 に変えると、合計はいくらでしょうか。
NumPyなら1行で書ける (例)
import numpy as np
prices = np.array([120, 300, 80])
quantities = np.array([3, 2, 10])
print(prices + 50) # 全部に50を足す: [170 350 130]
print(prices * quantities) # 同じ位置どうしを掛ける: [360 600 800]
print(np.dot(prices, quantities)) # 掛けて全部足す (内積): 1760
よくある間違い
注意
ベクトル化すると、足し算の数が減ると思いがちです。1000個なら、足し算は1000回のままです。減るのは、Pythonから命令を出す回数です。計算を速い部分へまとめて任せるので、速くなります。
ラボの端末で、2通りの計算を比べる
ラボにGPUはありません。ふつうのPythonとNumPyで、同じ計算を2通りで出します。スクリプトは、英語の単語を出力します。
python loop result はループの答え、one numpy operation result はNumPyの答えです。答えは同じで、Pythonが操作した回数だけが違います。時間は測りません。
ループとNumPyを比べる
docker exec jupyter python3 steps/vectors.pyここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
売上を1行で出す
docker exec jupyter python3 -c "import numpy as np; print(np.array([120, 300, 80]) * np.array([3, 2, 10]))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
さらに挑戦: 数を数える
1から1000までの2乗を足すのに、ループは掛け算と足し算の2000回の操作を書きます。NumPyは1回です。
1万個なら、ループは何回の操作になるでしょうか。自分の言葉で説明しましょう。