読者です 読者をやめる 読者になる 読者になる

pythonによる強調フィルタリング手法GroupLensの実装

レコメンドシステム構築の為、まずは定番のGroupLensの実装を行った。

python(crab)でもR(recommenderlab)でもライブラリはあるようだが、
さして複雑なアルゴリズムではないので、使いこなすより実装した方が早いと判断し、
pythonによる実装を試みた。

アルゴリズムは参考1のP50-56を利用している。
例題も同著の以下のデータを利用。

f:id:Tug-uca:20150517162841j:plain

# -*- coding: utf-8 -*-
import numpy as np

def pearson(e1,e2):
    #入力されたリストのうち、どちらともゼロでない要素のみの相関係数を算出
    te1=[]
    te2=[]
    tmp=np.array(e1)*np.array(e2)
    for i in range(len(tmp)):
        if tmp[i]!=0:
            te1.append(e1[i])
            te2.append(e2[i])
    if len(te1)==1:
        return 0
    return np.corrcoef(te1,te2)[0,1]

def average(e):
    #入力されたリストのうち、ゼロでない要素のみの平均を算出
    n = sum(e)
    d = len([x for x in e if x!=0])
    return n/d

def evaluate(a,y,data,arr):
    #評価推定値を算出
    aveA = average(data[a])
    d=0
    n=0
    for i in range(len(data)):
        if a!=i and data[i][y]!=0:#a自身と、yの評価値がないユーザを除く
            d+=abs(arr[a][i])
            # tmp=np.array(data[a])*np.array(data[i])
            # tmp2 = [0 for i in range(len(data[i]))]
            # for k in range(len(tmp)):
            #     if tmp[k]!=0:
            #         tmp2[k]=data[i][k]
            # n+=arr[a][i]*(data[i][y]-average(tmp2))
            
            #共通要素以外も含めた平均を利用、上部コメントアウト部分は共通要素を除いた平均を利用した場合
            n+=arr[a][i]*(data[i][y]-average(data[i]))
    return aveA+n/d


data = [[0 for i in range(4)] for j in range(4)]
arr = [[0 for i in range(4)] for j in range(4)]
eva = [[0 for i in range(4)] for j in range(4)]

# データの入力
data[0]= [1,3,0,3]
data[1]= [0,1,3,0]
data[2]= [2,1,3,1]
data[3]= [1,3,2,0]




# ユーザー間の類似度計算
for key in range(len(data)):
    base_customers = data[key]
    for key2 in range(len(data)):
        if key == key2:
            continue
        target_customers = data[key2]
        j = pearson(base_customers, target_customers)
        arr[key][key2] = j

#ユーザ・商品ごとの評価値推定
for i in range(len(data)):
    for j in range(len(data[i])):
        eva[i][j] = evaluate(i,j,data,arr)

# ユーザー間の類似度
print(' \t  1 \t  2 \t  3 \t  4 ')
print('1\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(arr[0][0], arr[0][1], arr[0][2], arr[0][3]))
print('2\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(arr[1][0], arr[1][1], arr[1][2], arr[1][3]))
print('3\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(arr[2][0], arr[2][1], arr[2][2], arr[2][3]))
print('4\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(arr[3][0], arr[3][1], arr[3][2], arr[3][3]))

#ユーザ・商品ごとの評価値推定値
print(' \t  1 \t  2 \t  3 \t  4 ')
print('1\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(eva[0][0], eva[0][1], eva[0][2], eva[0][3]))
print('2\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(eva[1][0], eva[1][1], eva[1][2], eva[1][3]))
print('3\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(eva[2][0], eva[2][1], eva[2][2], eva[2][3]))
print('4\t{0:2.2f}\t{1:2.2f}\t{2:2.2f}\t{3:2.2f}'.format(eva[3][0], eva[3][1], eva[3][2], eva[3][3]))

  • 実行結果
 	  1 	  2 	  3 	  4 
1	0.00	0.00	-1.00	1.00
2	0.00	0.00	1.00	-1.00
3	-1.00	1.00	0.00	-0.50
4	1.00	-1.00	-0.50	0.00
 	  1 	  2 	  3 	  4 
1	1.71	3.21	1.71	3.08
2	2.62	1.12	2.62	1.25
3	2.97	0.88	2.42	1.08
4	1.03	2.82	0.92	2.69

以上。



参考1:推薦システムのアルゴリズム
www.kamishima.net/archive/recsysdoc.pdf