CRF的實現(xiàn)-tensorflow版本

0.前言

CRF的原理已經(jīng)夠難理解了,需要解決的問題主要包括三大塊:

  • 概率計算問題,前向—后向算法庄呈,是一個遞推公式,這個和hmm是一樣的派阱。
  • 學(xué)習(xí)問題诬留,這是判別式模型必須要有的東西,得訓(xùn)練參數(shù)贫母,常用的方法是改進(jìn)的迭代尺度法文兑,擬牛頓法。
  • 預(yù)測問題腺劣,維特比算法绿贞,這是個動態(tài)規(guī)劃方法,hmm和crf都會用到橘原。這個好像廢話籍铁,目的都是為了預(yù)測,當(dāng)然要用靠柑。
    數(shù)學(xué)公式一大堆寨辩,什么向量形式,矩陣形式歼冰,著實難以理解,但是關(guān)于事先就很簡單了耻警,哈哈哈隔嫡。下面分別基于tensorflow甸怕、keras、pytorch來實現(xiàn)CRF腮恩。

1.tensorflow實現(xiàn)

tensorflow1.0可真難用啊梢杭,吐槽一下,還是2.0好用秸滴。舉個小例子武契,你定義一個op操作以后,即使是簡單的x1+x2荡含,要想看輸出咒唆,還得print(sess.run()),2.0就不用了释液,大家趕緊上手2.0全释。不過這里還是基于tensorflow1.0實現(xiàn)的。
tensorflow實現(xiàn)crf就三個函數(shù)误债,crf_log_likelihood浸船、viterbi_decode、crf_decode寝蹈,他們都在tf.contrib.crf這個API里李命,搞懂這三個函數(shù),不管事BiLSTM+CRF還是BERT+BiLSTM+CRF你都游刃有余了箫老。

  • tf.contrib.crf.crf_log_likelihood
    crf_log_likelihood(inputs,tag_indices,sequence_lengths,transition_params=None)
    通俗理解封字,這是CRF的訓(xùn)練函數(shù)。
    首先來看輸入:
    (1)inputs槽惫,維度為[batch_size, max_seq_len, num_tags]周叮,一般是LSTM的輸出,要轉(zhuǎn)換成這個要求的維度界斜,再到CRF里邊訓(xùn)練仿耽。
    batch_size是批次訓(xùn)練樣本量,好理解各薇,不解釋项贺。
    maxseq_len是輸入文本的長度,相當(dāng)于LSTM里的input_dim峭判,就是輸入幾個單詞开缎。
    num_tags是可供選擇的單詞個數(shù),比如你覺得這個位置有5個可能的單詞林螃,那這個就是5奕删。
    (2)tag_indices,維度為[batch_size, max_seq_len]疗认。
    具體的和inputs一樣完残,只不過這個是真實的標(biāo)簽伏钠,也就是相應(yīng)位置對應(yīng)的真實y值。
    (3)sequence_lengths谨设,維度為 [batch_size]熟掂。
    表示的是每一個序列的長度,是一維的扎拣,相當(dāng)于max_sql_len赴肚,可以用np.full這個函數(shù)實現(xiàn)。
    (4)transition_params二蓝,維度為[num_tags, num_tags]誉券,是轉(zhuǎn)移矩陣,要是事先沒有就訓(xùn)練一個侣夷。
    然后來看輸出:
    (1)log_likelihood横朋,標(biāo)量,還記得吧百拓,CRF訓(xùn)練參數(shù)用的是極大似然估計琴锭,這個值取負(fù)數(shù)就是交叉熵?fù)p失。
    (2)transition_params衙传,維度為[num_tags, num_tags]决帖,轉(zhuǎn)移矩陣,這個是我們預(yù)測要用到的蓖捶。
  • tf.contrib.crf.viterbi_decode
    viterbi_decode(score,transition_params)
    這個函數(shù)返回最好序列的標(biāo)簽地回,用的場景不是特別多。
    輸入:
    (1)score,維度為[seq_len, num_tags]俊鱼,參數(shù)的意思就不解釋了刻像,具體看上邊的說法,這就是一個得分并闲。
    (2)transition_params细睡,維度為[num_tags, num_tags],上邊訓(xùn)練輸出的轉(zhuǎn)移矩陣帝火。
    輸出:
    (1)viterbi溜徙,維度[seq_len],保留了每一步對應(yīng)得分值最高的索引犀填。
    (2)viterbi_score蠢壹,維度為[sel_len],這個是維特比的具體得分九巡。
  • tf.contrib.crf.viterbi_decode
    crf_decode(potentials,transition_params,sequence_length)
    這個函數(shù)和上邊那個差不多图贸,但是很常用。
    輸入:
    (1)potentials,維度為[batch_size, max_seq_len, num_tags]求妹,這個是滿足條件的一個輸入乏盐,可以使輸入和一個權(quán)重矩陣乘后的結(jié)果佳窑。
    (2)transition_params制恍,轉(zhuǎn)義矩陣不多說。
    (3)sequence_length神凑,和上邊一樣净神,輸入長度構(gòu)成的一維矩陣。
    輸出:
    (1)decode_tags溉委,維度為[batch_size, max_seq_len] 鹃唯,是一個最好序列的標(biāo)記。
    (2)best_score瓣喊,維度為[batch_size]坡慌,每個序列的最好得分。
    來看一個小例子藻三,這個例子是一個隨機(jī)的數(shù)字輸入洪橘,對應(yīng)一個只含0,1兩個狀態(tài)的目標(biāo)矩陣棵帽,然后根據(jù)輸入預(yù)測輸出熄求。代碼如下:
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
Timestep = 15#輸入的總長度,可以理解為15個rnn cell
Batchsize = 1#一次就輸入一個
Inputsize = 1
LR = 0.5
num_tags = 2
#定義batch輸出
def get_batch():
    xs = np.array([[2, 3, 4, 5, 5, 5, 1, 5, 3, 2, 5, 5, 5, 3, 5]])
    res = np.array([[0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1]])
    return [xs[:, :, np.newaxis], res]
