あなたにオススメの〜的なサービスを実装する。

AmazonやFacebookに代表されるように、「あなたにオススメの〜」みたいなサービスを構築する方法について考えてみます。いわゆるレコメンド・サービスのためのアソシエーション解析の一環ですね。

まずは解析するデータを自動で作成するために、ExcelでVBAを書きます。

Sub setRnd()
  For i = 2 To 31
    For j = 2 To 17
      Worksheets("Sheet1").Cells(i, j).Value = Round(Rnd())
    Next
  Next
End Sub


作成したデータがこちら。
例えば(A1, a3)は1となっていますが、これはA1というユーザーがa3という商品を購入した。もしくは、A1というユーザーがa3と友達である。みたいな解釈をしてください。
0の場合は、繋がりが無いといった感じです。

f:id:u651601f:20131127194024p:plain


さて、このデータから、例えば「a2とa7は、よく購入される組み合わせだ!」みたいなことを数値的に解析してみましょう。


まずはこのデータをcvsファイルに変換し、pythonで解析できるようにします。

次に、この「生」のデータから、組み合わせ表を作成します。
とりあえずプログラムを見て行きましょう。

1. csvファイルを読み込む

import sys
import types

with open('Workbook1.csv', 'r') as csv:
	for line in csv:
		data = line.strip().split(",")

# fix csv to create data table
matrix = []
row = []
for l in data:
	try:
		num = int(l)
	except ValueError:
		matrix.append(row)
		row = []
	else:
		row.append(num)
del matrix[0]

私のcsvファイルはなぜか改行がなされていなかったので、行の先頭に顧客名があることを利用して、データをテーブルにフォーマットします。

2. 購入の関連性表を作成する

# create association table
fav_table = []
for i in range(len(matrix[0])):
	fav_row = []
	for j in range(len(matrix[0])):
		fav_row.append([])
		fav_row[j] = 0
		for k in range(len(matrix)):
			fav_row[j] += matrix[k][i] * matrix[k][j]	
	fav_table.append(fav_row)

先ほどの説明のように、ある商品と他の商品がどのくらいの頻度で組み合わせ購入されているかを調べます。
例えば1行目と3行目ではa1とa3の商品が、10行目と18行目ではa10とa18の商品がどれだけ同時購入されたかわかります。

3. レコメンド用のテーブルをファイルに書き込む

# calculate association rate from table
transposed = [[row[i] for row in fav_table] for i in range(len(matrix[0]))]
def add(x, y): return x + y
sum_table = [reduce(add, transposed[i]) for i in range(len(transposed))]

for i in range(len(fav_table)):
	for j in range(len(fav_table[0])):
		fav_table[i][j] /= float(sum_table[j])

#write association rate table to csv file
try:
	f = open("associated.csv", 'w')
	w = ''
	for i in range(len(fav_table[0])):
		w += "\n"
		for j in range(len(fav_table)):
			w += repr(fav_table[i][j]) + ', '
	f.write(w)
finally:

例えばa1と組み合わせて購入された履歴が200回あるとします。そのうちa2との組み合わせが150回なら、a1とa2との組み合わせ購入率は150/200 = 0.75となります。

このようにそれぞれの組み合わせ購入率を計算して、レコメンド用のテーブルを更新してファイルに書き込みます。



以上の結果、作成したデータはこんな感じになりました。

f:id:u651601f:20131202035310p:plain


ラベルが無いので見難いですが、たとえばA2のデータはa1とa2の商品が組み合わせて購入される確率が0.02とかなり低く、あまりこの組み合わせ購入はおすすめできないことが読み取れます。


もし「あなたにオススメの〜は...」といったサービスを構築する際は、こんな感じのプログラムを作成するのがいいのですが、forループをかなり使うため、大規模なデータを扱う際にはアルゴリズムの改善をするべきだと思います。


追記:

a1とa1の商品の組み合わせ購入など、同じ商品同士で購入されることはありえないのですが、今回はその辺の計算を考慮し忘れてしまいました。そのためデータが正確では無いことをお詫び申し上げます。