Python入門トップページ


目次

  1. 協調フィルタリングによる推薦システム
  2. 顧客間の類似度に基づいた手法
  3. 個別データを順にマージしてみる
  4. 個別データを一気にマージしてみる
  5. 行列分解
  6. サンプルコードのまとめ
  7. Surprise による顧客間類似度に基づいた手法
  8. Surprise による行列分解
  9. ユーザごとの推薦アイテムリストを作成する
  10. 推薦アルゴリズムの性能を評価する
  11. 適合率と再現率
  12. クロスバリデーション
  13. 学習済みモデルの保存と読み込み

協調フィルタリングによる推薦システムを作ってみよう

個別データを一気にマージしてみる

ここでも,「商品データ」「顧客データ」「評価データ」の3つのデータを読み込んで行列形式に集計する方法を確認します.前のページとの違いは3つのテーブルを一気に結合するところです.

目次に戻る

データを読み込む

まず,必要なライブラリをインポートします.


import pandas as pd
import numpy as np

商品のCSVデータを GitHub のリポジトリからデータフレームに読み込みます.


url_items = "https://github.com/rinsaka/sample-data-sets/blob/master/collaborative_filtering_items.csv?raw=true"
df_items = pd.read_csv(url_items)
print(df_items)
   id item
0   0    A
1   1    B
2   2    C
3   3    D
4   4    E

顧客のCSVデータを読み込みます.


url_customers = "https://github.com/rinsaka/sample-data-sets/blob/master/collaborative_filtering_customers.csv?raw=true"
df_customers = pd.read_csv(url_customers )
print(df_customers)
   id   name
0   0    Eto
1   1   Sato
2   2   Kato
3   3   Muto
4   4   Kito
5   5   Goto
6   6   Bito
7   7  Saito
8   8  Naito
9   9   Koto

次に,評価のCSVデータを読み込みます.例えば先頭行は,顧客ID = 8 の Naito さんが,商品ID = 3 の商品「D」について「2」という評価を行ったことを意味しています.


url_ratings = "https://github.com/rinsaka/sample-data-sets/blob/master/collaborative_filtering_ratings.csv?raw=true"
df_ratings = pd.read_csv(url_ratings)
print(df_ratings)
    customer  item  rating
0          8     3       2
1          1     1       2
2          6     1       3
3          9     2       2
4          6     0       3
5          2     2       4
6          1     2       4
7          4     2       3
8          3     2       2
9          8     0       5
10         0     0       5
11         2     1       3
12         4     0       4
13         5     4       3
14         7     2       5
15         8     4       1
16         5     3       2
17         6     4       1
18         0     1       4
19         1     3       2
20         5     0       2
21         7     1       4
22         0     2       3
23         5     1       5
24         3     1       3
25         8     1       5
26         3     4       2
27         8     2       4
28         9     3       2
29         1     4       3
30         6     2       2
31         2     0       2
32         3     0       2
33         9     4       2
34         7     4       5
35         7     0       4
36         9     0       3
37         4     3       4
38         4     1       3

目次に戻る

テーブルの結合

3つのテーブル(表のこと)を一気に結合します.なお,テーブルの結合に関する詳細はここここで確認してください.


tbl_3 = pd.merge(
    pd.merge(
        df_ratings, df_items,
        left_on = 'item',
        right_on = 'id',
    ),
    df_customers,
    left_on = 'customer', right_on = 'id'
)
print(tbl_3)
    customer  item_x  rating  id_x item_y  id_y   name
0          8       3       2     3      D     8  Naito
1          8       1       5     1      B     8  Naito
2          8       2       4     2      C     8  Naito
3          8       0       5     0      A     8  Naito
4          8       4       1     4      E     8  Naito
5          5       3       2     3      D     5   Goto
6          5       1       5     1      B     5   Goto
...(中略)...
33         7       0       4     0      A     7  Saito
34         7       4       5     4      E     7  Saito
35         3       1       3     1      B     3   Muto
36         3       2       2     2      C     3   Muto
37         3       0       2     0      A     3   Muto
38         3       4       2     4      E     3   Muto

列名を変更します.


tbl_3 = tbl_3.rename(columns={'item_y': 'item', 'id_y': 'id'})
print(tbl_3)
    customer  item_x  rating  id_x item  id   name
