私は自分でビデオポータル用に1つ作成しました。私が持っていた主なアイデアは、すべてに関するデータを収集することでした。
- 誰がビデオをアップロードしましたか?
- 誰がビデオにコメントしましたか?
- どのタグが作成されましたか?
- 誰がビデオを訪れましたか?(匿名の訪問者も追跡します)
- 誰がビデオを好きでしたか?
- 誰がビデオを評価しましたか?
- ビデオはどのチャンネルに割り当てられましたか?
- タイトル、説明、タグ、チャネル、コメントのテキストストリームは、各データソースに重点を置くフルテキストインデクサーによって収集されます。
次に、上記の各ポイントの(id、weight)タプルのリストを返す関数を作成しました。限られた量の動画(たとえば、最後の50)のみを考慮するものもあれば、評価、タグ数(より頻繁にタグ付けされる=表現力が低い)などによって重みを変更するものもあります。次のリストを返す関数があります。
- 全文検索による類似の動画
- 同じユーザーがアップロードした動画
- これらのコメントからのユーザーがコメントした他のビデオ
- これらのお気に入りのユーザーがお気に入りに追加した他の動画
- これらの評価の評価者が評価した他の動画(加重)
- 同じチャンネルの他の動画
- 同じタグを持つ他の動画(タグの「表現力」で重み付け)
- このビデオを再生した人が再生した他のビデオ(XY最新の再生)
- コメント全文による同様のビデオ
- タイトル全文による類似のビデオ
- 説明全文による類似のビデオ
- タグ全文による類似の動画
これらはすべて、ビデオIDで重みを合計し、重みで並べ替えるだけで1つのリストにまとめられます。これは現在、約1000本のビデオでかなりうまく機能します。ただし、これを高速化するには、バックグラウンド処理または極端なキャッシュを実行する必要があります。
私はこれをすぐに一般的なレコメンデーションエンジンまたは類似性計算機に減らして、rails/activerecordプラグインとしてリリースできることを望んでいます。現在、それはまだ私のプロジェクトのよく統合された部分です。
ちょっとしたヒントを与えるために、ルビーコードでは次のようになります。
def related_by_tags
tag_names.find(:all, :include => :videos).inject([]) { |result,t|
result + t.video_ids.map { |v|
[v, TAG_WEIGHT / (0.1 + Math.log(t.video_ids.length) / Math.log(2))]
}
}
end
他の人がそのようなアルゴリズムをどのように解決するかに興味があります。