Programming Collective Intelligence#3

間開けてしまった。読みだけは3章に言ってるんだけど、アウトプットが追いつかない。

前回:

スコアを類似度で重み付けして正規化。いいのか?これで

なところまで
 まあ、僕の勘違いというか加重平均なんだからあれでいんだよね。寝ぼけてた。ただ、こういったところが気に入らなければ梃入れすることも必要と言う理解にたどり着いた。

で、続き

Matching Products

ここまでは:

 ユーザを引数にして似たスコアの人を取得→ 似た人のスコアを元にrecommendationをする。

amazonとかでは:

 ある商品を買う→ その商品を買った人が他に買っているものを出す。

amazonとかをやるには表をひっくり返せば良い。
これまで: {'user1': {'item1': score, ....}}, {'user2': .....}} ....
ひっくり返す: {'item1': {'user1': score, ......}}
んでこれまでと全く同じ事をすれば、ある itemを買ったときにそれに近い user ベクトルを持ったもの=類似度が高い、という指標が手に入る。というわけ。簡単。実際ひっくり返す transformPrefs(prefs): 以外は前と同じだ。

Building a del.icio.us Link Recommender

単に今までやったことを実データでやってみるだけ。del.icio.usAPIを作ってあるので楽チン。
http://code.google.com/p/pydelicious/source
内容は単に feedparserで拾ってそれを処理している単純なモジュール。でも結構長い。この節で使う機能はこの中の

get_popular(tag=..)
人気ポスト(dict)の配列を拾ってくる。
get_urlposts(url)
指定したurlに関するポストの配列を拾ってくる。
get_userposts(user)
userが投稿したポストの配列を拾ってくる。

くらい。要するにこれを使ってデータベースを作るところだけが新しい。残りは今までやってきた topMatch()や getRecommendations()をかけるだけで今までと全く同じ。

データベースの作り方は例によって二段ロケット方式。1段目は初期化(initializeUserDict())

  1. get_popular()で人気ポストを拾い -> p1
  2. p1の各urlをget_urlposts()して、「人気ポストに関連するポスト」を全て拾って -> p2
  3. p2の各 user を拾って、その userをキーにしたエントリに空っぽの辞書を作る。 -> user_dict[user] = {}

これで拾ってくるユーザーを決定する。1段目が終わったところでuser_dictに好きなキーを足してもいい(たとえば自分とか)。
2段目はこのuser_dictを使いratingsを設定する(fillItems(user_dict))。ただし、前の映画の例と違って評価値ではなく、 1(ポストした)か0(ポストしてない)かのどちらか。

  1. 各キー(user) に対して get_userpost()してそのユーザのポストを集める -> posts
  2. posts の url(href) をみて、user_dict[user]の辞書に1(ポストした)を追加 -> user_dict[user][url]=1.0
  3. 後で0(ポストしてない)を処理するための全アイテム辞書にも追加 -> all_items[url] = 1

のループをまわして全ユーザ終わってから

  1. user_dictの各辞書について処理 -> ratings
    1. 全アイテム辞書にあって、ratingsに無いものを0(ポストしてない)に設定 -> ratings[item] = 0.0

でき上がり。user_dictを引数にして適当なユーザを与えればrecommendateしてもらえる。

Item-Based Filtering

ここまでのrecommendationエンジンの実装は各ユーザの全ランキングを使う方法→1000エントリくらいが限界。amazonのようにミリオン以上級のデータセットでは問題外 + amazonのように商品も膨大な数がある場合、そもそもユーザーどうしのオーバーラップも少なく、類似判定が難しい。
ここまでやってきたような方式は user-based collaborative filteringと呼ばれている。別の方法として item-based collaborative filteringを使ってみる。

item-basedでもこれまで使ってきたのと同じような概念がほとんど。違いはアイテム同士の類似度を前計算する部分。
<続く>