Pytorch Bi-LSTM + CRF 代码详解
久聞LSTM + CRF的效果強大,最近在看Pytorch官網文檔的時候,看到了這段代碼,前前后后查了很多資料,終于把代碼弄懂了。我希望在后來人看這段代碼的時候,直接就看我的博客就能完全弄懂這段代碼。
看這個博客之前,我首先建議看看
Pytorch 關于Bi-LSTM + CRF的解釋
看完再看看這位的博客
Bi-LSTM-CRF for Sequence Labeling PENG
這兩部分內容都看完了之后,我就接著上面這位的博客繼續講,他講的很好了,只是沒有講的更細致。
首先我們來看看Score的定義:
這部分博主的解釋很詳細了,這里我想多提醒一下的是,我們的每一個Score都是對應于一個完整的路徑,舉例說
【我 愛 中國人民】對應標簽【N V N】那這個標簽就是一個完整的路徑,也就對應一個Score值。
接下來我想講的是這個公式
?
這個公式成立是很顯然的,動筆算一算就知道了,代碼里其實就是用了這個公式的原理,但是這位博主并沒有詳細解釋代碼是怎么實現這個公式的,所以我就寫下這篇博客來完成這位博主沒有做完的工作。
先上代碼
def _forward_alg(self, feats):
# Do the forward algorithm to compute the partition function
init_alphas = torch.Tensor(1, self.tagset_size).fill_(-10000.)
# START_TAG has all of the score.
init_alphas[0][self.tag_to_ix[START_TAG]] = 0.
# Wrap in a variable so that we will get automatic backprop
forward_var = autograd.Variable(init_alphas)
# Iterate through the sentence
for feat in feats:
alphas_t = [] # The forward variables at this timestep
for next_tag in range(self.tagset_size):
# broadcast the emission score: it is the same regardless of
# the previous tag
emit_score = feat[next_tag].view(
1, -1).expand(1, self.tagset_size)
# the ith entry of trans_score is the score of transitioning to
# next_tag from i
trans_score = self.transitions[next_tag].view(1, -1)
# The ith entry of next_tag_var is the value for the
# edge (i -> next_tag) before we do log-sum-exp
next_tag_var = forward_var + trans_score + emit_score
# The forward variable for this tag is log-sum-exp of all the
# scores.
alphas_t.append(log_sum_exp(next_tag_var))
forward_var = torch.cat(alphas_t).view(1, -1)
terminal_var = forward_var + self.transitions[self.tag_to_ix[STOP_TAG]]
alpha = log_sum_exp(terminal_var)
return alpha
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
我們看到有這么一段代碼
next_tag_var = forward_var + trans_score + emit_score
我們主要就是來講講他。
首先這個算法的思想是:假設我們要做一個詞性標注的任務,對句子【我 愛 中華人民】,我們要對這個句子做
意思就是 對這個句子所有可能的標注,都算出來他們的Score,然后按照指數次冪加起來,再取對數。一般來說取所有可能的標注情況比較復雜,我們這里舉例是長度為三,但是實際過程中,可能比這個要大得多,所以我們需要有一個簡單高效得算法。也就是我們程序中得用得算法, 他是這么算得。
先算出【我, 愛】可能標注得所有情況,取 log_sum_exp 然后加上 轉換到【中國人民】得特征值 再加上【中國人民】對應得某個標簽得特征值。其等價于【我,愛,中國人民】所有可能特征值指數次冪相加,然后取對數
接下來我們來驗證一下是不是這樣
首先我們假設詞性一共只有兩種 名詞N 和 動詞 V
那么【我,愛】得詞性組合一共有四種 N + N,N + V, V + N, V + V
那么【愛】標注為N時得log_sum_exp 為
log(escore(N,N)+score(V,N))
log(escore(N,N)+score(V,N))
【愛】 標注為 V時的 log_sum_exp為
log(escore(N,V)+score(V,V))
log(escore(N,V)+score(V,V))
我們的forward列表里就是存在著這兩個值,即:
[
log(escore(N,N)+score(V,N))
log(escore(N,N)+score(V,N))
,
log(escore(N,N)+score(V,N))
log(escore(N,N)+score(V,N))
]
在這里我在提醒一下score(N,V)的定義,前面有寫哈,可以翻前面取看看。
假設【中華人民】得詞性為N,我們按照代碼來寫一下公式,在forward列表對應位置相加就是這樣
[
log(escore(N+N)+score(V+N)+N+N?>N)
log(escore(N+N)+score(V+N)+N+N?>N)
,
log(escore(N,V)+score(V,V))+N+V?>N
log(escore(N,V)+score(V,V))+N+V?>N
]
我們的N+N->N可以寫成 log(eN+N?>N)log(eN+N?>N),這樣的話,我們的列表就變成
[
log(escore(N,N)+score(V,N)+N+N?>N)log(escore(N,N)+score(V,N)+N+N?>N),
log(escore(N,V)+score(V,V)+N+V?>N)log(escore(N,V)+score(V,V)+N+V?>N),
]
再次回想一下score的定義,我們就能知道這個式子其實也就是等于
[
log(escore(?,N,N))log(escore(?,N,N)),log(escore(?,V,N)log(escore(?,V,N)
]
我們對這個式子 long_sum_exp就變成了log∑(escore(?,?,N))log∑(escore(?,?,N))
他的直觀意義就是【中華人民】的詞性為N的時候,整個score值的long_sum_exp
以上是我們把【中華人民】作為N的舉例,如果我們再舉V的情況,計算過程同上,最后我們要把 中華人民兩種情況的再做一次log_sum_exp,這樣我們就完成了【我,愛,中華人民】所有情況的score值的log_sum_exp
以上就是對LSTM+crf 的所有講解,有問題,請留言
---------------------
作者:Johnny_Cuii
來源:CSDN
原文:https://blog.csdn.net/cuihuijun1hao/article/details/79405740
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
總結
以上是生活随笔為你收集整理的Pytorch Bi-LSTM + CRF 代码详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pytorch方法,Tensor及其基本
- 下一篇: pytorch lstm crf 代码理