【Pythonで学ぶ線形代数学講座(3)】ベクトルの内積
今回はベクトル同士の掛け算について学びます。ベクトルの掛け算には、内積と外積の2種類がありますが、今回は内積について考えます。内積の計算方法は特に難しくありませんが、「ベクトルの向きを揃えて掛ける」と考えるとイメージしやすいかと思います。機械学習の分野で頻繁に登場する概念なので、定義と実装方法についてマスターしておきましょう。外積については少し先の講座[09]で解説します。
内積の定義と性質
ベクトルの 内積 (inner product) は要素同士の積の総和として定義されます。
たとえば、
のように計算できます。3 次元以上も同様で、一般に
と定義されます。ベクトル
すなわち、ベクトル
のように表せます。
内積演算においては、交換法則、結合法則、分配法則が成り立ちます。
もう少し先の記事で行列について学ぶことになりますが、ベクトル
行列表記と整合性がとれるので、講座の後半では行ベクトルによる表記が増えると思います。行ベクトルを
numpy.dot()
numpy.dot(a, b) は行列積を計算する関数です。a, b に 1 次元配列(ベクトル)をわたせば内積を返します (1 列の行列同士の積はベクトルの内積と同じです)。
# numpy_inner_product_1
# In[1]
import numpy as np
# ベクトルv=[3 2 6]
v = np.array([3, 2, 6])
# ベクトルw=[4 7 2]
w = np.array([4, 7, 2])
# vとwの内積を計算
ip = np.dot(v, w)
print(ip)
# 38
ndarray.dot()
配列 (ndarrayオブジェクト) には内積を計算する dot() メソッドがあります。
# In[2]
# ベクトルv=[3 2 6]
v = np.array([3, 2, 6])
# ベクトルw=[4 7 2]
w = np.array([4, 7, 2])
# vとwの内積を計算
ip = v.dot(w)
print(ip)
# 38
numpy.vdot()
numpy.vdot(a, b) にベクトル(1 次元配列)を渡して内積を計算できます。
# numpy_inner_product_2
# In[1]
import numpy as np
# ベクトルv=[7+2i 3+i]
v = np.array([7 + 2j, 3 + 1j])
# ベクトルw=[4+5i 8]
w = np.array([4 + 5j, 8])
# vとwの内積を計算
ip = np.dot(v, w)
print(ip)
# 42+51j
numpy.vdot() の引数 a, b に 2 次元以上の配列を渡すと、1 次元配列に平坦化してから内積を計算します(テンソル複内積)。
# In[2]
# 行列a
a = np.array([[1, 4],
[3, 5]])
# 行列b
b = np.array([[3, 7],
[4, 9]])
# 1*3+4*7+3*4+5*9
ip = np.vdot(a, b)
print(ip)
# 88
numpy.inner()
numpy.inner(a, b) にベクトル (1 次元配列) を渡して内積を計算することができます。
# numpy_inner_product_3
# In[1]
import numpy as np
# ベクトルv=[2 5 0]
v = np.array([2, 5, 0])
# ベクトルw=[3 1 4]
w = np.array([3, 1, 4])
# vとwの内積を計算
ip = np.inner(v, w)
print(ip)
# 11
引数 a, b に行列を渡すと、a と b.T の行列積を返します (b.T は b の転置行列)。すなわち、np.dot(a, b.T) と同じ結果を返します。
内積の幾何学的意味
ベクトル
と表されます。この定義は (1) と同値であり(余弦定理を使って証明できます)、幾何学的には下図のように
2 つのベクトルのなす角度が直角であるとき、射影がなくなるので内積は
たとえば、
また、式 (10) より、ベクトル
となるので、
によって角度を計算できます。4 次元以上のベクトルのなす角度も(想像するのは難しいですが)、(12) で定義できます。Python で角度を求める関数を実装してみましょう。
# python_vector_angle
# In[1]
import numpy as np
# 2つのベクトルのなす角度を求める関数
def v_angle(v1, v2, deg = False):
# v1とv2の大きさ(ノルム)を計算
v1_n = np.linalg.norm(v1)
v2_n = np.linalg.norm(v2)
# v1とv2の内積を計算
v1_dot_v2 = np.dot(v1, v2)
# 角度の余弦を計算
cos_theta = v1_dot_v2 / (v1_n * v2_n)
# 逆三角関数を使って角度を計算
theta = np.arccos(cos_theta)
# 引数degがTrueならば、角度を度数単位(degree)に変換
if deg == True:
theta = np.degrees(theta)
return theta
deg は結果を度数法単位 (deg) とラジアン (rad) のどちらで返すか決定するオプション引数です。デフォルトでは False に設定されているので、この引数を省略するとラジアンで返してきます。
v_angle() を使って、
deg は True に設定して結果を度数単位で返すようにします。
# In[2]
# ベクトルを定義
v = np.array([1, 0])
w = np.array([1, np.sqrt(3)])
# vとwの間の角度を計算
theta = v_angle(v, w, deg = True)
print("θ = {:.3f}".format(theta))
# θ = 60.000
世界標準MIT教科書|ストラング:線形代数とデータサイエンス ● 新品価格 | ![]() |

≫ Pythonで学ぶ線形代数トップページ
コメント
下記は誤植と思われますので、ご確認ください。
式(11)の上の文章で、式(6)より → 式(10)より
式(12)の下の文章で、(2)で定義 → (12)で定義
いつもありがとうございますm(_ _)m
記事を訂正させていただきました。