Pythonによるベクトルのノルムの計算

Pythonでベクトルのノルム(大きさ)を計算します。まず、計算の流れを知るためリストによる計算からはじめ、次にNumPyモジュールによる計算を考えます。ノルムの計算では最後に平方根を使うので、すっきり整数になることはむしろ稀です。この場合、SymPyモジュールを使うと、ルートによる表示も少数表示も可能となるので非常に扱いやすくなります。

ベクトルの定義とノルムの計算

リストによる定義と計算

forループによるノルムの計算

すっきりと整数となるケースとして、ベクトルv_a=(2, 4, 4)のノルムから計算します。

ベクトルのノルムの計算
  1. import math
  2. v_a =[2, 4, 4]
  3. norm_a = 0
  4. for i in v_a:
  5. norm_a += i**2
  6. math.sqrt(norm_a)

1. 平方根を計算するため、2行目でmathモジュールをインポートします。
4. forループで、ベクトルの各要素をiとして取り出します。
5. norm_aに対し、各要素の二乗を計算して足しこんでいきます。
計算式は$\sqrt{2^2+4^2+4^2}=\sqrt{36}$となり6ときれいに整数になります。
ベクトルのノルムの計算
n次元ベクトル\vec{x} = (x_1, x_2, \cdots ,x_n)に対して$
|\vec{x}|=\sqrt{|x_1|^2 + |x_2|^2 + \cdots + |x_n|^2}としたとき、|\vec{x}|を\vec{x}のノルムという。$

リスト内包表記によるノルムの計算

リスト内包表記によりベクトルのノルムを計算します。

スト内包表記によるノルムの計算
  1. import math
  2. math.sqrt(sum([i**2 for i in v_a]))

lambda式によるノルムの計算

また、lambda式を使うと次の通りになります。

lambda式によるノルムの計算
  1. import math
  2. math.sqrt(sum(map(lambda i: i**2, v_a)))

いずれも、変数が1つなので簡単な式で計算することができます。

NumPyによるノルムの計算

Numpyで定義に従ってノルムを計算する

NumPyモジュールではベクトル演算を使うと、各要素を2乗してsum関数で合計することにより簡単に計算することができます。平方根の計算もNumPyモジュールに関数が用意されています。

NumPyによるノルムの計算
  1. import numpy as np
  2. n_a = np.array([2, 4, 4])
  3. np.sqrt(sum(n_a**2))

結果は同じく6となります。

NumPyのnorm関数によるノルムの計算

関数を使うと、簡単にノルムを計算することができます。NumPyにはlinalg (Linear algebra)という線形代数を扱うサブモジュールがあり、その中のnorm関数を使うことによりノルムを計算することができます。norm関数に求めたいベクトルを代入するだけで、計算は完了です。

Numpyのnorm関数によるノルムの計算
  1. np.linalg.norm(n_a)
  2. np.linalg.norm(n_a, ord=2)

これまでの計算は、ベクトルの各成分を2乗したものを合計したものの平方根を計算したL2ノルムというものでした。これに対し、L1ノルム(各要素の絶対値の合計)やL3ノルム(各要素を3乗して合計した値の3乗根)として計算する場合もあります。ノルムの概念を広げると次のように定義することができます。

ベクトルのノルムの計算
n次元ベクトル\vec{x} = (x_1, x_2, \cdots ,x_n)および1 ≤ p ≤ \inftyというpに対して$
|\vec{x}|_p=\sqrt[p]{|x_1|^p + |x_2|^p + \cdots + |x_n|^p}を\vec{x}としたとき、|\vec{x}|_pをL^pノルムという。$

このため、ord=2というように、L2ノルムであることを明示する方がより確実になります。結果はいずれも6になります。

SymPyによるノルムの計算

SymPyによる数値によるノルムの計算

SymPyモジュールでは1列のMatrixとしてベクトルを定義し、normメソッドで計算します。ordを省略するとL2ノルムで計算されますが、ここではあえてord=2と明示することにします。次のように変数を定義し、normメソッドを適用することで、ノルムの代数による計算結果を得ることができます。NumPyはnorm関数として引数にベクトルを指定しますが、SymPyではnormメソッドになります。

Sympyのnorm関数によるノルムの計算
  1. import sympy
  2. s_a = sympy.Matrix([2,4,4])

s_a.norm(ord=2)結果は同様に6となります。SymPyモジュールを使うメリットは代数計算ができることです。

SymPyでの代数によるノルムの計算

SymPyでは代数計算によりノルムを計算することができます。

SymPyでの代数によるノルムの計算
  1. import sympy
  2. sympy.var('a_x:z')
  3. s_a=sympy.Matrix([a_x,a_y,a_z])
  4. s_c=s_a.norm(ord=2)
  5. s_c

ここでは計算結果がs_cに格納され、次のように表示されます。

SymPyにノルムの代数計算

最後にs_cに、subsメソッドで数値を代入します

平方根をSympyにより計算した場合
  1. sn_n = s_c.subs({a_x:2,a_y:4,a_z:4})
  2. sn_n

結果はやはり6になります。

割り切れない場合のノルムの計算

これまではノルムがすっきりと整数になる例を取り扱ってきましたが、ベクトル[1, 4, 1]のように割り切れないケースを考えます。

NumPyにより割り切れない場合のノルムの計算

NumPyのndarrayで定義したベクトルに対しノルムを計算します。

$norm=\sqrt{1^2+4^2+1^2}=3\sqrt{2}$

平方根を計算した結果が割り切れない場合
  1. n_b = np.array([1, 4, 1])
  2. np.sqrt(sum(n_b**2))

4.242640687119285

小数点以下が延々と続くことになり扱いづらくなります。このような場合にSymPyが本領を発揮します。

SymPyの関数による外積の計算

SymPyによる外積の計算

SymPyでノルムの計算をします。はじめに、SymPy.Matrixでベクトルを定義し、normメソッドでノルムを計算することができます。

平方根を計算した結果が割り切れない場合
  1. import sympy
  2. s_b = sympy.Matrix([1,4,1])
  3. s_b.norm(ord=2)
Sympyにノルムの代数計算

今回はすっきりと割り切れませんが、ルート表示で結果を得ることができます。同様に、前に求めた代数による結果に数値を代入しても同様です。

平方根をSymPyにより計算した場合
  1. sn_n = s_c.subs({a_x:1,a_y:4,a_z:1})
  2. sn_n

Sympyにノルムの代数計算

最後に、ルート表示した結果を小数点で表示する場合にはpythonの組み込み関数であるfloat関数を使います。また、小数点の表示を限定したい場合は、round関数かSymPyモジュールのN関数を使います。N関数では小数点以下の桁数を指定することができます。

SymPyで計算した結果を小数点表示に転換
  1. print('float関数による表示',float(sn_n))
  2. print('round関数による表示',round(sn_n,3))
  3. print('N関数で小数点第3位まで表示:',sympy.N(sn_n,4))

print('float関数による表示',float(sn_n))
print('round関数による表示',round(sn_n,3))
print('N関数で小数点第3位まで表示:',sympy.N(sn_n,4))

float関数では#9のNumPyと同じ表示になります。round関数は表示したい小数テイン以下の桁数である3を指定します。N関数では2つ目の引数で四捨五入をする桁数を指定します。このケースでは小数点第4位を四捨五入し、小数点第3位まで表示されます。