多様性の観点から検索/推薦モデルをオフライン評価する
多様性指向評価とは
背景
検索/推薦の精度評価には、accuracy-baseなもの(精度、正解率、ランキングなど)が評価としてよく使われます。NetflixやSpotifyなどは、ユーザの好みを開拓するレコメンドを評価するため、多様性、新規性、意外性などの観点からも評価すべきと述べています。本記事では、多様性、新規性、意外性の3つの指標を紹介します。
前提条件
多様性:Diversity
内容の似ていないアイテムどうしがレコメンドされている状態を、多様性と定義します。
新規性:Novelty
そのアイテムを消費したユーザーの少なさを、新規性として定義します。
意外性:Serendipity
過去にユーザーが消費したアイテムと、レコメンドアイテムが似通っていない状態を、意外性と定義します。
注意点
多様性指向評価については、ネットで調べると複数の定義が出てきますが、ユーザの好み(prefs)を考慮するものが現在は優勢であると考えられています。本記事でもユーザの好みを考慮した定義を採用しています。
多様性指向評価の実装
prefs関数の定義
def prefs(item_id):
return len(dataset[dataset['item_id']==item_id])
def prefs_both(item_id1, item_id2):
df_both = dataset[
(dataset['item_id']==item_id1) |
(dataset['item_id']==item_id2)
]
series_user = df_both['user_id'].value_counts()
return series_user[series_user==2].count()
# 高速化のため、Dictionaryにする
prefs_dict = {}
for item_id in uq_items:
prefs_dict[item_id] = prefs(item_id)
ここで、消費データ(
dataset:過去の消費データ[dataframe:"user_id","item_id"]
df_recommend_list:推薦データ[dataframe:"user_id","item_id"]
とします。
ユーザーごとの多様性の計算
def diversity_user(user_id):
diversity_score = 0.0
rec_list_user = \
df_recommend_list[
df_recommend_list['user_id']==user_id
]['item_id']
for x1, x2 in list(
itertools.combinations(rec_list_user, 2)
):
pref_both = prefs_both(x1, x2)
if pref_both != 0:
diversity_score += \
np.sqrt(prefs_dict[x1]) * \
np.sqrt(prefs_dict[x2]) / pref_both
return diversity_score
ユーザーごとの新規性の計算
def novelty_user(user_id):
novelty_score = 0.0
rec_list_user = df_recommend_list[
df_recommend_list['user_id']==user_id
]['item_id']
for rec_item in rec_list_user:
pref = prefs(rec_item)
if pref != 0:
novelty_score += np.log2(n_users/pref) / topk
return novelty_score
ユーザーごとの意外性の計算
def serendipity_user(user_id):
serendipity_score = 0.0
rec_list_user = df_recommend_list[
df_recommend_list['user_id']==user_id
]['item_id']
con_list_user = dataset[
dataset['user_id']==user_id
]['item_id']
for rec_item, con_item in list(
itertools.product(rec_list_user, con_list_user)
):
pref_both = prefs_both(rec_item, con_item)
if pref_both != 0:
serendipity_score += \
np.sqrt(prefs_dict[rec_item]) * \
np.sqrt(prefs_dict[con_item]) / pref_both
return serendipity_score / len(con_list_user)
多様性指向評価の計算
def calc_diversity_oriented_score():
#初期化
diversity = 0.0
novelty = 0.0
serendipity = 0.0
# ユーザーごとのスコアを算出し加算する
for user_id in uq_users:
diversity += diversity_user(user_id)
novelty += novelty_user(user_id)
serendipity += serendipity_user(user_id)
# 平均を取る
diversity /= n_users
novelty /= n_users
serendipity /= n_users
return diversity, novelty, serendipity
これらの多様性指向の評価を取り入れることにより、新規作成した検索/推薦モデルについて、実サービスに出さずともバイアスの影響を受けずにオフライン評価することが可能です。
フィシルコムのテックブログです。マーケティングSaaSを開発しています。 マイクロサービス・AWS・NextJS・Golang・GraphQLに関する発信が多めです。 カジュアル面談はこちら(ficilcom.notion.site/bbceed45c3e8471691ee4076250cd4b1)から
Discussion