Numpy基本操作とcos類似度の実装

Numpy基本操作とcos類似度の実装

機械学習の勉強にはまっているのですが、最近なんとなく使っていたnumpyを、少しだけしっかり勉強しなおそうと思って、確認していきます。

1つの課題として、2つのベクトルのcos類似度を出すところまでをやっていこうと思います。

cos類似度とは

そもそもコサイン類似度とは何かというと、

ベクトル間の角度を求めることで、2つのベクトルの類似度を示したもののこと。

コサインの内積は、高校数学で学習したときは、それぞれの絶対値の積に、2つのベクトルの間の角度のコサイン成分をかけたものでした。

一応、高校数学の美しい物語に、コサイン類似度の記載があったので、乗っけておきます。

式を覚える必要はないと書いてあったので、省略しますが、これはたびたび機械学習で使用されるそうです。

機械学習はデータを扱いやすいように、ベクトル化することが多くて、それらのデータの類似度を見たいときに、コサイン類似度を用います。

データのベクトル化は、またいつか記事にします。

numpy配列の定義

numpy配列は、すべて、np.array()で定義します

例えば2行3列の行列を定義するときは

np.array([[1,2,3],
          [4,5,6]])

のように定義します

ブロードキャスト

pythonは本来、list型とint型の演算は型が違うからできないんですけど、numpyを使うと、配列内のすべての要素に対して演算ができて

この機能のことをブロードキャストといいます

ポイントはnumpy配列を使うという点で

np.array([1,2,3]) + 3

と打ち込むと、array([4,5,6])という形で返ってきます。

配列の内積

配列の内積はdot関数を使います。

使い方はこんな感じ

b = np.array([1,2])
c = np.array([3,4])
np.dot(b,c)

これは11という値を返します。

配列の合計

配列の合計は、sum()関数を使います。

cos類似度実装

いくつか計算ができるようになったところで、コサイン類似度を計算していこうと思います。

前提として、以下の知識を使います。

なので、この式をpythonで実装していくことになります。

計算の要素を1つ1つ丁寧に分解してやっていきます

  1. ベクトルの定義
  2. 分子の計算(内積計算のみ)
  3. 分母の計算
  4. ベクトルaの2乗の総和を求める
  5. 上の総和の平方根を取り、aの絶対値を取得
  6. ベクトルbも同じことをする
  7. 2つのベクトルの絶対値の積を取得
  8. 分母を分子で割って有効数字計算
  9. 出力しておしまい

具体的に見ていきます。

ベクトルの定義

import numpy as np
a = np.array([2, 1])
b = np.array([1, 3])

分子の計算(内積計算のみ)

num = np.dot(a,b)

内積計算はこれでおしまいです

分母の計算

まず最初に、ベクトルaの要素を2乗します

a_sq = a ** 2

2乗の演算子は ** です

ベクトルaの2乗の総和を求める

a_sum = sum(a_sq)

総和はsum()関数を使えばよかったです

上の総和の平方根を取り、aの絶対値を取得

a_root = np.sqrt(a_sum)

ベクトルbも同じことをする

b_sq = b ** 2
b_sum = sum(b_sq)
b_root = np.sqrt(b_sum)
den = a_root * b_root

2つのベクトルの絶対値の積を取得

den = a_root * b_root

分母を分子で割って有効数字計算

cos_similaarity = num / den
ans = cos_simirality.round(2)

出力しておしまい

print(ans)

これを実装すると、値が0.71で返ってきます。

最後に今日書いたコードをまとめて終わります。

# cos類似度を計算

import numpy as np

a = np.array([2, 1])
b = np.array([1, 3])

# 2つのベクトルの内積を計算
num = np.dot(a,b)

# まずはベクトルaの絶対値を計算
a_sq = a ** 2

# 要素が2乗されたベクトルaの要素の和
a_sum = sum(a_sq)

# 上で得られた値の平方根をとり、ベクトルaの絶対値を取得
a_root = np.sqrt(a_sum)

# 同様の操作をベクトルbにも行う
b_sq = b ** 2
b_sum = sum(b_sq)
b_root = np.sqrt(b_sum)
den = a_root * b_root

# 分子を分母で割ってcos類似度を求める
cos_simirality = num / den

# 少数第三位を四捨五入
ans = cos_simirality.round(2)

# 計算したcos類似度を出力
print(ans)