レコメンダーシステム:perl SVD

前のシリーズでは、特異分解(SVD)とは何かを説明し、基本的な予測子を使用して特異分解のモデルを定式化しました。 前回、私たちはすでに特定の更新式に問題をもたらしました。 今日は、非常に単純なモデルの非常に単純な実装を実証し、すでにおなじみの評価マトリックスに適用してから、結果が何であったかを説明します。





だから、PerlのSVD。 として実行できる完成したスクリプト
./svd.pl _ dataset.csv
      
      



こちらからダウンロードできます 。 トレーニング自体を行う一部を紹介します。



 #  SVD: ,    while (abs($old_rmse - $rmse) > 0.00001 ) { $old_rmse = $rmse; $rmse = 0; foreach my $u ( keys %l ) { foreach my $v ( keys %{$l{$u}} ) { #   $err = $l{$u}{$v} - ($mu + $b_u[$u] + $b_v[$v] + dot($u_f[$u], $v_f[$v]) ); #    $rmse += $err * $err; #      ... $mu += $eta * $err; $b_u[$u] += $eta * ($err - $lambda2 * $b_u[$u]); $b_v[$v] += $eta * ($err - $lambda2 * $b_v[$v]); # ...    for (my $f=0; $f < $features; ++$f) { $u_f[$u][$f] += $eta * ($err * $v_f[$v][$f] - $lambda2 * $u_f[$u][$f]); $v_f[$v][$f] += $eta * ($err * $u_f[$u][$f] - $lambda2 * $v_f[$v][$f]); } } } ++$iter_no; #   ,   RMSE $rmse = sqrt($rmse / $total); print "Iteration $iter_no:\tRMSE=" . $rmse . "\n"; #  RMSE  ,     if ($rmse > $old_rmse - $threshold) { $eta = $eta * 0.66; $threshold = $threshold * 0.5; } }
      
      





ご覧のとおり、絶対に大丈夫です-重みの更新プロセスを開始し、収束するまで続行するだけです。 収束は、RMSE(二乗平均平方根誤差)-二乗平均平方根誤差、つまり 二乗誤差の合計のルートをテストケースの数で割ったもの。 確率的勾配降下法を実装します。各テストケースの後、すぐにパラメーターを変更し、データベース全体でエラー統計を収集しません。



RMSEが著しく改善されなくなると、学習速度が低下します。 このアプローチでは、遅かれ早かれ、プロセスは収束するはずです(つまり、RMSEの変更が停止するはずです)。 ここでλとは何ですか-次に説明しますが、今日の例ではゼロになります。



次に、最初のテキストの1つで検討した評価マトリックスに、持っているものを適用します。

画像

適切な形式で、 ここからダウンロードできます (注文は保存されます)。 このデータセットでスクリプトを実行すると、次のようなものが得られます。

  5人のユーザーと5つのURLを読みます。
反復1:RMSE = 1.92845291697284
反復2:RMSE = 1.28481736445124
反復3:RMSE = 1.14159530044051
 ...
反復808:RMSE = 0.0580161117835789
反復809:RMSE = 0.0580061123741253
        mu:2.54559533638261
ユーザーベース:0.7271 0.1626 0.7139 1.9097 -0.9677	
アイテムベース:0.8450 0.6593 0.2731 0.7328 0.0354	
ユーザー機能
  ユーザー0:-0.5087 -0.8326	
  ユーザー1:1.0220 1.2826	
  ユーザー2:-0.9509 0.2792	
  ユーザー3:0.1031 -0.4814	
  ユーザー4:0.6095 0.0557	
アイテムの特徴:
  アイテム0:-0.8368 0.2511	
  アイテム1:1.1101 0.4120	
  アイテム2:-0.4159 -0.4073	
  アイテム3:-0.3130 -0.9115	
  アイテム4:0.6408 1.2205 
その結果、何が得られましたか? ほぼ予想どおり。 ユーザーは優しさに応じて基本的な予測因子を受け取りました。ペトロヴィッチは邪悪な観客であることが判明し、それとは対照的に、残りは優しく、特にジャンノチカです。 映画は、「全体的な品質」(評価によって自然に表現される)に従って基本的な予測因子を受け取りました。



しかし、最も興味深いのは、残りのユーザー設定を2つの要因に合理的に分解したことです。 この例はもちろんおもちゃであり、データセットは最初、映画が「子豚について」と「トラクターについて」の映画に分けられることを暗示していました。 強力な機器を好むユーザーもいれば、豚の軟骨が好きなユーザーもいます。



実際、最初の要因はトラクターに関するフィルムの量であり、2番目の要因は豚に関するフィルムの量であることは明らかです。 特定の値には深い意味はなく、それらの比率のみが重要です。



ちなみに、私はデータセットに特に適合しませんでした。この場合、兆候を伴うおかしなケースがありました。SVDは、トラクター、VasyaとValerikaが好きな2人のユーザーに「トラクター」係数の負の値を教えました。 しかしこれに伴い、SVDは実際にトラクターに関する映画の「トラクター」係数にマイナスの値を教えました。マイナスはマイナスになります。 そして、ペトラの1.0220とは正反対に、彼のトラクターは豚と比較してまったく興味がないということです...



これで、トラクタードライバーに対するVasyaの評価の値を次のように予測できます。

  2.5456 + 0.7271 + 0.8450 +(-0.5087)*(-0.8368)+(-0.8326)* 0.2511 = 4.3343143 


まあ、Vasyaがトラクタードライバーを好むと本当に仮定できました。



次回は、過剰適合と正則化について説明します-それが何であるか、なぜそれが必要であるか、そしてそれをSVDで実装する方法。



All Articles