畳庵〜tatamiya practice〜

機械学習・統計モデリング練習帳。読書・source code読みの記録や,実装など。

画像に直接レコメンドアルゴリズムを適用してみる〜通常の特異値分解とレコメンドのMatrix Factorizationで行列分解比較〜

昨日の記事で,レコメンドアルゴリズムを視覚的に理解するということで,FunkのMatrix Factorizationによる出力値をヒートマップにして表し,入力したUser-Item行列との比較を行いました。

tatamiya-practice.hatenablog.com

この中で,

  • 出力レコメンド評価値は「バイアス項+行列分解項」から成る
  • 行列分解項は入力行列を再現する方向に補正を行う
  • 因子数 dが大きくなるほど入力画像の再現度が高くなる

という解釈を行いました。

今回はこれを確かめるために,画像をUser-Item行列に見立ててFunkのレコメンドアルゴリズムを適用して, dが入力画像の列/行数に近づくにつれ出力が入力に近づいていくかを見ました。

例によって,実行コードは下記にアップしてあります。

numpyとscikit-learnで画像の特異値分解を試した。 · GitHub

Applying Recommendation Algorithms Directly to an Image Itself · GitHub

方法

入力画像

以下の謎のカボチャ画像を使います。

f:id:tatamiyatamiyatatatamiya:20200308135641p:plain

こちらは行数766列数796の行列で,ピクセル値が[0, 1]の範囲で入っています。

これを行: User, 列: ItemのUser-Item行列と見立て,行列分解を行います。

適用アルゴリズム

上記の2手法で画像を行列分解したのち,因子数 dで再構成します。

 dを変えながら,両手法の再構成後の画像の違いを見ていきます。

結果

因子数 d 通常の特異値分解 Funkのレコメンドアルゴリズム
1 f:id:tatamiyatamiyatatatamiya:20200308141303p:plain f:id:tatamiyatamiyatatatamiya:20200308140922p:plain
5 f:id:tatamiyatamiyatatatamiya:20200308141313p:plain f:id:tatamiyatamiyatatatamiya:20200308141009p:plain
766 f:id:tatamiyatamiyatatatamiya:20200308141328p:plain f:id:tatamiyatamiyatatatamiya:20200308141705p:plain

考察

両手法とも因子数 dを上げるほど入力画像に近づいていきます。

しかし,通常の特異値分解では dが入力行数である766に達した段階で元の画像が完璧に再現されるのに対して,Funkのレコメンドアルゴリズムではぼやけたままです。 *1

この違いは,Funkの方法ではバイアス項が加わっているためと考えられます。

Funkのレコメンドアルゴリズムの結果をよくみると, dが大きくなっても縦横の帯状の模様が残り続けるのが見て取れます。

Funkの方法で導入されたバイアス項は,User-Item行列で見た縦横の平均的な値を反映しているので,その影響として理解できそうです。

おわりに

やはり因子数 dを大きくすると,入力を再現する方向に出力が変化していくようです。

ただし,入力画像と出力画像の誤差をRMSEやMAEで評価すると,画像では dを大きくするについれ一様に誤差が小さくなっていくのに対して,User-Item行列ではある最適値以上では逆に誤差が大きくなっていくという違いがありました。(冒頭に貼ったURLを参照)

これについてははっきりと理由はわからないですが,入力データの滑らかさなどといった性質の違いに依存しそうです。

*1:特異値分解では原理的に dの最大値は入力行列のRankと一致し,この時厳密に入力行列が再現されます。一方でFunkのレコメンドアルゴリズムでは最適化手法により最も入力行列との誤差が小さくなる分解方法を探すので, dをいくらでも大きくできます。(ただ,パラメータ数が増えるので計算時間はかなり長くなりますが,,,)