NumPy の np.linalg.norm( )
によってベクトルの \(L_1\) ノルムや \(L_2\) ノルムを求めることができます.例えばベクトル \(x\) を次のように定義します.
import numpy as np
x = np.array([-2, -2])
print(x)
[-2 -2]
ベクトル \(x\) の \(L_1\) ノルムを求めると 4 になります.なお,引数の ord
は Order(次数)を意味します.
np.linalg.norm(x,ord=1)
4.0
ベクトル \(x\) の \(L_2\) ノルムを求めると 2.828 になります.
np.linalg.norm(x,ord=2)
2.8284271247461903
では \(L_1\) ノルムや \(L_2\) ノルムの具体的な意味を考えてみましょう.階層的クラスタリングに使用したデータをここでも使って説明します.まず,必要ライブラリをインポートします.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 高解像度ディスプレイのための設定
from IPython.display import set_matplotlib_formats
# from matplotlib_inline.backend_inline import set_matplotlib_formats # バージョンによってはこちらを有効に
set_matplotlib_formats('retina')
次に,GitHubからサンプルデータをダウンロードして Pandas のデータフレームに格納します.
url = "https://github.com/rinsaka/sample-data-sets/blob/master/clustering-sample-small.csv?raw=true"
df = pd.read_csv(url)
print(df)
ID x y 0 A 1 2 1 B 1 6 2 C 3 4 3 D 7 4 4 E 11 4 5 F 9 6
サンプルデータは2次元データなので散布図を作成します.
fig, ax = plt.subplots(1, 1, figsize=(6, 6))
ax.scatter(df['x'], df['y'], alpha=0.8, label=f"data")
ax.set_title("data")
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_xlim(0, 12)
ax.set_ylim(0, 12)
ax.set_xticks(np.arange(0, 12 + 1, 1))
ax.set_yticks(np.arange(0, 12 + 1, 1))
ax.grid()
annotations = df['ID'].values
for i, label in enumerate(annotations):
plt.annotate(label, (df['x'][i], df['y'][i]))
plt.show()
上で求めた \(L_1\) ノルムはデータ「A」とデータ「C」のマンハッタン距離に相当します.また \(L_2\) ノルムはデータ「A」とデータ「C」のユークリッド距離に相当します.
実際にダウンロードしたデータを用いてデータ「A」とデータ「C」の\(L_1\) ノルム,\(L_2\) ノルムを求めてみます.まず「A」のデータをベクトルに格納します.
a = df[(df.index == 0)][['x', 'y']].values.reshape(2)
a
array([1, 2])
「C」についてもベクトルに格納します.
c = df[(df.index == 2)][['x', 'y']].values.reshape(2)
c
array([3, 4])
a - c
が上で定義したベクトル x
に等しくなります.
a - c
array([-2, -2])
\(L_1\) ノルムはマンハッタン距離を意味することがわかりました.
np.linalg.norm(a - c, ord=1)
4.0
\(L_2\) ノルムはユークリッド距離を意味することがわかりました.
np.linalg.norm(a - c, ord=2)
2.8284271247461903