Gibbs sampler

今天將這個所學到的寫入到這裏以來保留自己學過的痕跡。
Gibbs採樣器主要的用途是用來採樣的,那麼能不能在開始的時候給自己提幾個問題呢?
1.爲什麼要用Gibbs採樣,採用Gibbs採樣有哪些好處?
2.Gibbs採樣是否正確?得到的樣本是否爲所服從的分佈?
3.採樣需要注意哪些問題?
1.我們來看,如果現在給定一個高斯分佈模型,其中的參數都爲已知,那麼我們怎麼樣從這個高斯分佈中用計算機來生成一些樣本呢?
首先得關注樣本的取值範圍,即定義域。對於高斯分佈模型有:高斯分佈的概率密度函數的定義域爲(-Inf,Inf),但是,在計算機中,或是現實生活中沒有Inf,所以我們就這樣做:對於[-3σ,3σ]暫居了很大一部分概率,因此,我們可以將範圍擴展到[-9σ,9σ].即高斯分佈模型的定義域爲:[-3σ,3σ].
2.定義域知道後怎麼來採樣呢?
    a。將這個定義域分割成很多小格子,然後取格子中間的x值?那麼你這樣取出來的絕對不會服從高斯模型了。
    b。將定義域分成很多格子,對於每一個格子的x值用中間值代替,然後計算每一個格子的概率,以這個概率(例如,用均勻分佈rand函數來產生一個數,當這個數小於這個概率值時我們接受這個x值,當大於這個概率值時,我們拒絕這個x值)來決定什麼時候接受和什麼時候拒絕。當然非常的接近了,但是,我們對於格子中的值選取的是其中值,這樣我們還是不能完美的得到樣本數據。當然可以將格子分的很小,以致我們不能夠觀察出什麼不對。這個方法是可行的。
   那麼上面這個方法有什麼不足嗎?首先,我們需要計算每個格子的概率,多大的格子合適呢,x的值該怎麼取呢?不可否認,這是一個採樣器,但有多的限制。
   c。對於多維概率模型,是不是這樣取值很麻煩呢?對我看來,這是很麻煩的事情。


Gibbs採樣器:
Gibbs採樣器一般運用到高維數據採樣的問題中。一維中可以採用MCMC採樣器來進行採樣。
Gibbs採樣器需要知道分佈的確定表示形式,即聯合分佈模型必需確定,但不必知道邊緣分佈概率。下面就是Gibbs採樣器的步驟:
這裏先特定到二維p(x,y)
      a.選擇一個y0,然後用y0來確定p(x,y0)。這樣我們就直接的降掉了一維,此時可以用MCMC或其它方法從p(x,y0)中來產生一個x0.
      b.得到x0後,我們可以用x0來確定p(x0,y),同理可以用p(x0,y)來得到y1.然後再用y1得到x1.
      c.以此不斷循環,就能得到二維p(x,y)分佈的樣本:(x0,y0),(x1,y1),(x2,y2),.... ...
對於多維,其實就是一樣的了,對於p(x,y,z,...),如果我們先求x,那麼就要先初始化y,z,...;然後用初始化的y,z,...來求x,然後固定x,z,...來求y,等等,這樣循環下去。
下面是自己編寫的一個Gibbs採樣器:
%% Gibbs sampler
%產生樣本的分佈爲一個二維的:p(x,y) = n!/(n-x)!x!*y.^(x+a-1)*(1-y).^(n-x+b-1);
%Gibbs sampler原理是:
%1. 首先從x,y中選點一個,這裏選定y,則我們在y的範圍內給y選一個值,得到一個y0
%2. 其次將y0代入到p(x,y)中去得到p(x|y=y0)下的一個分佈,然後我們從這個分佈中產生一個x。
%   當然,這個邊緣分佈可能交複雜,但是我們可以採用MCMC來進行了,這樣得到x0
%3. 將x0代入到p(x,y)中去,得到p(y|x=x0)下的一個分佈,我們從這個分佈中得到y1。
%4. 然後又由y1產生x1,以此這樣循環,自己設定一個循環結束條件:迭代多少次(k)後終止。

