tensorflow中crf源碼解析

2021-03-02 工程師milter

剛學習lstm+crf時,就閱讀過crf層的源碼,發現時間一久,就忘了。這次準備重新閱讀一下,順便做個筆記。主要的目的是深入理解代碼細節,提高自己編寫模型的能力。本文假定大家對lstm+crf的基本原理基本清楚。如果還不是很清楚,建議看看這篇論文:Bidirectional LSTM-CRF Models for Sequence Tagging公眾號後臺回復 crf (全部小寫) 即可獲得論文。

crf源碼的版本

網絡上crf的實現版本很多,我選擇的是這個:https://github.com/tensorflow/addons/blob/v0.11.2/tensorflow_addons/text/crf.py

概覽

首先來看看源碼的大概結構:

有1個類,11個方法。我們從crf_sequence_score這個方法開始。

閱讀代碼當然是非常抽象,我們最好在腦子裡構建一個例子,閱讀的過程中,想像這個例子在被計算。這樣就會好理解很多。比如這個:

crf_sequence_score

先看籤名和注釋:

inputs就是我們從bilstm層得到的輸出。tag_indices 就是我們要計算的一條標籤序列。根據前面的例子,可以想像成(B-ORG O B-MISC O)sequence_lengths  就是句子的真實長度,主要用來計算masktransition_params  就是crf的核心結構,狀態轉移矩陣

該方法返回tag_indices這個標籤序列的得分。

這裡面內部又定義了兩個方法。看注釋可以了解,當句子長度是1時,就沒必要計算轉移分數。直接從inputs中取出對應tag的值即可。也就是這個方法,相應解釋也寫在代碼注釋中了:

def _single_seq_fn():
'''
因為要從inputs中取出相應的元素,所以
使用 tf.gather_nd
難點在於構建indices,這就是本方法的主體。
indexes一共三維,構建一維,拼接一維。
'''
batch_size = tf.shape(inputs, out_type=tf.int32)[0]
# 構建第一維,即batch size維度
batch_inds = tf.reshape(tf.range(batch_size), [-1, 1])
# 拼接第二維,因為句子長度是1,所以第二維全是0
indices = tf.concat([batch_inds, tf.zeros_like(batch_inds)], axis=1)
#從tag_indices中取出第三維的值
tag_inds = tf.gather_nd(tag_indices, indices)
tag_inds = tf.reshape(tag_inds, [-1, 1])
# 拼接第三維
indices = tf.concat([indices, tag_inds], axis=1)
# 根據拼接好的indices從inputs中取出相應的元素
sequence_scores = tf.gather_nd(inputs, indices)

# 如果句子長度為0,則相應的score為0
sequence_scores = tf.where(
tf.less_equal(sequence_lengths, 0),
tf.zeros_like(sequence_scores),
sequence_scores,
)
return sequence_scores

當句子長度大於1時,就必須計算轉移分數,這才是正常的狀態。方法如下:

def _multi_seq_fn():
# Compute the scores of the given tag sequence.
unary_scores = crf_unary_score(tag_indices, sequence_lengths, inputs)
binary_scores = crf_binary_score(
tag_indices, sequence_lengths, transition_params
)
sequence_scores = unary_scores + binary_scores
return sequence_scores

可以看到,這裡面主要由兩個方法組成:

crf_binary_score我們一個一個看。

crf_unary_score

這個方法,是從inputs中,取出tag_indices對應位置的分數,然後把每個句子中的分數相加。

def crf_unary_score(
tag_indices: TensorLike, sequence_lengths: TensorLike, inputs: TensorLike
) -> tf.Tensor:
"""Computes the unary scores of tag sequences.
Args:
tag_indices: A [batch_size, max_seq_len] matrix of tag indices.
sequence_lengths: A [batch_size] vector of true sequence lengths.
inputs: A [batch_size, max_seq_len, num_tags] tensor of unary potentials.
Returns:
unary_scores: A [batch_size] vector of unary scores.
"""
tag_indices = tf.cast(tag_indices, dtype=tf.int32)
sequence_lengths = tf.cast(sequence_lengths, dtype=tf.int32)

