重要性採樣(Importance Sampling)

文章轉自:http://blog.csdn.net/Dark_Scope/article/details/70992266

看了好多篇關於採樣,重要性採樣的文章,很多都有公式與概念的錯誤,這篇真是最良心的一篇,從頭到尾沒有發現錯誤,而且講得深入淺出,通俗易懂。

引子

最近開始拾起來看一些NLP相關的東西,特別是深度學習在NLP上的應用,發現採樣方法在很多模型中應用得很多,因爲訓練的時候如果預測目標是一個詞,直接的softmax計算量會根據單詞數量的增長而增長。恰好想到最開始深度學習在DBN的時候採樣也發揮了關鍵的作用,而自己對採樣相關的方法瞭解不算太多,所以去學習記錄一下,經典的統計的方法確實巧妙,看起來非常有收穫。

本篇文章先主要介紹一下經典的採樣方法如Inverse Sampling、Rejective Sampling以及Importance Sampling和它在NLP上的應用,後面還會有一篇來嘗試介紹MCMC這一組狂炫酷拽的算法。才疏學淺,行文若有誤望指正。

Why Sampling

採樣是生活和機器學習算法中都會經常用到的技術,一般來說採樣的目的是評估一個函數在某個分佈上的期望值,也就是

E[f(x)],xp,p is a distribution.

比如我們都學過的拋硬幣,期望它的結果是符合一個伯努利分佈的,定義正面的概率爲p,反面概率爲1p。最簡單地使f(x)=x,在現實中我們就會通過不斷地進行拋硬幣這個動作,來評估這個概率p。
E[f(x)]1mi=1mf(xi).  xip

這個方法也叫做蒙特卡洛法(Monte Carlo Method),常用於計算一些非常複雜無法直接求解的函數期望。
對於拋硬幣這個例子來說:
E[f(x)]=p1mi=1mxi=cntum

其期望就是拋到正面的計數cntu除以總次數m
而我們拋硬幣的這個過程其實就是採樣,如果要用程序模擬上面這個過程也很簡單,因爲伯努利分佈的樣本很容易生成:
yiUniform(0,1)so xi=I(y<p)

而在計算機中的隨機函數一般就是生成0到1的均勻分佈隨機數。

Sampling Method

可以看到蒙特卡洛法其實就是按一定的概率分佈中獲取大量樣本,用於計算函數在樣本的概率分佈上的期望。其中最關鍵的一個步驟就是如何按照指定的概率分佈p進行樣本採樣,拋硬幣這個case裏伯努利分佈是一個離散的概率分佈,它的概率分佈一般用概率質量函數(pmf)表示,相對來說比較簡單,而對於連續概率分佈我們需要考慮它的概率密度函數(pdf):
【圖pmf->pdf】
比如上圖示例分別是標準正態分佈概率密度函數,它們的面積都是1(這是概率的定義),如果我們可以按照相應概率分佈生成很多樣本,那這些樣本繪製出來的直方圖應該跟概率密度函數是一致的。
而在實際的問題中,p的概率密度函數可能會比較複雜,我們由淺入深,看看如何採樣方法如何獲得服從指定概率分佈的樣本。

Inverse Sampling

對於一些特殊的概率分佈函數,比如指數分佈:

