協調フィルタリングを使用した推奨エンジンの構築
協調フィルタリングは、ユーザーに関するより多くの情報が収集されるにつれて、より良い推奨事項を提供することを学ぶことができるインテリジェントな推奨システムを構築する際に使用される最も一般的な手法です。
Amazon、YouTube、NetflixなどのほとんどのWebサイトは、高度な推奨システムの一部として協調フィルタリングを使用しています。 この手法を使用して、類似ユーザーの好き嫌いに基づいてユーザーに提案を行うレコメンダーを構築できます。
この記事では、以下について学習します。
-
協調フィルタリングとそのタイプ
-
レコメンダーを構築するために必要なデータ
-
レコメンダーを作成するためにPythonで使用可能なライブラリー
-
共同フィルタリングのユースケースと課題
Free Bonus:Click here to get access to a chapter from Python Tricks: The Bookは、Pythonのベストプラクティスと、より美しい+ Pythonicコードをすぐに適用できる簡単な例を示しています。
協調フィルタリングとは何ですか?
協調フィルタリングは、類似したユーザーの反応に基づいて、ユーザーが好む可能性のあるアイテムをフィルターで除外できる手法です。
多数の人々を検索し、特定のユーザーに似た好みを持つ少数のユーザーを見つけることで機能します。 好きなアイテムを見て、それらを組み合わせて、ランク付けされた候補リストを作成します。
どのユーザーが似ているかを判断し、選択肢を組み合わせて推奨事項のリストを作成する方法は多数あります。 この記事では、Pythonでそれを行う方法を示します。
データセット
レコメンデーションアルゴリズムを試すには、いくつかのアイテムに反応したset of itemsとset of usersを含むデータが必要です。
反応は、explicit(1から5のスケールで評価)またはimplicit(アイテムの表示、ウィッシュリストへの追加、記事に費やされた時間)の場合があります。
このようなデータを操作していると、ほとんどの場合、一連のアイテムからいくつかのアイテムに対して一連のユーザーが行った反応で構成されるmatrixの形式で表示されます。 各行にはユーザーが指定した評価が含まれ、各列にはアイテムが受け取った評価が含まれます。 5人のユーザーと5つのアイテムを持つマトリックスは次のようになります。
マトリックスには、一部のアイテムを1〜5のスケールで評価した5人のユーザーが表示されます。 たとえば、最初のユーザーが3番目のアイテムに評価4を与えました。
ほとんどの場合、マトリックス内のセルは空です。これは、ユーザーがいくつかのアイテムのみを評価するためです。 すべてのユーザーが利用可能なすべてのアイテムを評価または反応することはほとんどありません。 ほとんど空のセルを持つ行列はsparseと呼ばれ、その反対(ほとんど満たされた行列)はdenseと呼ばれます。
多くのデータセットが収集され、研究とベンチマークのために公開されています。 選択できるlist of high-quality data sourcesは次のとおりです。
始めるのに最適なのは、GroupLens Researchによって収集されたMovieLensデータセットです。 特に、MovieLens 100k datasetは、1682本の映画に対して943人のユーザーによって100,000の評価が与えられ、各ユーザーが少なくとも20本の映画を評価した安定したベンチマークデータセットです。
このデータセットは、映画、ユーザー、およびユーザーが視聴した映画に対してユーザーから与えられた評価に関する情報を含む多くのファイルで構成されています。 興味深いのは次のとおりです。
-
u.item
:映画のリスト -
u.data
:ユーザーによって与えられた評価のリスト
評価を含むファイルu.data
は、ユーザーID、アイテムID、評価、およびタイムスタンプのタブ区切りのリストです。 ファイルの最初の数行は次のようになります。
上記のように、このファイルは、ユーザーが特定の映画に付けた評価を示します。 このファイルには、100,000件のこのような評価が含まれており、ユーザーが視聴していない映画の評価を予測するために使用されます。
協調フィルタリングに含まれるステップ
他のユーザーの好みに基づいてユーザーにアイテムを自動的に推奨できるシステムを構築するには、最初のステップは類似したユーザーまたはアイテムを見つけることです。 2番目のステップは、ユーザーがまだ評価していないアイテムの評価を予測することです。 したがって、これらの質問に対する答えが必要になります。
-
どのユーザーまたはアイテムが互いに似ているかをどのように判断しますか?
-
どのユーザーが似ているかがわかっている場合、似たようなユーザーの評価に基づいて、ユーザーがアイテムに与える評価をどのように決定しますか?
-
計算した評価の精度をどのように測定しますか?
最初の2つの質問には単一の答えはありません。 協調フィルタリングは、類似したユーザーまたはアイテムを見つける複数の方法と、類似したユーザーの評価に基づいて評価を計算する複数の方法があるアルゴリズムのファミリーです。 選択した内容に応じて、最終的には協調的なフィルタリングアプローチのタイプになります。 この記事では、類似性を見つけて評価を予測するためのさまざまなアプローチを紹介します。
留意すべき重要な点は、純粋に協調フィルタリングに基づくアプローチでは、ユーザーの年齢、映画のジャンル、またはユーザーやアイテムに関するその他のデータなどの要因を使用して類似性が計算されないことです。 ユーザーがアイテムに与える評価(明示的または暗黙的)に基づいてのみ計算されます。 たとえば、2人のユーザーは、年齢に大きな違いがあるにもかかわらず、10本の映画に同じ評価を与えた場合、類似していると見なすことができます。
予測の精度を測定する方法に関する3番目の質問には、複数の回答があります。これには、協調フィルタリングに基づくレコメンダーだけでなく、多くの場所で使用できるエラー計算手法が含まれます。
結果の精度を測定する方法の1つは、二乗平均誤差(RMSE)です。この方法では、評価値が既知のユーザーとアイテムのペアのテストデータセットの評価を予測します。 既知の値と予測値の差がエラーになります。 テストセットのすべてのエラー値を平方し、平均(または平均)を求め、その平均の平方根を取得してRMSEを取得します。
精度を測定するもう1つのメトリックは平均絶対誤差(MAE)で、絶対値を見つけてすべての誤差値の平均を取ることで誤差の大きさを見つけます。
Pythonのさまざまなパッケージの一部としてすぐに利用できるため、この時点でRMSEまたはMAEの詳細を心配する必要はありません。詳細は記事の後半で説明します。
次に、協調フィルタリングのファミリーのさまざまなタイプのアルゴリズムを見てみましょう。
メモリベース
最初のカテゴリには、メモリベースのアルゴリズムが含まれます。このアルゴリズムでは、統計的手法がデータセット全体に適用され、予測が計算されます。
ユーザーUがアイテムIに与える評価Rを見つけるためのアプローチには、次のものが含まれます。
-
アイテムIを評価したUに類似したユーザーを見つける
-
前のステップで見つかったユーザーの評価に基づいて評価Rを計算する
次のセクションで、それらのそれぞれについて詳しく説明します。
評価に基づいて同様のユーザーを見つける方法
類似性の概念を理解するために、最初に簡単なデータセットを作成しましょう。
データには、2つの映画を評価した4人のユーザーA、B、C、およびDが含まれています。 評価はリストに保存され、各リストには各映画の評価を示す2つの数字が含まれています。
-
Aによる評価は
[1.0, 2.0]
です。 -
Bによる評価は
[2.0, 4.0]
です。 -
Cによる評価は
[2.5, 4.0]
です。 -
Dによる評価は
[4.5, 5.0]
です。
視覚的な手がかりから始めるには、ユーザーが指定した2つの映画の評価をグラフにプロットし、パターンを探します。 グラフは次のようになります。
上記のグラフでは、各ポイントはユーザーを表し、2つの映画に与えた評価に対してプロットされています。
点間の距離を調べることは、類似性を推定するための良い方法のようですよね? 2点間のユークリッド距離の式を使用して、距離を見つけることができます。 次のプログラムに示すように、scipy
で使用可能な関数を使用できます。
>>>
>>> from scipy import spatial
>>> a = [1, 2]
>>> b = [2, 4]
>>> c = [2.5, 4]
>>> d = [4.5, 5]
>>> spatial.distance.euclidean(c, a)
2.5
>>> spatial.distance.euclidean(c, b)
0.5
>>> spatial.distance.euclidean(c, d)
2.23606797749979
上に示したように、scipy.spatial.distance.euclidean
を使用して2点間の距離を計算できます。 これを使用して、A、B、およびDの評価とCの評価の間の距離を計算すると、距離の観点から、Cの評価がわかります。 )sはBのものに最も近いです。
グラフを見ても、ユーザーCがBに最も近いことがわかります。 しかし、AとDだけのうち、Cに近いのは誰ですか?
距離の点では、CはDに近いと言えます。 しかし、ランキングを見ると、AとCの両方が2番目の映画は最初の映画のほぼ2倍好きですが、Dは両方の映画を同じように好きです。
それで、ユークリッド距離ができないようなパターンを識別するために何を使用できますか? 点を原点に結合する線の間の角度を使用して決定を下すことができますか? 以下に示すように、グラフの原点とそれぞれのポイントを結ぶ線の間の角度を見ることができます。
グラフには、各ポイントを原点に結合する4本の線が表示されます。 AとBの線は一致しており、それらの間の角度はゼロになります。
線間の角度が大きくなると類似性が低下し、角度がゼロの場合はユーザーが非常に似ていると考えることができます。
角度を使用して類似性を計算するには、低い角度の場合はhigher similarityまたはsmaller distanceを返し、高い角度の場合はlower similarityまたはlarger distanceを返す関数が必要です。 角度の余弦は、角度が0から180に増加するにつれて1から-1に減少する関数です。
角度のコサインを使用して、2人のユーザー間の類似性を見つけることができます。 角度が大きいほど、余弦は低くなり、したがって、ユーザーの類似度は低くなります。 角度のコサインの値を逆にして、1から減算することにより、ユーザー間のコサイン距離を取得することもできます。
scipy
には、ベクトルのcosine distanceを計算する関数があります。 角度が大きいほど高い値を返します。
>>>
>>> from scipy import spatial
>>> a = [1, 2]
>>> b = [2, 4]
>>> c = [2.5, 4]
>>> d = [4.5, 5]
>>> spatial.distance.cosine(c,a)
0.004504527406047898
>>> spatial.distance.cosine(c,b)
0.004504527406047898
>>> spatial.distance.cosine(c,d)
0.015137225946083022
>>> spatial.distance.cosine(a,b)
0.0
CとAのベクトル間の角度が小さいほど、コサイン距離の値が小さくなります。 この方法でユーザーの類似性をランク付けする場合は、コサイン距離を使用します。
Note:上記の例では、2つの映画のみが考慮されているため、評価ベクトルを2次元で視覚化するのが簡単になります。 これは、説明を簡単にするためだけに行われます。
複数のアイテムを使用する実際のユースケースでは、評価ベクトルにより多くのディメンションが含まれます。 cosine similarityの数学にも入りたいと思うかもしれません。
ユーザーAとBは、評価が異なるにもかかわらず、コサイン類似度メトリックで完全に類似していると見なされることに注意してください。 これは実際には現実の世界では一般的なことであり、ユーザーAのようなユーザーはtough ratersと呼ぶことができます。 例としては、常に平均よりも低い評価を与える映画評論家がありますが、リスト内のアイテムのランキングは、BのようなAverage ratersに似ています。
このような個々のユーザー設定を考慮するには、バイアスを削除してすべてのユーザーを同じレベルにする必要があります。 これを行うには、そのユーザーが評価した各アイテムから、そのユーザーがすべてのアイテムに与えた平均評価を減算します。 これは次のようになります。
-
ユーザーAの場合、評価ベクトル
[1, 2]
の平均は1.5
です。 すべての評価から1.5
を引くと、ベクトル[-0.5, 0.5]
が得られます。 -
ユーザーBの場合、評価ベクトル
[2, 4]
の平均は3
です。 すべての評価から3
を引くと、ベクトル[-1, 1]
が得られます。
これにより、すべてのユーザーが指定する平均評価の値を0に変更しました。 ユーザーCとDについても同じことを試してみてください。評価が調整され、すべてのユーザーの平均が0になるようになりました。これにより、すべてのユーザーが同じレベルになり、ユーザーが削除されます。バイアス。
調整されたベクトル間の角度の余弦はcentered cosineと呼ばれます。 このアプローチは通常、ベクトルに多くの欠損値があり、欠損値を埋めるために共通の値を配置する必要がある場合に使用されます。
評価マトリックスの欠損値をランダムな値で埋めると、不正確になる可能性があります。 欠落している値を埋めるのに適した選択は、各ユーザーの平均評価ですが、ユーザーAとBの元の平均は、それぞれ1.5
と3
であり、埋めます。 Aのすべての空の値を1.5
で、Bの値を3
で上げると、それらは異なるユーザーになります。
ただし、値を調整した後、両方のユーザーのcentered平均は0
になります。これにより、両方のユーザーのすべての欠落値がある両方のユーザーの平均より上または下のアイテムのアイデアをより正確にキャプチャできます。同じ値0
を持つベクトル。
ユークリッド距離とコサイン類似度は、互いに類似したユーザー、さらには類似したアイテムを見つけるために使用できるアプローチの一部です。 (上記で使用される関数は、コサイン距離を計算します。 コサインの類似度を計算するには、1から距離を引きます)
Note:中心コサインの式は、ピアソン相関係数の式と同じです。 レコメンダーの多くのリソースとライブラリーは、中心コサインの実装をピアソン相関と呼んでいることがわかります。
評価の計算方法
ユーザーUに類似したユーザーのリストを決定したら、Uが特定のアイテムIに与える評価Rを計算する必要があります。 繰り返しますが、類似性と同様に、複数の方法でこれを行うことができます。
アイテムIに対するユーザーの評価Rは、Uに最も類似した上位5人または上位10人のユーザーによってIに与えられた評価の平均に近いと予測できます。 )s。 nユーザーによって与えられる平均評価の数式は次のようになります。
この式は、nの類似ユーザーによって与えられた平均評価が、それらによって与えられた評価の合計を類似ユーザーの数で割ったもの、つまりnに等しいことを示しています。
見つけたnの類似ユーザーが、ターゲットユーザーのUと等しく類似していない場合があります。 それらの上位3つは非常に類似している可能性があり、残りは上位3つほどUに類似していない可能性があります。 その場合、最も類似したユーザーの評価が2番目に類似したユーザーよりも重要であるというアプローチを検討できます。 加重平均は、それを達成するのに役立ちます。
加重平均アプローチでは、各評価に類似度係数(ユーザーの類似度を示す)を掛けます。 類似性係数を掛けることにより、評価に重みを追加します。 重量が重ければ重いほど、評価は重要になります。
重みとして機能する類似性係数は、距離が短いほど類似性が高いことを意味するため、前述の距離の逆数である必要があります。 たとえば、1からコサイン距離を減算して、コサイン類似度を取得できます。
ターゲットユーザーUと同様の各ユーザーの類似度係数Sを使用すると、次の式を使用して加重平均を計算できます。
上記の式では、すべての評価に評価を与えたユーザーの類似度係数が乗算されます。 ユーザーUによる最終的な予測評価は、加重評価の合計を加重の合計で割ったものに等しくなります。
Note:加重評価の合計が、nではなく加重の合計で除算されている理由がわからない場合は、次のことを考慮してください。前の平均の式で、 n、重みの値は1でした。
分母は、平均を見つける際には常に重みの合計であり、通常の平均の場合、重みが1であるということは、分母がnに等しいことを意味します。
加重平均を使用すると、類似ユーザーの評価を類似度の順にさらに考慮することができます。
これで、同様のユーザーを見つける方法と、評価に基づいて評価を計算する方法がわかりました。 また、ユーザーの代わりに互いに類似したアイテムを見つけて評価を計算することで評価を予測する、協調フィルタリングのバリエーションもあります。 このバリエーションについては、次のセクションで説明します。
ユーザーベースのコラボレーションフィルタリングとアイテムベースのコラボレーションフィルタリング
上記の例で、評価マトリックスを使用して、評価に基づいて類似のユーザーを見つける手法は、ユーザーベースまたはユーザー間協調フィルタリングと呼ばれます。 評価マトリックスを使用して、ユーザーから与えられた評価に基づいて類似のアイテムを検索する場合、このアプローチはアイテムベースまたはアイテムアイテム協調フィルタリングと呼ばれます。
2つのアプローチは数学的に非常に似ていますが、2つのアプローチには概念的な違いがあります。 この2つの比較方法は次のとおりです。
-
User-based:ユーザーUの場合、特定のアイテムの評価で構成される評価ベクトルに基づいて決定された類似ユーザーのセットを使用すると、評価されていないアイテムIの評価は次のようになります。アイテムIを評価した類似性リストからN人のユーザーを選び出し、これらのN人の評価に基づいて評価を計算することによって見つけられます。
-
Item-based:アイテムIの場合、受け取ったユーザー評価で構成される評価ベクトルに基づいて決定された類似アイテムのセットを使用すると、それを評価していないユーザーUによる評価は次のようになります。 Uで評価された類似性リストからN個のアイテムを選択し、これらのN個の評価に基づいて評価を計算することによって検出されます。
アイテムベースの協調フィルタリングは、Amazonによって開発されました。 アイテムよりもユーザーが多いシステムでは、アイテムベースのフィルタリングはユーザーベースよりも高速で安定しています。 通常、アイテムが受け取る平均評価は、ユーザーがさまざまなアイテムに与える平均評価ほど迅速に変化しないため、効果的です。 評価マトリックスがまばらな場合、ユーザーベースのアプローチよりもパフォーマンスが高いことも知られています。
ただし、アイテムベースのアプローチは、MovieLensなどのブラウジングやエンターテイメント関連のアイテムを含むデータセットではパフォーマンスが低下します。 このようなデータセットは、次のセクションで説明するマトリックス因数分解手法、またはcontent-based filteringを使用してジャンルなどのデータのコンテンツも考慮に入れるハイブリッド推奨を使用すると、より良い結果が得られます。
ライブラリSurpriseを使用して、さまざまなレコメンダーアルゴリズムをすばやく試すことができます。 (これについては記事の後半で詳しく説明します。)
モデルベース
2番目のカテゴリは、モデルベースのアプローチをカバーします。これは、大きくても疎なユーザーアイテムマトリックスを削減または圧縮するステップを含みます。 このステップを理解するには、次元削減の基本的な理解が非常に役立ちます。
次元削減
ユーザーアイテムマトリックスには、2つの次元があります。
-
ユーザー数
-
アイテム数
行列の大部分が空の場合、次元を減らすと、空間と時間の両方の点でアルゴリズムのパフォーマンスが向上します。 これを行うには、行列因数分解やオートエンコーダーなどのさまざまな方法を使用できます。
Matrix factorizationは、大きな行列を小さな行列の積に分解するものと見なすことができます。 これは整数の因数分解に似ており、12
は6 x 2
または4 x 3
として記述できます。 行列の場合、次元m x n
の行列Aは、次元m x p
とm x p
の2つの行列XとYの積に減らすことができます。それぞれt9)s。
Note:行列の乗算では、Xの列数がYの行数と等しい場合にのみ、行列XにYを乗算できます。 。 したがって、2つの縮小された行列は共通の次元pを持ちます。
次元削減に使用されるアルゴリズムに応じて、削減された行列の数も3つ以上になる可能性があります。
縮小されたマトリックスは、実際にはユーザーとアイテムを個別に表します。 最初のマトリックスのm行は、mユーザーを表し、p列は、ユーザーの機能または特性を示します。 同じことが、nアイテムとp特性を持つアイテムマトリックスにも当てはまります。 マトリックス分解がどのように見えるかの例を次に示します。
上の画像では、マトリックスは2つのマトリックスに縮小されています。 左側はmユーザーのユーザーマトリックスで、上部はnアイテムのアイテムマトリックスです。 評価4
は、次のように削減または因数分解されます。
-
ユーザーベクトル
(2, -1)
-
アイテムベクトル
(2.5, 1)
ユーザーマトリックスの2列とアイテムマトリックスの2行は潜在因子と呼ばれ、ユーザーまたはアイテムに関する隠された特性を示します。 因数分解の可能な解釈は次のようになります。
-
ユーザーベクトル
(u, v)
で、u
はユーザーがホラージャンルをどれだけ好きかを表し、v
はロマンスジャンルをどれだけ好きかを表すと仮定します。 -
したがって、ユーザーベクトル
(2, -1)
は、ホラー映画が好きで肯定的に評価し、恋愛映画が嫌いで否定的に評価するユーザーを表します。 -
アイテムベクトル
(i, j)
で、i
は映画がホラージャンルにどれだけ属しているかを表し、j
はその映画がロマンスジャンルにどれだけ属しているかを表していると仮定します。 -
映画
(2.5, 1)
のホラーレーティングは2.5
、ロマンスレーティングは1
です。 行列乗算ルールを使用してユーザーベクトルを乗算すると、(2 * 2.5) + (-1 * 1) = 4
が得られます。 -
そのため、映画はホラージャンルに属し、ユーザーはそれを
5
と評価できたはずですが、ロマンスをわずかに含めると、最終的な評価は4
に下がりました。
因子マトリックスは、ユーザーやアイテムに関するそのような洞察を提供できますが、実際には、通常、上記の説明よりもはるかに複雑です。 そのような要因の数は、1から数百、さらには数千にまで及ぶことがあります。 この数は、モデルのトレーニング中に最適化する必要があるものの1つです。
この例では、映画のジャンルに2つの潜在的要因がありましたが、実際のシナリオでは、これらの潜在的要因をあまり分析する必要はありません。 これらは、データのパターンであり、その意味を解読するかどうかにかかわらず、自動的に役割を果たします。
潜在的要因の数は、要因の数が多いほど推奨がよりパーソナライズされるように推奨に影響します。 ただし、要素が多すぎると、モデルが過剰適合する可能性があります。
Note:Overfittingは、モデルがトレーニングデータにうまく適合するようにトレーニングし、新しいデータではうまく機能しない場合に発生します。
行列分解のアルゴリズム
行列を因数分解するための一般的なアルゴリズムの1つは、singular value decomposition(SVD)アルゴリズムです。 SVDは、Netflix賞コンペティションで行列因子分解がうまく機能していることが確認されたときに脚光を浴びました。 他のアルゴリズムには、PCAとそのバリエーション、NMFなどが含まれます。 Autoencodersは、ニューラルネットワークを使用する場合の次元削減にも使用できます。
Pythonのさまざまなライブラリでこれらのアルゴリズムの実装を見つけることができるため、この時点で詳細について心配する必要はありません。 しかし、もっと読みたい場合は、本Mining of Massive Datasetsの次元削減に関する章を読む価値があります。
Pythonを使用してレコメンダーを作成する
Pythonには、レコメンダーを構築するために使用できるさまざまなアルゴリズムの実装を提供するライブラリとツールキットがかなりあります。 しかし、レコメンデーションシステムを理解しながら試してみるべきものはSurpriseです。
サプライズはPythonSciKitであり、さまざまなレコメンダーアルゴリズムと類似性メトリックが付属しており、レコメンダーの構築と分析を簡単に行うことができます。
pipを使用してインストールする方法は次のとおりです。
$ pip install numpy
$ pip install scikit-surprise
condaを使用してインストールする方法は次のとおりです。
$ conda install -c conda-forge scikit-surprise
Note:例に従う場合は、Pandasをインストールすることもお勧めします。
-
Dataset
モジュールは、ファイル、Pandas dataframes、または実験に使用できる組み込みデータセットからデータをロードするために使用されます。 (MovieLens 100kはSurpriseの組み込みデータセットの1つです。)データセットをロードするには、次のメソッドを使用できます。-
Dataset.load_builtin()
-
Dataset.load_from_file()
-
Dataset.load_from_df()
-
-
Reader
クラスは、評価を含むファイルを解析するために使用されます。 データを受け入れるデフォルトの形式では、各評価はuser item rating
の順序で別々の行に格納されます。 この順序と区切り文字は、パラメーターを使用して構成できます。-
line_format
は、"item user rating"
のように、フィールド名をスペースで区切ってデータの順序を格納するstringです。 -
sep
は、','
などのフィールド間の区切り文字を指定するために使用されます。 -
rating_scale
は、評価尺度を指定するために使用されます。 デフォルトは(1, 5)
です。 -
skip_lines
は、ファイルの先頭でスキップする行数を示すために使用されます。 デフォルトは0
です。
-
Pandasデータフレームまたは組み込みのMovieLens 100kデータセットからデータをロードするために使用できるプログラムは次のとおりです。
# load_data.py
import pandas as pd
from surprise import Dataset
from surprise import Reader
# This is the same data that was plotted for similarity earlier
# with one new user "E" who has rated only movie 1
ratings_dict = {
"item": [1, 2, 1, 2, 1, 2, 1, 2, 1],
"user": ['A', 'A', 'B', 'B', 'C', 'C', 'D', 'D', 'E'],
"rating": [1, 2, 2, 4, 2.5, 4, 4.5, 5, 3],
}
df = pd.DataFrame(ratings_dict)
reader = Reader(rating_scale=(1, 5))
# Loads Pandas dataframe
data = Dataset.load_from_df(df[[user", "item", "rating"]], reader)
# Loads the builtin Movielens-100k data
movielens = Dataset.load_builtin('ml-100k')
上記のプログラムでは、データは、Pandasデータフレームにロードされたディクショナリに格納され、その後サプライズのDatasetオブジェクトにロードされます。
K-Nearest Neighbors(k-NN)に基づくアルゴリズム
レコメンダー機能のアルゴリズムの選択は、使用する手法によって異なります。 上で説明したメモリベースのアプローチの場合、アルゴリズムは上で説明した中心コサイン類似度の式に非常に近いため、法案に適合するアルゴリズムはCentered k-NNです。 サプライズではKNNWithMeans
として利用できます。
類似性を見つけるには、辞書を引数としてリコメンダー関数に渡すことで、関数を構成するだけです。 辞書には、次のような必要なキーが必要です。
-
name
には、使用する類似性メトリックが含まれています。 オプションは、cosine
、msd
、pearson
、またはpearson_baseline
です。 デフォルトはmsd
です。 -
user_based
は、アプローチがユーザーベースかアイテムベースかを示すboolean
です。 デフォルトはTrue
です。これは、ユーザーベースのアプローチが使用されることを意味します。 -
min_support
は、類似性を考慮するためにユーザー間で必要な共通アイテムの最小数です。 アイテムベースのアプローチの場合、これは2つのアイテムの最小共通ユーザー数に対応します。
次のプログラムは、KNNWithMeans
関数を構成します。
# recommender.py
from surprise import KNNWithMeans
# To use item-based cosine similarity
sim_options = {
"name": "cosine",
"user_based": False, # Compute similarities between items
}
algo = KNNWithMeans(sim_options=sim_options)
上記のプログラムのリコメンダー機能は、コサイン類似度を使用し、アイテムベースのアプローチを使用して類似アイテムを検索するように構成されています。
このレコメンダーを試すには、data
からTrainset
を作成する必要があります。 Trainset
は同じデータを使用して作成されますが、アルゴリズムで使用されるユーザー数やアイテム(n_users
、n_items
)など、データに関する詳細情報が含まれています。 データ全体またはデータの一部を使用して作成できます。 また、データの一部をトレーニングに使用し、一部をテストに使用するフォールドに分割することもできます。
Note:通常、トレーニングデータとテストデータのペアを1つだけ使用するだけでは不十分です。 元のデータセットをトレーニングデータとテストデータに分割するときは、テストデータのトレーニングにバリエーションがある複数の観測を可能にするために、複数のペアを作成する必要があります。
アルゴリズムは、複数のフォールドを使用するcross-validatedである必要があります。 異なるペアを使用することで、レコメンダーからの異なる結果が表示されます。 MovieLens 100kは、5つの異なる交差検証のために、u1.base、u1.test、u2.base、u2.test…u5.base、u5.testの5種類のトレーニングデータとテストデータを提供します。
これは、ユーザーEが映画2をどのように評価するかを調べる例です。
>>>
>>> from load_data import data
>>> from recommender import algo
>>> trainingSet = data.build_full_trainset()
>>> algo.fit(trainingSet)
Computing the cosine similarity matrix...
Done computing similarity matrix.
>>> prediction = algo.predict('E', 2)
>>> prediction.est
4.15
アルゴリズムは、ユーザーEが映画4.15を評価すると予測しました。これは、推奨として表示されるのに十分な高さである可能性があります。
サプライズライブラリで利用可能なさまざまな類似性オプションとmatrix factorization algorithmsとともに、さまざまなk-NN based algorithmsを試してみてください。 MovieLensデータセットでそれらを試して、ベンチマークを上回ることができるかどうかを確認してください。 次のセクションでは、サプライズを使用してデータに最適なパラメータを確認する方法について説明します。
アルゴリズムパラメーターの調整
サプライズは、scikit-learn
のGridSearchCVに類似したGridSearchCV
クラスを提供します。
すべてのパラメーターのdict
を使用して、GridSearchCV
はパラメーターのすべての組み合わせを試行し、任意の精度測定に最適なパラメーターを報告します。
たとえば、メモリベースのアプローチで、どの類似性メトリックがデータに最適かを確認できます。
from surprise import KNNWithMeans
from surprise import Dataset
from surprise.model_selection import GridSearchCV
data = Dataset.load_builtin("ml-100k")
sim_options = {
"name": ["msd", "cosine"],
"min_support": [3, 4, 5],
"user_based": [False, True],
}
param_grid = {"sim_options": sim_options}
gs = GridSearchCV(KNNWithMeans, param_grid, measures=["rmse", "mae"], cv=3)
gs.fit(data)
print(gs.best_score["rmse"])
print(gs.best_params["rmse"])
上記のプログラムの出力は次のとおりです。
0.9434791128171457
{'sim_options': {'name': 'msd', 'min_support': 3, 'user_based': False}}
そのため、MovieLens 100kデータセットの場合、アイテムベースのアプローチを採用し、最小サポート3の類似性メトリックとしてmsdを使用すると、Centered-KNNアルゴリズムが最適に機能します。
同様に、モデルベースのアプローチの場合、Surprise
を使用して、次の要因のどの値が最も効果的かを確認できます。
-
n_epochs
は、SGDの反復回数です。これは、基本的に、関数を最小化するために統計で使用される反復法です。 -
lr_all
は、すべてのパラメーターの学習率です。これは、各反復でパラメーターを調整する量を決定するパラメーターです。 -
reg_all
は、すべてのパラメーターの正則化項であり、過剰適合を防ぐために追加されるペナルティ項です。
Note:潜在因子がユーザーまたはアイテム間の類似性を処理するため、行列因数分解アルゴリズムには類似性メトリックがないことに注意してください。
次のプログラムは、行列因数分解アルゴリズムであるSVDアルゴリズムの最適値をチェックします。
from surprise import SVD
from surprise import Dataset
from surprise.model_selection import GridSearchCV
data = Dataset.load_builtin("ml-100k")
param_grid = {
"n_epochs": [5, 10],
"lr_all": [0.002, 0.005],
"reg_all": [0.4, 0.6]
}
gs = GridSearchCV(SVD, param_grid, measures=["rmse", "mae"], cv=3)
gs.fit(data)
print(gs.best_score["rmse"])
print(gs.best_params["rmse"])
上記のプログラムの出力は次のとおりです。
0.9642278631521038
{'n_epochs': 10, 'lr_all': 0.005, 'reg_all': 0.4}
したがって、MovieLens 100kデータセットの場合、SVD
アルゴリズムは、10エポックを使用し、0.005の学習率と0.4の正則化を使用する場合に最適に機能します。
これらの例に従って、これらのアルゴリズムで使用できるすべてのパラメーターを深く掘り下げることができます。 あなたは間違いなくそれらの背後にある数学をチェックアウトする必要があります。 最初にアルゴリズムの実装について心配する必要はないため、リコメンダーは機械学習の分野に移行し、それに基づいてアプリケーションを構築するのに最適な方法です。
協調フィルタリングはいつ使用できますか?
協調フィルタリングは、ユーザーがアイテムに対して行う対話を回避します。 これらの相互作用は、アイテムやユーザーに関するデータではできないパターンを見つけるのに役立ちます。 協調フィルタリングを使用できるかどうかを判断するのに役立ついくつかのポイントを次に示します。
-
協調フィルタリングでは、アイテムやユーザーに関する機能を知る必要はありません。 さまざまな種類のアイテムのセットに適しています。たとえば、さまざまなカテゴリのアイテムを追加できるスーパーマーケットの在庫などです。 しかし、書店のような類似のアイテムのセットでは、作家やジャンルなどの既知の機能が有用である可能性があり、コンテンツベースまたはハイブリッドのアプローチの恩恵を受ける可能性があります。
-
協調フィルタリングは、レコメンダーがユーザーのプロファイルを過度に専門化せず、以前に見たものとは完全に異なるアイテムを推奨するのに役立ちます。 同様のスニーカーを購入したばかりの人に推奨者がスニーカーを提案しないようにしたい場合は、推奨スペルに協調フィルタリングを追加してみてください。
コラボレーティブフィルタリングはレコメンダーで非常に一般的に使用されていますが、使用中に直面する課題のいくつかは次のとおりです。
-
協調フィルタリングは、リストに追加された新しいアイテムのコールドスタートなどの問題を引き起こす可能性があります。 誰かがそれらを評価するまで、推奨されません。
-
データのスパース性は、ユーザーベースのレコメンダーの品質に影響を与え、上記のコールドスタートの問題に追加される可能性があります。
-
複雑さは大きくなりすぎる可能性があるため、スケーリングはデータセットの成長にとって困難な場合があります。 データセットが大きい場合、アイテムベースのレコメンダーはユーザーベースのレコメンダーよりも高速です。
-
簡単な実装では、推奨事項がすでに人気があり、long tailセクションの項目が無視される可能性があることに気付くかもしれません。
長所と短所の独自のリストを持つすべてのタイプのリコメンダーアルゴリズムでは、通常、救助に来るのはハイブリッドレコメンダーです。 一緒にまたはパイプラインで動作する複数のアルゴリズムの利点は、より正確なレコメンダーのセットアップに役立ちます。 実際、Netflix賞の受賞者のソリューションは、複数のアルゴリズムの複雑な組み合わせでもありました。
結論
これで、協調フィルタリングタイプレコメンダーの計算と、データセットでさまざまなタイプのアルゴリズムをすばやく試して、協調フィルタリングが有効かどうかを確認する方法がわかりました。 高い精度でデータに適合していないように思われる場合でも、説明したユースケースのいくつかは、長期的にハイブリッドな方法で物事を計画するのに役立つ場合があります。
実装のほか、協調フィルタリングやその他の推奨アルゴリズムの詳細を読むためのリソースを次に示します。
図書館:
-
LightFM:Pythonのハイブリッドレコメンデーションアルゴリズム
-
Python-recsys:レコメンダーシステムを実装するためのPythonライブラリ
研究論文:
-
Item Based Collaborative Filtering Recommendation Algorithms:アイテムベースの推奨者に公開された最初の論文
-
Using collaborative filtering to weave an information tapestry:協調フィルタリングという用語の最初の使用
本:
-
Mining of Massive Datasets by Jure Leskovec、Anand Rajaraman、Jeff Ullman
-
Programming Collective Intelligence by Toby Segaran