batch_size = tf.shape(inputs)[0]
max_seq_len = tf.shape(inputs)[1]
num_tags = tf.shape(inputs)[2]
# 將整個輸入拉平,變成一維數組
flattened_inputs = tf.reshape(inputs, [-1])
# 確定鋪平後batch中每個句子的起點
offsets = tf.expand_dims(tf.range(batch_size) * max_seq_len * num_tags, 1)
# 確定鋪平後,batch中每個句子中的每個字的起點
offsets += tf.expand_dims(tf.range(max_seq_len) * num_tags, 0)
# Use int32 or int64 based on tag_indices' dtype.
if tag_indices.dtype == tf.int64:
offsets = tf.cast(offsets, tf.int64)
# 將tag_indices轉化成鋪平後的indices
flattened_tag_indices = tf.reshape(offsets + tag_indices, [-1])
# 獲取單獨的值,並重新reshape
unary_scores = tf.reshape(
tf.gather(flattened_inputs, flattened_tag_indices), [
batch_size, max_seq_len]
)
# 根據句子長度,生成mask
masks = tf.sequence_mask(
sequence_lengths, maxlen=tf.shape(tag_indices)[1], dtype=tf.float32
)
# 將每個字符的分數相加,作為標籤序列的unary_scores
unary_scores = tf.reduce_sum(unary_scores * masks, 1)
return unary_scores

如果你對上面的reshape有所陌生,提供如下例子供參考:

好了,今天先到這裡吧。下次繼續,再長你也不會看了。