pexp(x)={λexp(λx)0,x0,x<0

我們可以定義它的概率累積函數(Cumulative distribution function),也就是(ps.這個’F’和前面的’f’函數並沒有關係)
F(x)=xp(x)dx

從圖像上看就是概率密度函數小於x部分的面積。這個函數在x0的部分是一個單調遞增的函數(在定義域上單調非減),定義域和值域是[0,+)[0,1),畫出來大概是這樣子的一個函數,在p(x)大的地方它增長快(梯度大),反之亦然:

【exp dist的cdf】
因爲它是唯一映射的(在>0的部分,接下來我們只考慮這一部分),所以它的反函數可以表示爲F1(a)a[0,1),[0,+)

因爲F單調遞增,所以F1也是單調遞增的:

xyabF(x)F(y)F1(a)F1(b)

利用反函數的定義,我們有:
F1(a)<x,iff  a<F(x)

我們定義一下[0,1]均勻分佈的CDF,這個很好理解:
P(ax)=H(x)=1x0,x1,0x1,x<0

所以
P(F1(a)x)=P(aF(x))=H(F(x))F(x)[0,1)P(F1(a)x)=H(F(x))=F(x)

根據F(x)的定義,它是exp分佈的概率累積函數,所以上面這個公式的意思是F1(a)符合exp分佈,我們通過F的反函數將一個0到1均勻分佈的隨機數轉換成了符合exp分佈的隨機數,注意,以上推導對於cdf可逆的分佈都是一樣的,對於exp來說,它的反函數的形式是:
F1exp(a)=1λlog(1a)

具體的映射關係可以看下圖(a),我們從y軸0-1的均勻分佈樣本(綠色)映射得到了服從指數分佈的樣本(紅色)。
[圖ab,映射關係]
我們寫一點代碼來看看效果,最後繪製出來的直方圖可以看出來就是exp分佈的圖,見上圖(b),可以看到隨着採樣數量的變多,概率直方圖和真實的CDF就越接近:

def sampleExp(Lambda = 2,maxCnt = 50000):
    ys = []
    standardXaxis = []
    standardExp = []
    for i in range(maxCnt):
        u = np.random.random()
        y = -1/Lambda*np.log(1-u) #F-1(X)
        ys.append(y)
    for i in range(1000):
        t = Lambda * np.exp(-Lambda*i/100)
        standardXaxis.append(i/100)
        standardExp.append(t)
    plt.plot(standardXaxis,standardExp,'r')
    plt.hist(ys,1000,normed=True)
    plt.show()

Rejective Sampling

我們在學習隨機模擬的時候通常會講到用採樣的方法來計算π值,也就是在一個1×1的範圍內隨機採樣一個點,如果它到原點的距離小於1,則說明它在1/4圓內,則接受它,最後通過接受的佔比來計算1/4圓形的面積,從而根據公式反算出預估的π值,隨着採樣點的增多,最後的結果π^會越精準。
[1/4圓形] 代碼和結果
上面這個例子裏說明一個問題,我們想求一個空間裏均勻分佈的集合面積,可以嘗試在更大範圍內按照均勻分佈隨機採樣,如果採樣點在集合中,則接受,否則拒絕。最後的接受概率就是集合在‘更大範圍’的面積佔比。

當我們重新回過頭來看想要sample出來的樣本服從某一個分佈p,其實就是希望樣本在其概率密度函數p(x)高的地方出現得更多,所以一個直覺的想法,我們從均勻分佈隨機生成一個樣本xi,按照一個正比於p(xi)的概率接受這個樣本,也就是說雖然是從均勻分佈隨機採樣,但留下的樣本更有可能是p(x)高的樣本。

這樣的思路很自然,但是否是對的呢。其實這就是Rejective Sampling的基本思想,我們先看一個很intuitive的圖
[概率計算圖]
假設目標分佈的pdf最高點是1.5,有三個點它們的pdf值分別是

p(x1)p(x2)p(x3)=1.5;=0.5;=0.3;

因爲我們從x軸上是按均勻分佈隨機採樣的,所以採樣到三個點的概率都一樣,也就是
q(x1)=q(x2)=q(x3)

接下來需要決定每個點的接受概率acc(xi),它應該正比於p(xi),當然因爲是概率值也需要小於等於1.
我們可以畫一根y=2的直線,因爲整個概率密度函數都在這根直線下,我們設定
acc(xi)=p(xi)2;acc(x1)=0.75;acc(x2)=0.25;acc(x3)=0.15;

我們要做的就是生成一個0-1的隨機數xi,如果它小於接受概率acc(xi),則留下這個樣本。因爲accp,所以可以看到因爲p(x1)p(x2)的3倍,所以acc(x1)=3acc(x2)。同樣採集100次,最後留下來的樣本數期望也是3倍。這根本就是概率分佈的定義!

我們將這個過程更加形式化一點,我們我們又需要採樣的概率密度函數p(x),但實際情況我們很有可能只能計算出p~(x),有p(x)=p~(x)Zp。我們需要找一個可以很方便進行採樣的分佈函數q(x)並使

cq(x)p~(x)

其中c是需要選擇的一個常數。然後我們從q分佈中隨機採樣一個樣本xi,並以
acc(xi)=p~(xi)cq(xi)

的概率決定是否接受這個樣本。重複這個過程就是「拒絕採樣」算法了。

在上面的例子我們選擇的q分佈是均勻分佈,所以從圖像上看其pdf是直線,但實際上cq(x)p~(x)越接近,採樣效率越高,因爲其接受概率也越高:
P&Q

Importance Sampling

上面描述了兩種從另一個分佈獲取指定分佈的採樣樣本的算法,對於1.在實際工作中,一般來說我們需要sample的分佈都及其複雜,不太可能求解出它的反函數,但p(x)的值也許還是可以計算的。對於2.找到一個合適的cq(x)往往很困難,接受概率有可能會很低。
那我們回過頭來看我們sample的目的:其實是想求得E[f(x)],xp,也就是

E[f(x)]=xf(x)p(x)dx

如果符合p(x)分佈的樣本不太好生成,我們可以引入另一個分佈q(x),可以很方便地生成樣本。使得
xf(x)p(x)dxwhere  g(x)=xf(x)p(x)q(x)q(x)dx=xg(x)q(x)dx=f(x)p(x)q(x)=f(x)w(x)

我們將問題轉化爲了求g(x)q(x)分佈下的期望!!!
我們稱其中的w(x)=p(x)q(x) 叫做Importance Weight.

Importance Sample 解決的問題

首先當然是我們本來沒辦法sample from p,這個是我們看到的,IS將之轉化爲了從q分佈進行採樣;同時IS有時候還可以改進原來的sample,比如說:
[圖sample from q and p]
可以看到如果我們直接從p進行採樣,而實際上這些樣本對應的f(x)都很小,採樣數量有限的情況下很有可能都無法獲得f(x)值較大的樣本,這樣評估出來的期望偏差會較大

而如果我們找到一個q分佈,使得它能在f(x)p(x)較大的地方採集到樣本,則能更好地逼近[Ef(x)],因爲有Importance Weight控制其比重,所以也不會導致結果出現過大偏差。

所以選擇一個好的p也能幫助你sample出來的效率更高,要使得f(x)p(x)較大的地方能被sample出來。

無法直接求得p(x)的情況

上面我們假設g(x)q(x)都可以比較方便地計算,但有些時候我們這個其實是很困難的,更常見的情況市我們能夠比較方便地計算p~(x)q~(x)

p(x)=p~(x)Zpq(x)=q~(x)Zq

其中Zp/q是一個標準化項(常數),使得p~(x)或者p~(x)等比例變化爲一個概率分佈,你可以理解爲softmax裏面那個除數。也就是說
Zp=xp~(x)dxZq=xq~(x)dx

這種情況下我們的importance sampling是否還能應用呢?
xf(x)p(x)dxwhere  g~(x)=xf(x)p(x)q(x)q(x)dx=xf(x)p~(x)/Zpq~(x)/Zqq(x)dx=ZqZpxf(x)p~(x)q~(x)q(x)dx=ZqZpxg~(x)q(x)dx=f(x)p~(x)q~(x)=f(x)w~(x)
ZqZp我們直接計算並不太好計算,而它的倒數:
ZpZq=1Zqxp~(x)dxZq=q~(x)/q(x)ZpZq=xp~(x)q~(x)q(x)dx=xw~(x)q(x)dx

因爲我們家設能很方便地從q採樣,所以上式其實又被轉化成了一個蒙特卡洛可解的問題,也就是
ZpZq=1mi=1mw~(xi).   xiq

最終最終,原來的蒙特卡洛問題變成了
Ef(x)=1ni=1mw^(xi)f(xi).xiqw^(xi)=w~(xi)mi=1w~(xi)

所以我們完全不用知道q(x)確切的計算值,就可以近似地從中得到在q分佈下f(x)的取值!!amazing!

Importance Sampling在深度學習裏面的應用

在深度學習特別是NLP的Language Model中,訓練的時候最後一層往往會使用softmax函數並計算相應的梯度。
此處輸入圖片的描述
而我們知道softmax函數的表達式是:

P(yi)=softmax(xTwi)=exTwiZZ=j=1|V|exTwj

要知道在LM中m的大小是詞彙的數量決定的,在一些巨大的模型裏可能有幾十萬個詞,也就意味着計算Z的代價十分巨大。

而我們在訓練的時候無非是想對softmax的結果進行求導,也就是說

Δθ(logP(yi))=Δθ(xTwi)yVP(y)Δθ(xTw)

後面那一塊,我們好像看到了熟悉的東西,沒錯這個形式就是爲採樣量身定做似的。

yVP(y)Δθ(xTw)=EP[Δθ(xTw)]

經典的蒙特卡洛方法就可以派上用途了,與其枚舉所有的詞,我們只需要從V裏sample出一些樣本詞,就可以近似地逼近結果了。

同時直接從P中sample也不可取的,而且計算P是非常耗時的事情(因爲需要計算Z),我們一般只能計算P~(y),而且直接從P中sample也不可取,所以我們選擇另一個分佈Q進行Importance Sample即可。

一般來說可能選擇的Q分佈是簡單一些的ngram模型。下面是論文中的算法僞代碼,基本上是比較標準的流程(論文圖片的符號和上面的描述稍有出入,理解一下過程即可):
[圖片]

References

【1】mathematicalmonk’s machine learning course on y2b. machine learing
【2】Pattern Recognition And Machine Learning
【3】Adaptive Importance Sampling to Accelerate Training
of a Neural Probabilistic Language Model.Yoshua Bengio and Jean-Sébastien Senécal.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章