社内se × プログラマ × ビッグデータ

プログラミングなどITに興味があります。

ユーザー類似度の計算(協調フィルタリングの前段階) python

今回は Mario さん、Peach さん、Koopa さんに5つのゲームを遊んでもらい、それぞれに5段階点数で評価をつけてもらいました。
※登場人物はフィクションです
その結果が以下です。
data.py

review={
 'Mario': {
 'OCTOPATH TRAVELER': 3.5, 'MARIO TENNIS ACE': 3.0, 'Splatoon2': 2.5, 'Legend of Zelda: Breath of the Wild': 3.5, 'Xenoblade 2': 2.5
  },
 'Peach': {
 'OCTOPATH TRAVELER': 1.5, 'MARIO TENNIS ACE': 3.5, 'Splatoon2': 5.0, 'Legend of Zelda: Breath of the Wild': 5.0, 'Xenoblade 2': 3.0
  },
 'Koopa': {
 'OCTOPATH TRAVELER': 3.0, 'MARIO TENNIS ACE': 3.5, 'Splatoon2': 3.5, 'Legend of Zelda: Breath of the Wild': 4.0, 'Xenoblade 2': 3.5
  }
}

この結果から、これらの3人が”どの位似ている”のかを求めていきます。
いわゆる 協調フィルタリングと呼ばれるものに使われたりするものです。
何らかの評価データから、ユーザー同士の類似度を計算し、似ているユーザーが好むものは、そのユーザーにも好まれやすいという仮説の元、レコメンデーションに使われたりします。

ここでは、ユーザー同士の類似度を以下で計算しました。
user-similarity.py

import sys
from math import sqrt
from data import review

def calc_similarity(member1, member2):
  games = set(review[member1].keys())
  distance_list = []

  for game in games:
    distance = pow(review[member1][game] - review[member2][game], 2)   <- (1)
    distance_list.append(distance)

  print "similarity of " + member1 + " and " + member2
  print 1/(1 + sqrt(sum(distance_list)))  <- (2)

if __name__ == '__main__':
  args = sys.argv
  calc_similarity(args[1], args[2])

1. それぞれの評価(点数)の差を2乗したものを”距離”とし、それぞれの評価が以下に離れているかを数字で表します。
2乗にしているのは、あくまでその距離を絶対値として評価するためですね。

2. それぞれのゲームに対する”距離”の和を求めてから、その平行根を求めています。
※sqrt(sum(distance_list))の部分
この値が大きいほど、”距離が離れている”= "類似していない" ということになります。
そのため、”類似している” 度合いを取るために、その逆数を取る(1から割る)ようにしています。

ちなみに 1 + sqrt(sum(distance_list)) のようにに +1 していますが、もし距離がゼロの場合、sqrt(sum(distance_list)) が 0 になります。
よって、1 / 1 + sqrt(sum(distance_list)) = 1/1 という計算式になり、類似度が"1" という結果になります。
これが完全に一致している状態です。

では、それぞれの類似度をみていきます。

$ python user-similarity.py Mario Peach
similarity of Mario and Peach
0.217129272955

$ python user-similarity.py Mario Koopa
similarity of Mario and Koopa
0.37617851153

$ python user-similarity.py Peach Koopa
similarity of Peach and Koopa
0.294298055086

ということで、Mario さんと Koopa さんが似た趣向を持っていて、Mario さんと Peach さんがあまり似ていないという結果になりました。
確かに、Mario さんと Koopa さんでは、最大で 1.0 しか評価の差はありませんが、Mario さんと Peach さんでは 2.5 の差がある評価もありました。

もし Koopa さんに何かレコメンドしたいのであれば、Mario さんが好んでいるものをレコメンドすれば、刺さりやすいだろうということになります。

何らかのデータを元に仮説を立てるという作業は面白いと思います。
あとは、それを実際に検証が出来ると良いのですが。