nikkie-ftnextの日記

イベントレポートや読書メモを発信

イベントレポート | (第87回)Python mini Hack-a-thon #pyhack

はじめに

だんないよ、nikkieです。
土曜日は#pyhackに参加してきました。(3月は#rettypy優先したので2月以来の参加)

 

勉強会の概要

(第87回)Python mini Hack-a-thon - connpass

この勉強会について

基本的に毎月開催です。スプリントのゆるい版みたいな感じで各自自分でやりたいことを持ってきて、勝手に開発を進めています。参加費は無料です。 初めての方も常連さんもぜひご参加ください。

独学している身としては猛者同士のちょっとした会話からも勉強できる場です。
なるべく毎回行きたいなあと思っています。

取り組んだこと

『仕事ではじめる機械学習』の7章(映画のレコメンドの章)を写経しました。
1月から3ヶ月ほど弊社にてレコメンドシステムの開発に携わっていたので、
振り返って総括するために写経することにしました。(どうやるべきだったか知りたかった)
開発ではAzure Machine LearningでMicrosoft謹製のレコメンドアルゴリズムを使って実装したのですが、
レコメンド予測モデルがブラックボックスすぎるので理解を深めたいという気持ちもありました。
 
仮想環境作って写経スタートと思いきや。。
pip installに失敗するエラーが発生。(pipのバージョンも上げられず、原因不明)
かしゅーさんに診ていただきつつ、Python3.6系を導入してpip installはできるようになりました。
かしゅーさん、ありがとうございました!
venvに代えてvirtualenv使おう。pipのバージョンアップも自動で適用されるところに魅力を感じる。
 

写経

  • 推薦システム構築に使うライブラリ:fastFM
  • ユーザIDと商品IDはカテゴリ変数として扱う。(→One-hot Encoding)
  • データは3種類
    ユーザ情報(例:ユーザID=U001の名前はnikkie、男性、、)
    レーティング情報(例:ユーザU001が映画M12345を☆5(=最高評価)と評価)
    映画情報(例:M12345はタイトルが『さよ朝』、公開が2018年、、)
  • pandasを使ってデータを探索
    pd.mergeでDataFrameの同じ名前の列同士を内部結合。
    古い映画ほど評価データの数が多い。(古い映画ほど多くの人が評価)
    映画ごとの平均評価を出す上では、評価の数が100以上のようにフィルターをかける必要あり
    ユーザ1人あたりの評価した映画数の中央値は65本(平均が106本なので、数多く見ている人に引っ張られている)
    ユーザ1人あたりの評価値の平均は25%〜75%が☆3台:(▲)
    →平均評価が高い映画を評価しているユーザの属性など、もっと探索は深められそう
  • アルゴリズムMCMCを採用(ハイパーパラメタが少ないのが長所)
    レーティング情報だけを用いる
    イテレーション回数を300までで変化させ、平均二乗誤差やハイパーパラメタの様子を見ると、100回程度で収束している
    行列を圧縮する次数rankを変化させて平均二乗誤差(性能指標)を見ると、rank=32以降は収束している(ユーザの映画への評価値を予測しているので、平均二乗誤差が求まる)
    (▲)から、ユーザごとに平均評価値にばらつきがあったので標準化する
  • イテレーション回数とrankが決まった後は、ユーザ情報と映画情報も加える
    加える特徴量の数パターン用意し、平均二乗誤差を比較する
    →ユーザの年齢、性別、評価した年、映画の公開日を加えるとよさそう
  • pandasでの処理の書き方勉強になる
    movie_stats = lens.groupby('title').agg({'rating': [np.size, np.mean]})
    list(filtered_lens.drop('rating', axis=1).T.to_dict().values())
    lens['date'].apply(str).str.split('-').str.get(0)
  • Cell 21に不要なコードありませんか?
    (不要と思う点1箇所目)同内容の繰り返し
    lens['year'] = lens['date'].apply(str).str.split('-').str.get(0)
    lens['release_year'] = lens['release_date'].apply(str).str.split('-').str.get(2)
    (不要と思う点2箇所目)y_predに代入していないfm.fit_predict、不要じゃないでしょうか?
    fm.fit_predict(X_mf_train, y_mf_train_norm, X_mf_test)
    MCMCでは学習と予測をセットで行うfit_predictメソッドしか提供されていないそうなので、
    上記の箇所とy_predへの代入の箇所で全く同じことを重ねて行っている認識。
    指摘箇所を削ったところ、結果は変わらずに待ち時間は減った(ただし体感)。
  • p.156に誤植発見(Cell21が正しい)
    誤:y_mf_train_norm = scaler.fit_transform(np.array(y_mf_train)).ravel()
    正:y_mf_train_norm = scaler.fit_transform(np.array(y_mf_train).reshape(-1, 1)).ravel()
  

感想

人に説明できるレベルでは理解できていない感じ。もう少し取り組んでみる。

pandasの書き方は大変勉強になりました。使いこなせるよう自分でもこのデータ探索してみよう。

fastFMはチュートリアルがあるようなので、手を動かしてみたい。

Tutorials — fastFM 0.2.10 documentation

Azure MLのレコメンドのサンプルデータをfastFMで動かして
同じ結果を得られることを確認してはじめて脱ブラックボックスかなと思う。

 

nobolisさんの三角グラフ、画像をRGBで表すのによさそう。

 

運営及び参加者の皆さま、1日どうもありがとうございました!