はじめに
僕は以前はよく映画を観ていた。
でもそれは学生までだった。
社会人になったら時間が無くなる。
それまでは、結構チャレンジして映画は観ていた。
自分の苦手そうな作品も観ていた。
だけど、そんなこともできなくなった。
今は数か月に1回観るか観ないか。
映画を観たときの価値観が増える感覚も、観始めるときのわくわく感もなくなってしまった。
だから、自分が好みの映画を見つけられるようなサービスを作ってみようと思った。
機能と仕組み
今回作成したサービスは、フロントエンドはReactとTypescript。バックエンドはRust。DBはPostgreSQLで作られている。
サービスを使っている様子はこんな👇感じ。

画像やあらすじのデータは映画.comとwikipediaから取得している。
機能
機能としては大きく2つ。
- 「新しい映画を見つける」モード
- 「気分で探す」モード
「新しい映画を見つける」モードでは、上記の画像のように映画を2択から選んでいき、選んだ映画の類似度から好みの映画を見つけられるようにしている。
「気分で探す」モードでは、その日みたい映画の気分を選んでから、映画を2択から選んでいき、その日の気分に合わせた映画をチョイスしてくれるものである。
仕組みの中ではイロレーティングを使用している。
$$E_a = \frac{1}{1 + 10^{(R_b – R_a)/400}}$$
$$E_b = \frac{1}{1 + 10^{(R_a – R_b)/400}}$$
勝者の更新:
$$R’_a = R_a + K(1 – E_a)$$
敗者の更新:
$$R’_b = R_b + K(0 – E_b)$$
(この実装では $K = 24$ を使用している。)
アルゴリズム
好みの映画を見つけるのに、2つのフェーズがある。
- 1つ目のフェーズは「イロレーティングで好みの順位を作る」フェーズ
- 2つ目のフェーズは「ランキングからプロフィールを作り、映画に適用する」フェーズ
の2つである。
フェーズ1:「イロレーティングで好みの順位を作る」
映画を2択から選んでいく中で、以下のイロレーティングが計算されていく。
- 勝ち側の新レーティング = 現レーティング + 24 × (1.0 – 期待スコア)
- 負け側の新レーティング = 現レーティング + 24 × (0.0 – 期待スコア)
このフェーズで自分が見た映画の相対ランキングを作る。
フェーズ2:「ランキングからプロフィールを作り、映画に適用する」
フェーズ1で、イロレーティングが平均以上の映画を「好みの映画」と判定する。
その映画のあらすじ・監督・脚本家・制作国・キャストを特徴量として重み付き集計する。
平均以下の映画は「嫌いな特徴」として別集計している。
スコア = イロレーティング + あらすじ類似度 × 520 + 監督一致 × 45 + 脚本一致 × 35 + 制作国一致 × 28 + キャスト一致 × 18 + 上映時間近さ × 10 + 製作年近さ × 8 – 嫌いな特徴ペナルティ
あらすじ類似度は2文字バイグラムのオーバーラップ率を用いて、テーマや雰囲気の近さを間接的に捉える。
バイグラムは「再会」「別れ」「家族」「故郷」のような核心的な単語は1語がまるごと2〜3個のバイグラムを共有するので、テーマが近いほど一致数が増える仕組みである。
例えば、
映画A「幼い頃に離れ離れになった姉妹が、旅の途中で再会する」
→ {幼い, い頃, 頃に, に離, 離れ, れ離, 離れ, れに, にな, なっ, った, た姉, 姉妹, 妹が, が旅, 旅の, の途, 途中, 中で, で再, 再会, 会す, する}
映画B「長年疎遠だった兄弟が、父の遺言をきっかけに再会する」
→ {長年, 年疎, 疎遠, 遠だ, だっ, った, た兄, 兄弟, 弟が, が父, 父の, の遺, 遺言, 言を, をき, きっ, っか, かけ, けに, に再, 再会, 会す, する}
一致した断片: った 再会 会す する
→「離れていた家族が再び出会う」という共通テーマが文字の断片として浮かび上がるといった具合である。
これから
今はここまでだが、実際に使ってみると、本当に自分の好みなのか?と思う映画が結果として出力されてしまう。
精度がまだ低い。
今後はこの精度を上げていく必要がある。
でも、本音は精度を上げるのは難しいと思う。
最後に
さらに精度を上げていって、いずれはサービスとしてリリースしたい。
