1. 程式人生 > >推薦系統的探索與利用問題綜述

推薦系統的探索與利用問題綜述

1.簡述

問題引入

  • 推薦系統冷啟動問題常見的一種解決方案就是利用Bandit演算法,Bandit演算法通常用於解決探索與利用問題,其中解決探索與利用問題的經典案例是MAB問題;

  • 這裡MAB問題有三個概念:臂,收益,遺憾
    • 1.臂:實際可以選擇的物件,這裡的臂可以是推薦系統中的策略或者內容分類,一般情況下臂的數量應該小於選擇的次數,這樣才能保證收斂。
    • 2.收益:選擇了臂後對應的單次收益,在推薦系統中可以理解為點選或者購買某個物品
    • 3.遺憾:單次收益與最優收益的差
  • 目標與建模:
    所以我們的目標就是在有限的N次選擇中儘量使得累計遺憾最低

\[ \text{數學建模:} R_{T} = \sum_{i=1}^{T}(W_{opt}-W_{B(i)})\text{,其中}R_T\text{代表累計遺憾;T是總選擇次數;} W_{opt}\text{是最優收益;}W_{B(i)}\text{是第i次選擇獲得的收益} \]

\[ \text{特別地,當每次選擇的收益是0或者1時,稱為伯努利收益;上式可以化簡為如下形式:} R_{T} = T - \sum_{i=1}^{T-N}0\text{,這裡的N是取到收益1的次數} \]

UCB演算法介紹

計算公式

Upper Confidence Bound,即置信區間上界
置信區間可以簡單直觀地理解為不確定性的程度,區間越寬,越不確定,反之就很確定。

\[ score(i) = \frac{N_i}{T} + \sqrt{\frac{2\ln_T}{N_i}} \text{,其中}N_i\text{代表第i個臂收益為1的次數;T是總選擇次數。注:這裡直接給出了結論,推導部分見附錄} \]

對公式的理解:

  • 公式有兩部分,加號前面是這個候選臂到目前的平均收益,反應了它的效果,後面的叫做 Bonus,本質上是均值的標準差,反應了候選臂效果的不確定性,就是置信區間的上邊界。
  • 如果一個臂的選擇次數很少,即N很小,那麼它的 Bonus 就會較大,在最後排序輸出時有優勢,這個 Bonus 反映了一個候選的收益置信區間寬度,Bonus 越大,候選的平均收益置信區間越寬,越不確定,越需要更多的選擇機會。反之如果平均收益很大,就是說加號左邊很大,也會在被選擇時有優勢。

2.實踐

import numpy as np

# T個使用者/T次曝光
T = 1000
# N個電影/N個電影品類
N = 10

# 保證結果可復現
np.random.seed(888)
# 每部電影累積點選率(理論概率)
true_rewards = np.random.uniform(low=0, high=1, size=N)
# 每部電影當前點選率(實際頻率)
estimated_rewards = np.zeros(N)
# 每部電影點選次數
chosen_count = np.zeros(N)
total_reward = 0


def calculate_delta(T, item):
    if chosen_count[item] == 0:
        return 1
    else:
        return np.sqrt(2 * np.log(T) / chosen_count[item])


def UCB(t, N):
    # UCB得分
    upper_bound_probs = [estimated_rewards[item] + calculate_delta(t, item) for item in range(N)]
    item = np.argmax(upper_bound_probs)
    # 模擬伯努利收益
    reward = np.random.binomial(n=1, p=true_rewards[item])
    return item, reward


# T個使用者/T次曝光依次發生
for t in range(1, T):
    # 為第t個使用者推薦一部電影,reward = 1 表示使用者點選觀看,reward = 0 表示使用者未點選
    item, reward = UCB(t, N)
    # print("item, reward = %s,%s" % (item, reward))
    # 一共有多少使用者接受了推薦/N部電影的點選次數
    total_reward += reward

    # 更新電影的當前點選率
    estimated_rewards[item] = ((t - 1) * estimated_rewards[item] + reward) / t
    # print(estimated_rewards[item])
    chosen_count[item] += 1
    # 輸出當前點選率
    # print(t,estimated_rewards)
    # 輸出累積點選率
    # print(t,true_rewards)
    diff = np.subtract(true_rewards,estimated_rewards)
    print(diff[0])
    
0.8595606060609418
0.35956060606094176
0.19289393939427513
0.10956060606094176
0.2595606060609418
...
0.01640294418596766
0.016245471958934443
0.01709132465111296
0.01693347823970004
0.016775947837118665

3.擴充套件

其他Bandit 演算法

  • 1.湯普森取樣演算法
  • 2.Epsilon 貪婪演算法
  • 3.效果對比
    完全隨機:就是不顧使用者反饋的做法。
    樸素選擇:就是認準一個效果好的,一直推。
    Epsilon 貪婪演算法:每次以小概率嘗試新的,大概率選擇效果好的。
    UCB:每次都會給予機會較少的候選一些傾向。
    湯普森取樣:用貝塔分佈管理每一個候選的效果。

其他的臂

  • 1.新使用者:冷啟動策略
  • 2.新策略/新模型

方法擴充套件

1.LinUCB(加入了特徵的UCB)
2.COFIBA演算法(將Bandit演算法與協同過濾結合使用)

4.附錄

17【MAB問題】簡單卻有效的Bandit演算法
Bandit演算法與推薦系統
UCB公式的理解
專治選擇困難症——bandit演算法
Multi-Armed Bandit: UCB (Upper Bound Confidence)
Bandit演算法,A/B測試,孰優孰劣?
【MAB問題】結合上下文資訊的Bandit算