#コンテンツベースフィルタリングとは
コンテンツベースフィルタリングはユーザーが評価したデータをもとに、そのユーザーの嗜好に合ったコンテンツを勧める方法のことです。
例えば、今まで見たアニメのなかで、「ソードアートオンライン」と「ダンジョンに出会いを求めるのは間違っているだろうか」を高評価にしているユーザー(自分とか)は「ファンタジー」「バトル」を嗜好としているため、2019年冬アニメは「盾の勇者の成り上がり」をみるといいかもしれない。
協調フィルタリングとは違い、他のユーザーのデータを必要としません。
#コンテンツベースフィルタリングの実装
コンテンツベースフィルタリングは以下の方法で実装していきます。
- 単語がアイテムの中でどれだけ重要かを求め、これを並べて特徴ベクトルをつくる
- 求めた特徴ベクトルを他アイテムの特徴ベクトルと比較してコサイン類似度を求める
- 類似度の高いデータをレコメンドする
##特徴ベクトルを抽出する
文書中に含まれる単語の重要度を評価する手法の1つにtf-idfがあります。
tf-idfはtf(term Frequency、単語の出現頻度)とidf(Inverse Document Frequency、逆文書頻度)の2つの指標に基づいて計算されます。tfとidfは以下の式で計算できます。
$$TF=\frac{文章中に含まれる調べたい単語の出現回数}{文章に含まれる全ての単語の出現回数の和}$$
$$ITF=log\frac{総文書数}{その単語が出現する文章の数}+1$$
Pythonでコードを書くと以下の通りになります。
import numpy as np
import math
docs = [
['ラノベ','ゲーム','仮想','RPG','オンライン','最強','人工知能','仮想','ゲーム','ファンタジー','近未来','バトル','剣','戦闘','プレイヤー']
,['ラノベ','ラブコメ','ファンタジー','ダンジョン','最強','バトル','異世界','コミカル','ライバル','必殺技','熱い']
,['異世界','召喚','バトル','ファンタジー','勇者','裏切り','冒険','戦闘','ラノベ','仲間','2クール','魔法','召喚','成長','決闘']
]
data = []
def tf(docs):
words = set(docs)
tf_values = np.array([docs.count(doc) for doc in words])
tf_list = (tf_values/sum(tf_values)).tolist()
return tf_list
def idf(words, docs):
words = set(words)
idf_list = np.array([math.log10((len(docs)+1)/(sum([word in doc for doc in docs])+1)) for word in words])
return idf_list
tf = tf(docs[0])
idf = idf(docs[0], docs)
tfidf = tf*idf
for i,word in enumerate(set(docs[0])):
data.append([word, tfidf[i]])
data = sorted(data, key=lambda x: x[1], reverse=True)
print(data)
Pythonだとscikit-learnのTfidfVectorizerを使うことでtf-idfを計算できます。
こちらのほうが高速で正確かと思います。
##類似度を判定する
コサイン類似度を使って特徴ベクトルの類似度判定を行います。
三角関数のコサインより、1に近ければ類似しており、0に近ければ似ていないということになります。
import numpy as np
def cos_sim(v1, v2):
return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))
X = np.array([5, 2, 3, 0, 1, 2])
Y = np.array([2, 1, 5, 0, 5, 4])
print(cos_sim(X, Y)) #=>0.7239300246860821
#参考
TF-IDF で文書をベクトル化。python の TfidfVectorizer を使ってみる
scikit-learnでtf-idfを計算する
自然言語処理の基礎技術!tf-idfを簡単に解説!
【Python】コサイン類似度