相關焦點

  • tensorflow源碼解析之seq2seq.py文件(上)
    一、前言自從接觸並學習tensorflow框架之後,總是會遇到很多莫名奇妙的報錯信息。而網上又很少有相似的問題的解決方案。因此很久之前就想學一下tendorflow的源碼,能夠深層次的理解tensorflow這個框架。但是由於一些原因耽擱了。
  • 【TensorFlow】優化器AdamOptimizer的源碼分析
    TensorFlow的優化器基本都繼承於 "class Optimizer",AdamOptimizer也不例外,本文嘗試對該優化器的源碼進行解讀。源碼位置: /tensorflow/python/training/adam.py
  • python代碼實戰 | 用 TensorFlow 實現序列標註:基於bi-LSTM+CRF和字符嵌入實現NER和POS
    Tensorflow vs Theano  當時,Tensorflow剛剛開源,Theano是使用最廣泛的框架。對於那些不熟悉這兩者的人來說,Theano在矩陣級別運行,而Tensorflow則提供了大量預編碼層和有用的訓練機制。使用Theano有時很痛苦,但卻強迫我注意方程中隱藏的微小細節,並全面了解深度學習庫的工作原理。
  • TensorFlow 安裝詳解
    節點(Nodes)在圖中表示數學操作,圖中的線(edges)則表示在節點間相互聯繫的多維數據數組,即張量(tensor)。它靈活的架構讓你可以在多種平臺上展開計算,例如臺式計算機中的一個或多個 CPU(或GPU),伺服器,行動裝置等等。
  • 如何用30天吃掉TensorFlow2.0?
    tensorflow2.0官方文檔和tensorflow1.0官方文檔顯然是出自同一批作者之手,他們一如既往地秉承著谷歌make things complicated的風格傳統,用哈希表一般混亂的文檔結構、無法運行的範例代碼、複雜的函數嵌套調用關係、隨意插入的不常用第三方庫等技巧將讀者的懵圈程度逐步推向高潮。
  • TensorFlow中RNN實現的正確打開方式
    此處建議大家閱讀tf.nn.dynamic_rnn的文檔(地址:https://www.tensorflow.org/api_docs/python/tf/nn/dynamic_rnn)做進一步了解。三、學習如何堆疊RNNCell:MultiRNNCell很多時候,單層RNN的能力有限,我們需要多層的RNN。
  • GitHub標星2000+,如何用30天啃完TensorFlow2.0?
    作者 | 梁雲1991天下苦tensorflow久矣!儘管tensorflow2.0宣稱已經為改善用戶體驗做出了巨大的改進,really easy to use,但大家學得並不輕鬆。2.學習環境本書全部源碼在jupyter中編寫測試通過,建議通過git克隆到本地,並在jupyter中交互式運行學習。為了直接能夠在jupyter中打開markdown文件,建議安裝jupytext,將markdown轉換成ipynb。
  • SSD網絡tensorflow版本源碼深入分析
    一:SSD網絡相關參數代碼解析原始碼中對SSD網絡需要的6個層大小,默認框大小、最小與最大放縮比率、默認框不同寬高比、步長感受野、並交比等參數給出了相關默認值。其符合原著SSD論文中作者給出的SSD網絡模型圖:
  • 帶你入門機器學習與TensorFlow2.x
    1.2 什麼是機器學習機器學習是實現人工智慧的一種方法,基本原理是使用算法來解析數據,並從中學習到規律,然後對真實世界中的事件做出決策和預測。也就是說,機器學習的核心有兩個:算法和數據。與傳統的人工智慧程序不同,機器學習需要依賴大量的數據進行「訓練」,通過各種算法從數據中學習如何完成任務。
  • 【官方教程】TensorFlow在圖像識別中的應用
    我們也會討論如何從模型中提取高層次的特徵,在今後其它視覺任務中可能會用到。Python API的使用方法第一次運行classify_image.py腳本時,它會從tensorflow.org官網上下載訓練好的模型。你需要在磁碟上預留約200M的空間。接下去的步驟默認你已經通過PIP包安裝了TensorFlow,並且已經位於TensorFlow的根目錄下。
  • 深度學習環境配置指南:Pytorch、TensorFlow、Keras
    導讀本文介紹了作者使用RTX3090進行深度學習環境配置pytorch、tensorflow、keras等的詳細過程及代碼。筆者中山大學研究生,醫學生+計科學生的集合體,機器學習愛好者。cudnn)從https://developer.nvidia.com/rdp/cudnn-download下載cudnn,解壓後進入cuda/lib64路徑下,把裡面所有文件拷入對應虛擬環境(exp38)的lib中(6)裝tf2.5(不要裝tensorflow-gpu==2.4.0rc0
  • tensorflow安裝教程
    tensorflow是谷歌開源的人工智慧庫,有最完善的生態支持。是進行人工智慧領域開發和科研的必備工具。本文在windows10下,藉助anaconda建立成功進入tf2.0環境conda activate tf2.0安裝tensorflow2.0 pip install tensorflow==2.0.0-beta1下載的東西挺多,多等一會,最後成功如下命令行運行python,執行import
  • TensorFlow極速入門
    最後給出了在 tensorflow 中建立一個機器學習模型步驟,並用一個手寫數字識別的例子進行演示。1、tensorflow是什麼?tensorflow 是 google 開源的機器學習工具,在2015年11月其實現正式開源,開源協議Apache 2.0。
  • TensorFlow應用實戰 | TensorFlow基礎知識
    其他屬性:https://www.tensorflow.org/api_docs/python/tf/Tensor可以通過搜索Tensor 查看到它的其他屬性。A Tensor是一個輸出的符號句柄 Operation。它不包含該操作輸出的值,而是提供了在TensorFlow中計算這些值的方法tf.Session。
  • tensorflow極速入門
    最後給出了在 tensorflow 中建立一個機器學習模型步驟,並用一個手寫數字識別的例子進行演示。1、 tensorflow是什麼?tensorflow 是 google 開源的機器學習工具,在2015年11月其實現正式開源,開源協議Apache 2.0。下圖是 query 詞頻時序圖,從中可以看出 tensorflow 的火爆程度。
  • OpenCV+Tensorflow實現實時人臉識別演示
    FaceNet網絡設計目標任務有如下1.驗證-驗證是否為同一張臉2.識別-識別是否為同一個人3.聚類-發現人臉具有相同之處的人關於什麼是神經網絡嵌入,這個解釋比較複雜,簡單的說神經網絡的嵌入學習可以幫助我們把離散變量表示為連續的向量,在低維空間找到最近鄰,tensorflow中的word2vec就是用了嵌入。
  • 令人困惑的TensorFlow!
    但對於有些應用開發人員而言,他們開發的應用並沒有好的教程,或對於那些想打破常規的人(在研究中很常見)而言,剛接觸 TensorFlow 肯定是讓人沮喪的。我試圖通過這篇文章去填補這個空白。我沒有專注於某個特定的任務,而是提出更一般的方法,並解析 TensorFlow 背後基礎的抽象概念。
  • Anaconda軟體安裝TensorFlow教程
    Anaconda軟體的安裝,請閱讀文章《Anaconda軟體安裝和簡易使用教程》第一步:創建r-tensorflow環境打開Anaconda Prompt,執行命令conda create --name r-tensorflow python=3.6該命令用來創建r-tensorflow虛擬環境
  • Windows配置tensorflow開發環境
    通過這篇文章,希望能夠幫助大家更加順利地配置tensorflow的開發環境。4、測試tensorflow是否可用可通過兩種方式測試tensorflow:(1)通過Anaconda Prompt窗口:首先,激活tensorflow環境。
  • 在Windows中安裝Tensorflow和Kears深度學習框架
    建立Tensorflow的Anaconda虛擬環境在一臺計算機中,我們常常需要安裝很多軟體,但是每個軟體所需要的Python的關聯模塊或版本不相同。例如,我們要使用Python開發開發網站系統,安裝的網站框架可能需要Python2.X的版本,但是安裝Tensorflow需要Python3.5的版本,此時就會發生版本不一致的問題。