len = 20000;
sample = zeros(len,2);
y0 = 0.5 ; %  0< y < 1
k = 1 ;
n = 10 ;
a = 1 ;
b = 2 ;
num = 10 ;
while k <= len
    sample(k,2) = y0 ;
    x0 = 5 ;
    i = 1 ;
    while i <= num 
          pxy0 = factorial(n)/ (factorial(n-x0)*factorial(x0) )* y0.^(x0+a-1)*(1-y0).^(n-x0+b-1);
          x1 = randi([1,10]);
          pxy1 = factorial(n)/ (factorial(n-x1)*factorial(x1) )* y0.^(x1+a-1)*(1-y0).^(n-x1+b-1);
          judge = pxy1/pxy0 ;
          if judge >= 1
              x0 = x1 ;
              i = i + 1 ;
          else
              if rand() < judge
                   x0 = x1 ;
                   i = i + 1 ;
              end
          end
    end
    %得到了x0
    sample(k,1) = x0 ;
    %去獲得y1
    i = 1 ;
        while i <= num 
          pyx0 = factorial(n)/ (factorial(n-x0)*factorial(x0) )* y0.^(x0+a-1)*(1-y0).^(n-x0+b-1);
          y1 = rand();
          pyx1 = factorial(n)/ (factorial(n-x0)*factorial(x0) )* y1.^(x0+a-1)*(1-y1).^(n-x0+b-1);
          judge = pyx1/pyx0 ;
          if judge >= 1
              y0 = y1 ;
              i = i + 1 ;
          else
              if rand() < judge
                   y0 = y1 ;
                   i = i + 1 ;
              end
          end
        end
     k = k + 1 ;
end
%% 畫圖
xx = 1:1:10;
yy = 0:0.01:1;
z = getResult(n,a,b);
mesh(z);
myhist = getHist(sample(100:len,:),xx,yy,1,0.01);
figure;
mesh(myhist);

%%
getResult函數如下:
function z = getResult(n,a,b)
%% 得到一個二維矩陣的結果
xx = 1:1:10;
yy = 0:0.01:1;
lenx = length(xx);
leny = length(yy);
z = zeros(lenx,leny);
for i=1:lenx
    z(i,:) = factorial(n)./ (factorial(n-i).*factorial(i) ).* yy.^(i+a-1).*(1-yy).^(n-i+b-1);
end

%% getHist函數如下:
function myhist = getHist(sample,x,y,dx,dy)
%% 產生二維直方圖
%Input:
%    sample:樣本,Nx2
%       x  : x方向上的間隔大小
%       y  : y方向上的間隔大小
%      dx  : x方向上的間隔
%      dy  : y方向上的間隔
%Output:
%       myhist:一個二維數組
if nargin < 4
    dx = x(1);
    dy = y(2);
end
row = length(x);
col = length(y);
fx = x(1);
fy = y(1);
myhist = zeros(row,col);
len = length(sample);
for i=1:len
     sx = sample(i,1);
     sy = sample(i,2);
     tx = ceil((sx - fx)/dx) +1 ;
     ty = ceil((sy - fy)/dy) ;
     myhist(tx,ty) = myhist(tx,ty) + 1 ;
end
myhist = myhist./len;
最後貼一個圖來看看採樣器的結果:
這是採樣器模擬出來的結果。
這是分佈函數的曲線
當然可以看出其實在圖上表現的有很大的不同,這主要是樣本數據少,再有就是在統計直方圖時,格子寬度的選取問題。以致不能得到平滑的曲線圖。(自己的臆斷!)
其中介紹一篇非常好的論文:《Markov Chain Monte Carlo and Gibbs Sampling》Lecture Notes for EEB 581, version 26 April 2004°c B. Walsh 2004。
發佈了31 篇原創文章 · 獲贊 9 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章