ドット積は向きの一致を測る
ドット積とは、2つのベクトルの同じ位置の成分を掛けて、全部足した数です。この1つの数から、2つのベクトルがどれだけ同じ向きを向いているかが分かります。
映画の好みを点数のベクトルにすると、好みの似た人を探せます。おすすめの機能は、この考え方を使います。
このレッスンのゴール
メモ
ドット積を使って、2つのベクトルがどれだけ同じ向きかを言うことができる。
キーワード
| ことば | いみ |
|---|---|
| ドット積 | 同じ位置の成分を掛けて、全部足した数。内積ともいう |
| 向き | ベクトルが指している方向。長さとは別 |
| 直交 | 2つのベクトルが直角で、ドット積が 0 になること |
| コサイン類似度 | 向きの近さを、-1 から 1 の数で表したもの |
学生が入力するセルは、このプレビューでは空白です。
ドット積は掛けて足すだけ
2つのベクトルの同じ位置の成分を掛け、その合計を取ります。結果は、ベクトルではなく、ふつうの1つの数です。
同じ向きを向くと大きなプラスの数になり、直角だと 0、反対向きだとマイナスの数になります。
例: 3組のドット積
| a | b | 計算 | ドット積 |
|---|---|---|---|
| [2, 3] | [4, 1] | 2 × 4 + 3 × 1 | 11 |
| [1, 0] | [0, 1] | 1 × 0 + 0 × 1 | 0 |
| [2, 2] | [2, -2] | 2 × 2 + 2 × (-2) | 0 |
| [1, 2] | [-1, -2] | 1 × (-1) + 2 × (-2) | -5 |
学生が入力するセルは、このプレビューでは空白です。
ドット積を計算する
# 3つのジャンルで、2人が付けた点数です。
hina = [5, 1, 0]
ren = [4, 2, 0]
total = 0
for i in range(len(hina)):
total = total + hina[i] * ren[i]
print("ドット積:", total)
# ren の最後を 0 から 5 に変えて、ドット積を予想してから実行してください。
NumPy でドット積を求める
docker exec jupyter python3 -c "import numpy as np; a = np.array([2, 3]); b = np.array([4, 1]); print(np.dot(a, b), a @ b)"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
コサイン類似度は向きだけを比べる
ドット積は、ベクトルが長いほど大きくなります。向きだけを比べたいので、2つの長さの積で割ります。これがコサイン類似度です。
同じ向きなら 1、直角なら 0、反対向きなら -1 になります。長さが違っても、向きが同じなら 1 です。
例: コサイン類似度の値
| a | b | ドット積 ÷ 長さの積 | 結果 |
|---|---|---|---|
| [3, 4] | [4, 3] | 24 ÷ (5 × 5) | 0.96 |
| [1, 2] | [2, 4] | 10 ÷ (√5 × √20) | 1 |
| [1, 0] | [0, 1] | 0 ÷ (1 × 1) | 0 |
| [1, 0] | [-1, 0] | -1 ÷ (1 × 1) | -1 |
学生が入力するセルは、このプレビューでは空白です。
よくある間違い
注意
多くの人は、ドット積が大きいほど、2つが似ていると考えます。長いベクトルは、向きが違っても大きくなります。向きの近さは、長さで割ったコサイン類似度で比べます。
好みの近い人を探す
3人が、アクション、コメディ、恋愛の3つに0から5の点数を付けました。ひなたは [5, 1, 0]、蓮は [4, 2, 0]、葵は [0, 1, 5] です。
ひなたと蓮のコサイン類似度は約 0.96、ひなたと葵は約 0.04 です。ひなたには、蓮の好みが近いと分かります。
コサイン類似度を計算する
# ドット積を、2つの長さの積で割ると、向きの近さになります。
a = [3, 4]
b = [4, 3]
dot = a[0] * b[0] + a[1] * b[1]
length_a = (a[0] ** 2 + a[1] ** 2) ** 0.5
length_b = (b[0] ** 2 + b[1] ** 2) ** 0.5
print("ドット積:", dot)
print("コサイン類似度:", dot / (length_a * length_b))
# b を [6, 8] に変えて、結果が変わるかどうか予想してください。
3人の好みの近さを求める
docker exec jupyter python3 -c "import numpy as np; hina = np.array([5, 1, 0]); ren = np.array([4, 2, 0]); aoi = np.array([0, 1, 5]); n = np.linalg.norm; print(round(hina @ ren / (n(hina) * n(ren)), 2), round(hina @ aoi / (n(hina) * n(aoi)), 2))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
さらに挑戦: 単位をそろえる
前回の1日のベクトル [気温, 雨量, 貸出台数] は、台数の数字が大きすぎました。それぞれの列を、その列の最大の値で割ると、どの成分も 0 から 1 になります。
こうして単位をそろえてから、ドット積で、よく似た2日を探してみましょう。