0          8       3       2     3    D   8  Naito
1          8       1       5     1    B   8  Naito
2          8       2       4     2    C   8  Naito
...(省略)...

必要な列だけ残し,更に順序も変更します.


tbl_3 = tbl_3.loc[:,['id', 'name','item','rating']]
print(tbl_3)
    id   name item  rating
0    8  Naito    D       2
1    8  Naito    B       5
2    8  Naito    C       4
3    8  Naito    A       5
4    8  Naito    E       1
5    5   Goto    D       2
6    5   Goto    B       5
7    5   Goto    A       2
8    5   Goto    E       3
9    1   Sato    D       2
10   1   Sato    B       2
11   1   Sato    C       4
12   1   Sato    E       3
13   9   Koto    D       2
14   9   Koto    C       2
15   9   Koto    A       3
16   9   Koto    E       2
17   4   Kito    D       4
18   4   Kito    B       3
19   4   Kito    C       3
20   4   Kito    A       4
21   6   Bito    B       3
22   6   Bito    C       2
23   6   Bito    A       3
24   6   Bito    E       1
25   2   Kato    B       3
26   2   Kato    C       4
27   2   Kato    A       2
28   0    Eto    B       4
29   0    Eto    C       3
30   0    Eto    A       5
31   7  Saito    B       4
32   7  Saito    C       5
33   7  Saito    A       4
34   7  Saito    E       5
35   3   Muto    B       3
36   3   Muto    C       2
37   3   Muto    A       2
38   3   Muto    E       2

目次に戻る

評価の集計

評価の生データをピボットテーブルを利用して行列形式にまとめます.まず,念の為に顧客と商品ごとの評価数を確認します.つまり,同一顧客が同じ商品に複数回評価していないかを確認しておきます.この結果,1.0 より大きなデータがない,つまり,同じ商品を複数回評価しているデータはないことがわかりました.


df = tbl_3.pivot_table('rating', index=['id', 'name'], columns='item', aggfunc='count')
print(df)
item        A    B    C    D    E
id name
0  Eto    1.0  1.0  1.0  NaN  NaN
1  Sato   NaN  1.0  1.0  1.0  1.0
2  Kato   1.0  1.0  1.0  NaN  NaN
3  Muto   1.0  1.0  1.0  NaN  1.0
4  Kito   1.0  1.0  1.0  1.0  NaN
5  Goto   1.0  1.0  NaN  1.0  1.0
6  Bito   1.0  1.0  1.0  NaN  1.0
7  Saito  1.0  1.0  1.0  NaN  1.0
8  Naito  1.0  1.0  1.0  1.0  1.0
9  Koto   1.0  NaN  1.0  1.0  1.0

重複した評価がないことが確認できたので,合計を計算すると簡単に集計できます.


df = tbl_3.pivot_table('rating', index=['id', 'name'], columns='item', aggfunc='sum')
print(df)
item        A    B    C    D    E
id name
0  Eto    5.0  4.0  3.0  NaN  NaN
1  Sato   NaN  2.0  4.0  2.0  3.0
2  Kato   2.0  3.0  4.0  NaN  NaN
3  Muto   2.0  3.0  2.0  NaN  2.0
4  Kito   4.0  3.0  3.0  4.0  NaN
5  Goto   2.0  5.0  NaN  2.0  3.0
6  Bito   3.0  3.0  2.0  NaN  1.0
7  Saito  4.0  4.0  5.0  NaN  5.0
8  Naito  5.0  5.0  4.0  2.0  1.0
9  Koto   3.0  NaN  2.0  2.0  2.0

これで行列形式のデータフレームが完成したので,NumPy 配列に格納し,レイティング行列 y を生成します.


y = df.values
print(y)
[[ 5.  4.  3. nan nan]
 [nan  2.  4.  2.  3.]
 [ 2.  3.  4. nan nan]
 [ 2.  3.  2. nan  2.]
 [ 4.  3.  3.  4. nan]
 [ 2.  5. nan  2.  3.]
 [ 3.  3.  2. nan  1.]
 [ 4.  4.  5. nan  5.]
 [ 5.  5.  4.  2.  1.]
 [ 3. nan  2.  2.  2.]]

これも以前のページの行列 y と全く同じ形式です.ここまでできれば,類似度の計算やスコアの計算は前のページと同じ方法で可能です.

これまでコードを断片的に示してきたので,次のページではコードの全体像を示します.

目次に戻る