numpyでコサイン類似度を計算する

コサイン類似度は以下の式で計算できる。 {} $$ \begin{align} \cos{ (\boldsymbol{a}, \boldsymbol{b} ) } &= \frac{\boldsymbol{a} \cdot \boldsymbol{b}}{|\boldsymbol{a}| |\boldsymbol{b}|} \\ &= \frac{\boldsymbol{a} \cdot \boldsymbol{b}}{\sqrt{\sum^{n} a_{i}} \cdot \sqrt{\sum^{n} b_{i}}} \end{align} $$

コサイン類似度は,ベクトル同士の角度の近さが表現されるため, 1に近いほど類似度が高く,0に近ければ類似度が低いこととなる.

このコサイン類似度を求めるために、 {a, b}のノルムを毎回計算するのはコストが大きいので、 予め{a, b}を正規化しておけば以下のように計算できる。 {} $$ \begin{align} \cos{ (\boldsymbol{a}, \boldsymbol{b} ) } &= \boldsymbol{a} \cdot \boldsymbol{b} \\ &= \sum^{n} a_{i}b_{i} \end{align} $$

コードで書くと例えば, ベクトルの集合{\boldsymbol{X}}が与えられた際に, 各ベクトルをnumpy.linalg.normで計算したノルムで割る.

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

そしてコサイン類似度を計算したいベクトル同士で内積をとればよい.

print(np.dot(X[0], X[1]))