協調フィルタリング

協調フィルタリングとは、大規模な人々の集団を検索し、好みが似た小集団を発見する。

Convergece Lab.の長谷部 尊則です。

今回は協調フィルタリングについて書きたいと思います。

協調フィルタリングのアルゴリズムは、大規模な人々の集団を検索し、好みが似た小集団を発見することで動作します。

協調フィルタリングでは、彼らが好きな他のものも見て、それらを組み合わせ、順序づけした推薦のリストを作成します。

今回、協調フィルタリングに用いるデータは以下のようになります。

import pandas as pd

# 映画の評者といくつかの映画に対する彼らの評点のディクショナリ
critics = {
			'Lisa Rose':{
						'Lady in the Water': 2.5, 
						'Snakes on a Plane': 3.5, 
						'Just My Luck': 3.0, 
						'Superman Returns': 3.5,
						'You, Me and Dupree': 2.5,
						'The Night Listener': 3.0
						},
			'Gene Seymour':{
						'Lady in the Water': 3.0,
						'Snakes on a Plane': 3.5,
						'Just My Luck': 1.5, 
						'Superman Returns': 5.0,
						'The Night Listener': 3.0,
						'You, Me and Dupree': 3.5
						},
			'Michael Phillips':{
						'Lady in the Water': 2.5,
						'Snakes on a Plane': 3.0,
						'Superman Returns': 3.5,
						'The Night Listener': 4.0
						},
			'Claudia Puig':{
						'Snakes on a Plane': 3.5, 
						'Just My Luck': 3.0, 
						'The Night Listener': 4.5, 
						'Superman Returns': 4.0, 
						'You, Me and Dupree': 2.5
						},
			'Mick LaSalle':{
						'Lady in the Water': 3.0,
						'Snakes on a Plane': 4.0,
						'Just My Luck': 2.0, 
						'Superman Returns': 3.0,
						'The Night Listener': 3.0,
						'You, Me and Dupree': 2.0
						},
			'Jack Matthews':{
						'Lady in the Water': 3.0,
						'Snakes on a Plane': 4.0,
						'The Night Listener': 3.0,
						'Superman Returns': 5.0,
						'You, Me and Dupree': 3.5
						},
			'Toby':{
						'Snakes on a Plane': 4.5,
						'You, Me and Dupree': 1.0,
						'Superman Returns': 4.0
						}
			}
df = pd.DataFrame(critics)

データを集めたあとは、人々の好みの上でどの程度似ているかを決める方法が必要になります。

ここでは、スコアを計算するのに、ピアソンの相関係数を用います。

ピアソンの相関係数については以下のURLが詳しいです。

https://atarimae.biz/archives/7966

https://sci-pursuit.com/math/statistics/correlation-coefficient.html

それでは、ピアソンの相関係数を用いることにより、映画の好みが似ている評者を探し出すことをやってみましょう。

import numpy as np

for name in df.columns:
    result_dict = {}
    for name_compare in df.columns:
        x = df[name].values
        if name != name_compare:
            y = df[name_compare].values
            bad = ~np.logical_or(np.isnan(x), np.isnan(y))
            result_dict[name_compare] = np.corrcoef(np.compress(bad, x), np.compress(bad, y))[0][1]
    print(name)
    for i in sorted(result_dict.items(), key=lambda x: x[1], reverse = True)[0:3]:
        print(i)
    print('')

上記のコードを実行すると、下記のような実行結果が出ます。

Lisa Rose
('Toby', 0.9912407071619304)
('Jack Matthews', 0.747017880833996)
('Mick LaSalle', 0.5940885257860047)

Gene Seymour
('Jack Matthews', 0.963795681875633)
('Mick LaSalle', 0.411764705882353)
('Lisa Rose', 0.3960590171906697)

Michael Phillips
('Claudia Puig', 1.0)
('Lisa Rose', 0.40451991747794525)
('Gene Seymour', 0.20459830184114206)

Claudia Puig
('Michael Phillips', 1.0)
('Toby', 0.8934051474415642)
('Lisa Rose', 0.5669467095138409)

Mick LaSalle
('Toby', 0.924473451641905)
('Lisa Rose', 0.5940885257860046)
('Claudia Puig', 0.5669467095138409)

Jack Matthews
('Gene Seymour', 0.9637956818756331)
('Lisa Rose', 0.747017880833996)
('Toby', 0.6628489803598703)

Toby
('Lisa Rose', 0.9912407071619304)
('Mick LaSalle', 0.924473451641905)
('Claudia Puig', 0.8934051474415642)

協調フィルタリングにより、Lisa Roseさんに似ている評者は、

Tobyさん、Jack Matthewsさん、Mick LaSalleさんとなります。

他の人も同様に協調フィルタリングにより、似ている評者がスコア付けされています。

これはユーザーベースの協調フィルタリングです。

アイテムベースの協調フィルタリングは評点を利用して、アイテムの(ここでは映画の)類似度を算出します。

以上で、協調フィルタリングの説明を終わりにします。

ドキュメントアクション