# xs, res = get_batch()
# print(xs)
# xs變成三維的 res還是二維的
class crf:
    def __init__(self, time_steps, input_size, num_tags, batch_size):
        self.time_steps = time_steps
        self.input_size = input_size
        self.num_tags = num_tags
        self.batch_size = batch_size
        self.xs = tf.placeholder(tf.float32, [None, self.time_steps, self.input_size], name='xs')
        self.res = tf.placeholder(tf.int32, [self.batch_size, self.time_steps], name='res')#為什么和xs的定義模式不一樣
        weights = tf.get_variable('weights', [self.input_size, self.num_tags])
        matricized_xs = tf.reshape(self.xs, [-1, self.input_size])
        matricized_unary_scores = tf.matmul(matricized_xs, weights)
        unary_scores = tf.reshape(matricized_unary_scores, [self.batch_size, self.time_steps, self.num_tags])
        sequence_len = np.full(self.batch_size, self.time_steps, dtype=np.int32)
        log_likelihood, transition_params = tf.contrib.crf.crf_log_likelihood(unary_scores, self.res, sequence_len)
        self.pred, viterbiscore = tf.contrib.crf.crf_decode(unary_scores, transition_params, sequence_len)
        self.loss = tf.reduce_mean(-log_likelihood)
        self.train_op = tf.train.AdamOptimizer(LR).minimize(self.loss)


if __name__ == '__main__':
    model = crf(Timestep, Inputsize, num_tags, Batchsize)
    sess = tf.Session()
    sess.run(tf.initialize_all_variables())
    plt.ion()#動態(tài)曲線
    plt.show()
    for i in range(150):
        xs, res = get_batch()
        feed_dict = {model.xs: xs,
                     model.res: res}
        _, cost, pred = sess.run([model.train_op, model.loss, model.pred],
                                 feed_dict=feed_dict)#只有placeholder才可以feed
        x = xs.reshape(-1, 1)
        r = res.reshape(-1, 1)
        p = pred.reshape(-1, 1)
        x = range(len(x))
        plt.clf()
        plt.plot(x, r, 'r', x, p, 'g')
        plt.ylim(-1.2, 1.2)
        plt.draw()
        plt.pause(0.3)
        if i % 20 == 0:
            print('cost:', round(cost, 4))
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逗概,一起剝皮案震驚了整個濱河市弟晚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逾苫,老刑警劉巖卿城,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異铅搓,居然都是意外死亡瑟押,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門狸吞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勉耀,“玉大人,你說我怎么就攤上這事蹋偏”愠猓” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵威始,是天一觀的道長枢纠。 經(jīng)常有香客問我,道長黎棠,這世上最難降的妖魔是什么晋渺? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任镰绎,我火速辦了婚禮,結(jié)果婚禮上木西,老公的妹妹穿的比我還像新娘畴栖。我一直安慰自己,他們只是感情好八千,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布吗讶。 她就那樣靜靜地躺著,像睡著了一般恋捆。 火紅的嫁衣襯著肌膚如雪照皆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天沸停,我揣著相機(jī)與錄音膜毁,去河邊找鬼。 笑死愤钾,一個胖子當(dāng)著我的面吹牛瘟滨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播绰垂,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼室奏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了劲装?” 一聲冷哼從身側(cè)響起胧沫,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎占业,沒想到半個月后绒怨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡谦疾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年南蹂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片念恍。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡六剥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出峰伙,到底是詐尸還是另有隱情疗疟,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布瞳氓,位于F島的核電站策彤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜店诗,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一裹刮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧庞瘸,春花似錦捧弃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至霜第,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間户辞,已是汗流浹背泌类。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留底燎,地道東北人刃榨。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像双仍,于是被迫代替她去往敵國和親枢希。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容