#IGMCを試してみた
GNNを作ったレコメンドシステムを探していたら、
面白そうな論文と著者のgithub(MITライセンス)を見つけたので試しに動かしてみました。
なので備忘録がわりにこの記事を書いています。
間違っている箇所も有るかも知れませんが、その時はご指摘いただけると幸いです。
#IGMCとは
側面情報を用いない行列補完をGNNを用いて行うモデル。
行列の補完を何に使うかと言うと、
例えばユーザーを行とアイテムを列としたときにそのアイテムへの評価を要素にすると評価の高いものを予測するレコメンドに使える。
このシステムの売りは
- 側面情報を用いないので情報を登録していないユーザーなどにも使える
- グラフ全体ではなく目標となるユーザーやアイテムの近傍のサブグラフを学習に用いるので、新しいユーザーやアイテムにも学習せずに対応できる
- 上の性質からスパースなデータにも対応できる
- 転移学習が容易
ちなみに側面情報を用いて学習を行うことも出来ます。
#何をしてるのか詳しく見てみる
入力されるデータはユーザーuがアイテムiに対して行った評価rのセット。u*iの行列で表されるものをu,vをノードとして評価が有るものだけを関係rのエッジとしてもつ2部グラフに置き換えます。
ユーザーとユーザー、アイテムとアイテムをつなぐノードは考えません。
評価rは離散値で例えば大変良かったを5大変悪かったを1とする5段階評価です。
学習ではその2部グラフ全てを使うのではなく関係を推定したいユーザーとアイテム周辺のサブグラフを用いて学習します。入力データには推定したいユーザーとアイテムをつなぐエッジは存在しません。(学習時にはこのエッジはもともと存在するので削除する)
サブグラフの取得方法は目標となるユーザー、アイテムからのh-hop近傍をとってきていています。
通常入力や出力はユーザーIDやアイテムIDをそのまま使いますが、この論文では違っていて、
これを取得する際にどのhopでサブグラフに始めて含まれたかによってノードにラベルづけを行っています。
つまり目標となるユーザー、アイテムには0,1のラベルが与えられ、そのノードから遠ければ遠いほど大きい数字のラベルがついていきま。す(ユーザーは奇数、アイテムは偶数に制限してユーザーのノードとアイテムのノードが混合しないようにしている)
図にするとこんな感じ
橙が新ラベル、赤エッジが予測したいエッジ黒エッジが予測したいエッジの近傍のエッジ青文字が評価(関係)
特定のユーザーIDやアイテムIDを使っていないので新しいユーザーやアイテムに対しても対応できるということでしょう。
GNNの形はメッセージ通過層としてR-GCNを関係を評価rとして使用し、
2つの層の間にtanh活性化を持つL個のメッセージ通過層を積み重ね
その結果をconcatして
そのなかから目標のユーザーとアイテムを指すものだけを取り出しconcatしたものをプール層としてそれにMLPを掛けてその出力と正解ラベルのMSEで学習しているみたいです。
(正解ラベルは目標ユーザーが目標アイテムに行った評価の値)
……文章で書いてもわかりにくいのでgithubのコード見たほうがわかりやすいと思います。
また、評価一つ一つをR-GCNの関係として入れているため評価が連続値であり評価1よりも4のほうが5に近いことを教えてあげる必要が有るようで隣接する評価のR-GCNの重みが異なるほどlossに重みを加えているようです。
#実際に動かしてみる
実際に動かしてみます、作業OSはUbuntu16.04です。
githubからコードをcloneしてきて、
githubにかかれている通りpytorchとPyTorch_Geometricをインストールすれば動くはずです。
以下おまかんだと思うのですが躓いたところを書いていきます。
-
PyTorch 1.4.0、なんたら.soがないと怒られてる
代わりに1.7.0を入れて解決しました。 -
LIBCXX_3.4.22がないと怒られる
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install gcc-4.9
sudo apt upgrade libstdc++6
参考
https://github.com/lhelontra/tensorflow-on-arm/issues/13
-
joblib内でTypeError: an integer is required (got type bytes)
joblibのバージョンを0.14以上にする -
RGCNConv' object has no attribute 'att
train_eval.pyの170-171行目を
gconv.comp,
gconv.weight.view(gconv.num_bases, -1)
にする
参考
https://github.com/muhanzhang/IGMC/issues/7
自分で作ったデータを使いたい場合
data_utils.pyのml-10mのコードを使いまわすのが一番簡単
データをダウンロードする代わりに
ユーザーID,アイテムID,評価,タイムスタンプの形式で適当な区切り符号でつなげたものを自分で作成したデータとして読み込ませる。
実行結果はこんな感じ
今回はIGMCを動かして見ました。
参考になれば幸いです。