2020-05-08に投稿

アニメのレコメンドサービスを作りました。

サービスURL

https://annict-suggest.netlify.app/

アニメの類似性をどう計算するか

コサイン類似度

人工知能を使わずにアニメのレコメンドサービスを作ろうと思ったのがきっかけです。
ユークリッド距離は触ったことがあるので、他の指標としてコサイン類似度が面白そうだと思いました。
ユークリッド距離は2点間の距離、コサイン類似度は2点のベクトル同士の角度です。

使った指標

約3300の作品に対して「見た」「見てない」のベクトルを作ってコサイン類似度を算出しようとしました。
「あにこれ」のように成分分析されているタグの類似度を計算するのもありだと思いました。

挫折

導入は比較的楽なように思えたのですが、計算量が尋常ではありませんでした。事前にフィルタリングを何もかけていなかったため、3300レコードx3300レコードの計算をしようとしていて、あまりに時間がかかるので諦めました。

結局SQL

例:ID4342の作品を見たユーザを抽出して、
それらのユーザが他に見た作品のうち共通している人数が多い順に30件を取得する。

select 
    sum(st2.watch_status) as count,
    st2.work_id,
    w.title
from status st2
-- ID:4342の作品を見たユーザを取得
inner join (
    select 
        st.user_id 
    from status st
    where st.work_id = 4342
 )st3
on st2.user_id = st3.user_id
inner join works w
on w.annict_id = st2.work_id
-- 作品自身を除く
where st2.work_id != 4342
group by st2.work_id
order by count desc
limit 30

今回使った技術

  • GraphQL(Annict API)
  • ReactJS
  • NodeJS(TypeScript)
  • twitterAPI
  • netlify

データの棲み分け

最新のデータが欲しい場合はAnnictAPI(GraphQL)、分析データが欲しい場合はDBから読み込み、というようにデータの棲み分けを行っています。

GraphQLでエイリアスを使う

Annict API
ユーザが見たアニメと見ているアニメ両方が欲しい場合、
エイリアスを使うと複数条件が記述できる。

query {
      user(username:"${username}"){
       annictId,
       works(state:WATCHED){
         nodes{
           annictId
           title
         }
       }
      ing:works(state:WATCHING){
         nodes{
           annictId
           title
         }
       }
      }
    }

CSP(コンテンツセキュリティポリシー)

アニメのOGPがない場合は公式twitterアカウントの画像を使用しているが、CSPなどで同じサイトでないコンテンツは表示できなくなったので、
URLに「twitter」が含まれる場合はサーバにプロキシさせて画像を読み込むようにした。

ご意見

こちらから使ってみた感想・ご意見をお寄せください。

ツイッターでシェア
みんなに共有、忘れないようにメモ

ckoshien

個人開発5年目。普段はフロントエンドエンジニア。 ReactJS/NextJS/NodeJS/ReactNative/Java

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント