python(numpy)でL2ノルムが1になるようにする

コサイン類似度は以下で求まる.

\( cos(\vec{a}, \vec{b}) = \frac{\vec{a} \cdot \vec{b}}{ \sqrt{\sum^{n}a_i} \sqrt{\sum^{n}b_i}} \)

ここでコサイン類似度を求めるのに、毎度ベクトルのノルム(\( \sqrt{\sum^{n}a_i} \sqrt{\sum^{n}b_i}\) )を求めるのは効率が悪い. そこで予めこれが1になるようにする(→内積=コサイン類似度になる)

ベクトルのリスト \( X = (\vec{x_1}, \vec{x_2}, ..., \vec{x_n}) \) について,各々のベクトルを正規化する.numpyのlinalg.normを利用するとベクトルの長さ(ノルム)を求めることができるので、それを利用する.

import numpy as np

norm = np.linalg.norm(X, ord=2, axis=1)
X = X / norm[:np.newaxis]

np.linalg.normについて、キーワード引数ordでノルムの次元数を指定、axisでどの次元方向に和を取るかを指定できる.

  • axis=0とすれば,各列の二乗和の平方根をとった(行)ベクトルが出力される.
  • axis=1とすれば,各行の二乗和の平方根をとった(列)ベクトルが出力される.

Xをnorm[:np.newaxis]で割って終了.

なおここでnorm(横ベクトル)を縦ベクトルに転置している. 元の配列の大きさを維持する次元には":"を指定し,新たに大きさが 1 の次元を追加するところには np.newaxis を指定している.