條件隨機場
馬爾可夫過程
定義
假設一個隨機過程中, 時刻的狀態的條件發佈,只與其前一狀態 相關,即:
則將其稱爲 馬爾可夫過程。
隱馬爾科夫算法
定義
隱馬爾科夫算法是對含有未知參數(隱狀態)的馬爾可夫鏈進行建模的生成模型,如下圖所示:
在隱馬爾科夫模型中,包含隱狀態 和 觀察狀態,隱狀態 對於觀察者而言是不可見的,而觀察狀態 對於觀察者而言是可見的。隱狀態間存在轉移概率,隱狀態 到對應的觀察狀態 間存在輸出概率。
假設
- 假設隱狀態 的狀態滿足馬爾可夫過程,i時刻的狀態 的條件分佈,僅與其前一個狀態相關,即:
- 假設觀測序列中各個狀態僅取決於它所對應的隱狀態,即:
存在問題
在序列標註問題中,隱狀態(標註)不僅和單個觀測狀態相關,還和觀察序列的長度、上下文等信息相關。例如詞性標註問題中,一個詞被標註爲動詞還是名詞,不僅與它本身以及它前一個詞的標註有關,還依賴於上下文中的其他詞。
條件隨機場 (以線性鏈條件隨機場爲例)
定義
給定 , 均爲線性鏈表示的隨機變量序列,若在給隨機變量序列 X 的條件下,隨機變量序列 Y 的條件概率分佈 構成條件隨機場,即滿足馬爾可夫性:
則稱爲 P(Y|X) 爲線性鏈條件隨機場。
通過去除了隱馬爾科夫算法中的觀測狀態相互獨立假設,使算法在計算當前隱狀態時,會考慮整個觀測序列,從而獲得更高的表達能力,並進行全局歸一化解決標註偏置問題。
參數化形式
其中:
爲歸一化因子,是在全局範圍進行歸一化,枚舉了整個隱狀態序列的全部可能,從而解決了局部歸一化帶來的標註偏置問題。
爲定義在邊上的特徵函數,轉移特徵,依賴於前一個和當前位置
爲定義在節點上的特徵函數,狀態特徵,依賴於當前位置。
特徵函數, 取值爲1或0:當滿足特徵條件的時取值爲1
簡化形式
因爲條件隨機場中同一特徵在各個位置都有定義,所以可以對同一個特徵在各個位置求和,將局部特徵函數轉化爲一個全局特徵函數,這樣就可以將條件隨機場寫成權值向量和特徵向量的內積形式,即條件隨機場的簡化形式。
step 1
將轉移特徵和狀態特徵及其權值用統一的符號表示,設有k1個轉移特徵,個狀態特徵,,記
step 2
對轉移與狀態特徵在各個位置i求和,記作
step 3
將 和 用統一的權重表示,記作
step 4
轉化後的條件隨機場可表示爲:
step 5
若 表示權重向量:
以 表示特徵向量,即
則,條件隨機場寫成內積形式爲:
矩陣形式
推導 begin
推導 end
基本問題
條件隨機場包含概率計算問題、學習問題和預測問題三個問題。
- 概率計算問題:已知模型的所有參數,計算觀測序列 出現的概率,常用方法:前向和後向算法;
- 學習問題:已知觀測序列 ,求解使得該觀測序列概率最大的模型參數,包括隱狀態序列、隱狀態間的轉移概率分佈和從隱狀態到觀測狀態的概率分佈,常用方法:Baum-Wehch 算法;
- 預測問題:一直模型所有參數和觀測序列 ,計算最可能的隱狀態序列 ,常用算法:維特比算法。
概率計算問題
給定條件隨機場,輸入序列 和 輸出序列 ;
計算條件概率
計算相應的數學期望問題;
前向-後向算法
step 1 前向計算
對觀測序列 的每個位置 ,定義一個 階矩陣( 爲標記取值的個數)
對每個指標 ,定義前向向量 ,則遞推公式:
其中,
step 2 後向計算
對每個指標 ,定義前向向量 ,則遞推公式:
step 3
step 4 概率計算
所以,標註序列在位置 是標註 的條件概率爲:
其中,
step 5 期望值計算
通過利用前向-後向向量,計算特徵函數關於聯合概率分佈 和 條件概率分佈 的數學期望,即特徵函數 關於條件概率分佈 的數學期望:
其中:
學習問題
這裏主要介紹一下 BFGS 算法的思路。
輸入:特徵函數 :經驗分佈 ;
輸出:最優參數值 ,最優模型。
- 選定初始點 w^{(0)}, 取 爲正定對稱矩陣,k = 0;
- 計算 ,若 ,則停止計算,否則轉 (3) ;
- 利用 計算 ;
- 一維搜索:求 使得
-
設
-
計算 = g(w^{(k+1)}),
若 , 則停止計算;否則,利用下面公式計算 :
-
令 ,轉步驟(3);
預測問題
對於預測問題,常用的方法是維特比算法,其思路如下:
輸入:模型特徵向量 和權重向量 ,輸入序列(觀測序列) ;
輸出:條件概率最大的輸出序列(標記序列),也就是最優路徑;
- 初始化
- 遞推,對
- 終止
- 返回路徑
求得最優路徑
例子說明
利用維特比算法計算給定輸入序列 對應的最優輸出序列:
- 初始化
- 遞推,對
- 終止
- 返回路徑
求得最優路徑
import numpy as np
class CRF(object):
'''實現條件隨機場預測問題的維特比算法
'''
def __init__(self, V, VW, E, EW):
'''
:param V:是定義在節點上的特徵函數,稱爲狀態特徵
:param VW:是V對應的權值
:param E:是定義在邊上的特徵函數,稱爲轉移特徵
:param EW:是E對應的權值
'''
self.V = V #點分佈表
self.VW = VW #點權值表
self.E = E #邊分佈表
self.EW = EW #邊權值表
self.D = [] #Delta表,最大非規範化概率的局部狀態路徑概率
self.P = [] #Psi表,當前狀態和最優前導狀態的索引表s
self.BP = [] #BestPath,最優路徑
return
def Viterbi(self):
'''
條件隨機場預測問題的維特比算法,此算法一定要結合CRF參數化形式對應的狀態路徑圖來理解,更容易理解.
'''
self.D = np.full(shape=(np.shape(self.V)), fill_value=.0)
self.P = np.full(shape=(np.shape(self.V)), fill_value=.0)
for i in range(np.shape(self.V)[0]):
#初始化
if 0 == i:
self.D[i] = np.multiply(self.V[i], self.VW[i])
self.P[i] = np.array([0, 0])
print('self.V[%d]='%i, self.V[i], 'self.VW[%d]='%i, self.VW[i], 'self.D[%d]='%i, self.D[i])
print('self.P:', self.P)
pass
#遞推求解佈局最優狀態路徑
else:
for y in range(np.shape(self.V)[1]): #delta[i][y=1,2...]
for l in range(np.shape(self.V)[1]): #V[i-1][l=1,2...]
delta = 0.0
delta += self.D[i-1, l] #前導狀態的最優狀態路徑的概率
delta += self.E[i-1][l,y]*self.EW[i-1][l,y] #前導狀態到當前狀體的轉移概率
delta += self.V[i,y]*self.VW[i,y] #當前狀態的概率
print('(x%d,y=%d)-->(x%d,y=%d):%.2f + %.2f + %.2f='%(i-1, l, i, y, \
self.D[i-1, l], \
self.E[i-1][l,y]*self.EW[i-1][l,y], \
self.V[i,y]*self.VW[i,y]), delta)
if 0 == l or delta > self.D[i, y]:
self.D[i, y] = delta
self.P[i, y] = l
print('self.D[x%d,y=%d]=%.2f\n'%(i, y, self.D[i,y]))
print('self.Delta:\n', self.D)
print('self.Psi:\n', self.P)
#返回,得到所有的最優前導狀態
N = np.shape(self.V)[0]
self.BP = np.full(shape=(N,), fill_value=0.0)
t_range = -1 * np.array(sorted(-1*np.arange(N)))
for t in t_range:
if N-1 == t:#得到最優狀態
self.BP[t] = np.argmax(self.D[-1])
else: #得到最優前導狀態
self.BP[t] = self.P[t+1, int(self.BP[t+1])]
#最優狀態路徑表現在存儲的是狀態的下標,我們執行存儲值+1轉換成示例中的狀態值
#也可以不用轉換,只要你能理解,self.BP中存儲的0是狀態1就可以~~~~
self.BP += 1
print('最優狀態路徑爲:', self.BP)
return self.BP
def CRF_manual():
S = np.array([[1,1], #X1:S(Y1=1), S(Y1=2)
[1,1], #X2:S(Y2=1), S(Y2=2)
[1,1]]) #X3:S(Y3=1), S(Y3=1)
SW = np.array([[1.0, 0.5], #X1:SW(Y1=1), SW(Y1=2)
[0.8, 0.5], #X2:SW(Y2=1), SW(Y2=2)
[0.8, 0.5]])#X3:SW(Y3=1), SW(Y3=1)
E = np.array([[[1, 1], #Edge:Y1=1--->(Y2=1, Y2=2)
[1, 0]], #Edge:Y1=2--->(Y2=1, Y2=2)
[[0, 1], #Edge:Y2=1--->(Y3=1, Y3=2)
[1, 1]]])#Edge:Y2=2--->(Y3=1, Y3=2)
EW= np.array([[[0.6, 1], #EdgeW:Y1=1--->(Y2=1, Y2=2)
[1, 0.0]], #EdgeW:Y1=2--->(Y2=1, Y2=2)
[[0.0, 1], #EdgeW:Y2=1--->(Y3=1, Y3=2)
[1, 0.2]]])#EdgeW:Y2=2--->(Y3=1, Y3=2)
crf = CRF(S, SW, E, EW)
ret = crf.Viterbi()
print('最優狀態路徑爲:', ret)
return
if __name__=='__main__':
CRF_manual()
self.V[0]= [1 1] self.VW[0]= [1. 0.5] self.D[0]= [1. 0.5]
self.P: [[0. 0.]
[0. 0.]
[0. 0.]]
(x0,y=0)-->(x1,y=0):1.00 + 0.60 + 0.80= 2.4000000000000004
(x0,y=1)-->(x1,y=0):0.50 + 1.00 + 0.80= 2.3
self.D[x1,y=0]=2.40
(x0,y=0)-->(x1,y=1):1.00 + 1.00 + 0.50= 2.5
(x0,y=1)-->(x1,y=1):0.50 + 0.00 + 0.50= 1.0
self.D[x1,y=1]=2.50
(x1,y=0)-->(x2,y=0):2.40 + 0.00 + 0.80= 3.2
(x1,y=1)-->(x2,y=0):2.50 + 1.00 + 0.80= 4.3
self.D[x2,y=0]=4.30
(x1,y=0)-->(x2,y=1):2.40 + 1.00 + 0.50= 3.9000000000000004
(x1,y=1)-->(x2,y=1):2.50 + 0.20 + 0.50= 3.2
self.D[x2,y=1]=3.90
self.Delta:
[[1. 0.5]
[2.4 2.5]
[4.3 3.9]]
self.Psi:
[[0. 0.]
[0. 0.]
[1. 0.]]
最優狀態路徑爲: [1. 2. 1.]
最優狀態路徑爲: [1. 2. 1.]
CRF 模型 可以 解決什麼問題?
比如邏輯迴歸,接着用模型去預測這一天的每張照片最可能的活動標記。
這種辦法雖然是可行的,但是卻忽略了一個重要的問題,就是這些照片之間的順序其實是有很大的時間順序關係的,而用上面的方法則會忽略這種關係。比如我們現在看到了一張Bob閉着嘴的照片,那麼這張照片我們怎麼標記Bob的活動呢?比較難去打標記。但是如果我們有Bob在這一張照片前一點點時間的照片的話,那麼這張照片就好標記了。如果在時間序列上前一張的照片裏Bob在喫飯,那麼這張閉嘴的照片很有可能是在喫飯咀嚼。而如果在時間序列上前一張的照片裏Bob在唱歌,那麼這張閉嘴的照片很有可能是在唱歌。」
舉個例子把,比如 天氣預測,序列標註,還是這個 圖片排序,都是有一個特點,那就是 有 相互依賴關係」
比如,對於 詞性標註 任務,每個詞的詞性往往和上下文的詞的詞性有關
step 2 : CRF 模型的歷史?(隨機場->HMM->MEMM->CRF)
寧靜致遠:
「我:「我:「我:【問題】step 2 : CRF 模型的歷史?(隨機場->HMM->MEMM->CRF)」
聊聊 隨機場唄:每個位置按照某種分佈隨機賦予一個值 所構成 的 整體。」
馬爾可夫過程:由於 每個狀態間 是以 有向直線連接,也就是 當前時刻狀態 僅與上一時刻狀態相關。」
HMM 比較核心了,首先需要 找到他的一些東西,比如 兩序列:觀測序列和隱藏序列,其實 只要 能夠 轉化爲 已知一個序列,然後去預測另外一個序列 的 問題 , 而且 每個節點相關, 都可以用 CRF,
金金金:
對呀,就還是HMM的那兩個基本假設;CRF解除了這兩個假設?
金金金:
MEMM是解除了觀測變量的獨立性假設
從有向到無向是解除了t時刻狀態變量僅受t-1時刻狀態變量的假設