クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

協調フィルタリングの仕組み

このレッスンのあとで: 似た人の評価から、まだ読んでいない本の点を予測できる。

55分のレッスンコマンド2件JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

似た人が好きな本をすすめる

レコメンドとは、その人が好きそうな品物を、記録から選んですすめる仕組みです。協調フィルタリングは、好みの似た人たちの評価を使って、まだ見ていない品物の点を予測する方法です。

大学の図書館アプリは、借りた本に1から5の点をつけてもらいます。まだ読んでいない本のうち、どれを見せるかを考えます。

このレッスンのゴール

メモ

似た人の評価から、まだ読んでいない本の点を予測できる。

キーワード

ことばいみれい
協調フィルタリング似た人の評価から、好みを予測する方法
評価表人ごと、品物ごとの点を並べた表
類似度2人の好みがどれだけ近いかを表す数0.33
予測まだ評価していない品物の点を見積もること
コールドスタート評価がまだなくて、予測できない状態

学生が入力するセルは、このプレビューでは空白です。

評価表から始める

4人の学生が、5冊の本に1から5の点をつけました。ゆいは「暗号」をまだ読んでいません。ゆいが何点をつけそうかを予測します。

考え方は単純です。ゆいと好みが近い人は、ゆいと似た点をつけるはずです。近い人の点を重く数えます。

例: 4人の評価表

学生統計入門Python入門データベースネットワーク暗号
ゆい5441?
けん55425
あや12152
そう44514

学生が入力するセルは、このプレビューでは空白です。

近さは点の差で測る

2人が同じ本につけた点の差を、すべて足します。差が小さいほど、好みが近いということです。

類似度は 1 ÷ (1 + 差の合計) にします。差が0なら 1 で、差が大きいほど 0 に近づきます。次のコマンドで、ゆいとけんの類似度を求めます。答えは 0.33 です。

ゆいとけんの類似度

コマンド
docker exec jupyter python3 -c 'a = [5, 4, 4, 1]; b = [5, 5, 4, 2]; print(round(1 / (1 + sum([abs(x - y) for x, y in zip(a, b)])), 2))'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

例: ゆいとほかの3人の類似度

学生差の合計類似度
けん20.33
あや130.07
そう20.33

学生が入力するセルは、このプレビューでは空白です。

近い人の点を重くして平均する

暗号に点をつけたのは、けん(5点)、あや(2点)、そう(4点)です。ふつうの平均は約 3.67 です。けれど、あやはゆいと好みが違います。

類似度を重みにして平均します。(0.33×5 + 0.07×2 + 0.33×4) ÷ (0.33 + 0.07 + 0.33) で、約 4.26 です。次のコマンドも、同じ計算をします。

重みつき平均で予測する

コマンド
docker exec jupyter python3 -c 'w = [1/3, 1/14, 1/3]; s = [5, 2, 4]; print(round(sum([a * b for a, b in zip(w, s)]) / sum(w), 2))'

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

予測をコードで計算する

コード: python
# 4人の評価表です。ゆいは「暗号」を読んでいません。
ratings = {
    "ゆい": {"統計入門": 5, "Python入門": 4, "データベース": 4, "ネットワーク": 1},
    "けん": {"統計入門": 5, "Python入門": 5, "データベース": 4, "ネットワーク": 2, "暗号": 5},
    "あや": {"統計入門": 1, "Python入門": 2, "データベース": 1, "ネットワーク": 5, "暗号": 2},
    "そう": {"統計入門": 4, "Python入門": 4, "データベース": 5, "ネットワーク": 1, "暗号": 4},
}

def similarity(a, b):
    gap = 0
    for book in a:
        if book in b:
            gap = gap + abs(a[book] - b[book])
    return 1 / (1 + gap)

top = 0
bottom = 0
for other in ratings:
    if other != "ゆい" and "暗号" in ratings[other]:
        weight = similarity(ratings["ゆい"], ratings[other])
        top = top + weight * ratings[other]["暗号"]
        bottom = bottom + weight
print("ゆいの予測:", round(top / bottom, 2))
# あやの暗号の点を 2 から 5 に変えて、もう一度実行してください。
# 予測はどう変わりますか。

品物どうしの近さを使う方法もある

似た人を探す代わりに、似た本を探す方法もあります。同じ人たちに好まれる本どうしは、近い本と考えます。

ゆいが好きな本に近い本を、すすめます。人の数が増えても本のほうが変わりにくいので、大きなサービスでよく使われます。

よくある間違い

注意

平均点がいちばん高い本を、全員にすすめればよいと考えがちです。実際は、人気の本が、その人の好みに合うとは限りません。好みの近い人の点を重く数えます。新しい学生は、評価がなく予測できません。

このラボとソースについて: JupyterLab データサイエンスラボ:pandas、Matplotlib、scikit-learn をブラウザーで

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。