如果想理解湯普森采樣算法,就必須先熟悉了解貝塔分布。
一、Beta(貝塔)分布
Beta分布是一個定義在[0,1]區間上的連續概率分布族,它有兩個正值參數,稱為形狀參數,一般用α和β表示,Beta分布的概率密度函數形式如下:
這里的Γ表示gamma函數。
Beta分布的均值是:
方差:
Beta分布的圖形(概率密度函數):
從Beta分布的概率密度函數的圖形我們可以看出,Beta分布有很多種形狀,但都是在0-1區間內,因此Beta分布可以描述各種0-1區間內的形狀(事件)。因此,它特別適合為某件事發生或者成功的概率建模。同時,當α=1,β=1的時候,它就是一個均勻分布。
貝塔分布主要有 α和 β兩個參數,這兩個參數決定了分布的形狀,從上圖及其均值和方差的公式可以看出:
1)α/(α+β)也就是均值,其越大,概率密度分布的中心位置越靠近1,依據此概率分布產生的隨機數也多說都靠近1,反之則都靠近0。
2)α+β越大,則分布越窄,也就是集中度越高,這樣產生的隨機數更接近中心位置,從方差公式上也能看出來。
二、舉例理解Beta分布
貝塔分布可以看作是一個概率的分布,當我們不知道一個東西的具體概率是多少時,它給出了所有概率出現的可能性大小,可以理解為概率的概率分布。
以棒球為例子:
棒球運動的一個指標就是棒球擊球率,就是用一個運動員擊中的球數除以總的擊球數,一般認為0.27是一個平均的擊球水平,如果擊球率達到0.3就會認為非常優秀了。如果我們要預測一個棒球運動員,他整個賽季的棒球擊球率,怎么做呢?你可以直接計算他目前的棒球擊球率,用擊中數除以擊球數。但是,這在賽季開始階段時是很不合理的。假如這個運動員就打了一次,還中了,那么他的擊球率就是100%;如果沒中,那么就是0%,甚至打5、6次的時候,也可能運氣爆棚全中擊球率100%,或者運氣很糟擊球率0%,所以這樣計算出來的擊球率是不合理也是不准確的。
為什么呢?
當運動員首次擊球沒中時,沒人認為他整個賽季都會一次不中,所以擊球率不可能為0。因為我們有先驗期望,根據歷史信息,我們知道擊球率一般會在0.215到0.36之間。如果一個運動員一開始打了幾次沒中,那么我們知道他可能最終成績會比平均稍微差一點,但是一般不可能會偏離上述區間,更不可能為0。
如何解決呢?
一個最好的方法來表示這些先驗期望(統計中稱為先驗(prior))就是貝塔分布,表示在運動員打球之前,我們就對他的擊球率有了一個大概范圍的預測。假設我們預計運動員整個賽季的擊球率平均值大概是0.27左右,范圍大概是在0.21到0.35之間。那么用貝塔分布來表示,我們可以取參數 α=81,β=219,因為α/(α+β)=0.27,圖形分布也主要集中在0.21~0.35之間,非常符合經驗值,也就是我們在不知道這個運動員真正擊球水平的情況下,我們先給一個平均的擊球率的分布。
假設運動員一次擊中,那么現在他本賽季的記錄是“1次打中;1次打擊”。那么我們更新我們的概率分布,讓概率曲線做一些移動來反應我們的新信息。
Beta(α0+hits,β0+misses)
注:α0,β0是初始化參數,也就是本例中的81,219。hits表示擊中的次數,misses表示未擊中的次數。
擊中一次,則新的貝塔分布為Beta(81+1,219),一次並不能反映太大問題,所以在圖形上變化也不大,不畫示意圖了。然而,隨着整個賽季運動員逐漸進行比賽,這個曲線也會逐漸移動以匹配最新的數據。由於我們擁有了更多的數據,因此曲線(擊球率范圍)會逐漸變窄。假設賽季過半時,運動員一共打了300次,其中擊中100次。那么新的貝塔分布是Beta(81+100,219+200),如下圖:
可以看出,曲線更窄而且往右移動了(擊球率更高),由此我們對於運動員的擊球率有了更好的了解。新的貝塔分布的期望值為0.303,比直接計算100/(100+200)=0.333要低,是比賽季開始時的預計0.27要高,所以貝塔分布能夠拋出掉一些偶然因素,比直接計算擊球率更能客觀反映球員的擊球水平。
總結:
這個公式就相當於給運動員的擊中次數添加了“初始值”,相當於在賽季開始前,運動員已經有81次擊中219次不中的記錄。 因此,在我們事先不知道概率是什么但又有一些合理的猜測時,貝塔分布能夠很好地表示為一個概率的分布。
三、湯普森采樣
湯普森采樣的背后原理正是上述所講的Beta分布,你把貝塔分布的 a 參數看成是推薦后用戶點擊的次數,把分布的 b 參數看成是推薦后用戶未點擊的次數,則湯普森采樣過程如下:
1、取出每一個候選對應的參數 a 和 b;
2、為每個候選用 a 和 b 作為參數,用貝塔分布產生一個隨機數;
3、按照隨機數排序,輸出最大值對應的候選;
4、觀察用戶反饋,如果用戶點擊則將對應候選的 a 加 1,否則 b 加 1;
注:實際上在推薦系統中,要為每一個用戶都保存一套參數,比如候選有 m 個,用戶有 n 個,那么就要保存 2 m n個參數。
湯普森采樣為什么有效呢?
1)如果一個候選被選中的次數很多,也就是 a+b 很大了,它的分布會很窄,換句話說這個候選的收益已經非常確定了,就是說不管分布中心接近0還是1都幾乎比較確定了。用它產生隨機數,基本上就在中心位置附近,接近平均收益。
2)如果一個候選不但 a+b 很大,即分布很窄,而且 a/(a+b) 也很大,接近 1,那就確定這是個好的候選項,平均收益很好,每次選擇很占優勢,就進入利用階段。反之則有可能平均分布比較接近與0,幾乎再無出頭之日。
3)如果一個候選的 a+b 很小,分布很寬,也就是沒有被選擇太多次,說明這個候選是好是壞還不太確定,那么分布就是跳躍的,這次可能好,下次就可能壞,也就是還有機會存在,沒有完全拋棄。那么用它產生隨機數就有可能得到一個較大的隨機數,在排序時被優先輸出,這就起到了前面說的探索作用。
python代碼實現:
choice = numpy.argmax(pymc.rbeta(1 + self.wins, 1 + self.trials - self.wins))