日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用PaddleFluid和TensorFlow训练序列标注模型

發布時間:2024/10/8 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用PaddleFluid和TensorFlow训练序列标注模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


專欄介紹:Paddle Fluid 是用來讓用戶像 PyTorch 和 Tensorflow Eager Execution 一樣執行程序。在這些系統中,不再有模型這個概念,應用也不再包含一個用于描述 Operator 圖或者一系列層的符號描述,而是像通用程序那樣描述訓練或者預測的過程。


本專欄將推出一系列技術文章,從框架的概念、使用上對比分析 TensorFlow 和 Paddle Fluid,為對 PaddlePaddle 感興趣的同學提供一些指導。

上一篇我們通過 RNN 語言模型初識 PaddleFluid 和 TensorFlow 中的循環神經網絡模型。了解了:


  • 在 PaddleFluid 和 TensorFlow 平臺下如何組織序列輸入數據;

  • 如何使用循環神經網絡單元;

  • 使用中的注意事項。


可以看到 PaddleFluid 中的各種循環神經網絡單元都直接支持非填充序列作為輸入,用戶在使用時無需對 mini-batch 中的不等長序列進行填充,無需關心填充位是否會對代價(loss)計算產生影響,從而需要在計算損失時對填充位置進行過濾這樣的細節,對使用來說無疑是十分方便的。?


循環神經網絡的是深度學習模型中最為重要的一部分,這一篇我們以序列標注任務為例將會構造一個更加復雜的循環神經網絡模型用于命名實體識別任務。我們的關注點始終放在:在兩個平臺下:(1)如何組織序列數據;(2)如何使用序列處理單元(不限于循環神經網絡)。


這一篇會看到:?


1. PaddleFluid Data Feeder vs. 使用 TensorFlow r1.4 之后 release 的 Dataset API 讀取數據;?


2. 在 PaddleFluid 和 TensorFlow 中,使用條件隨機場(Conditional Random Field,CRF)單元;?


3. 在 PaddleFluid 和 TensorFlow 中,通過數據并行方式使用多塊 GPU 卡進行訓練。


如何使用代碼


本篇文章配套有完整可運行的代碼, 請隨時從 github [1] 上獲取最新代碼。代碼包括以下幾個文件:



在執行訓練任務前,請首先在終端執行下面的命令進行訓練數據下載以及預處理。


sh download.sh


在終端運行以下命令便可以使用默認結構和默認參數運行 PaddleFluid 訓練序列標注模型。


python sequence_tagging_fluid.py


在終端運行以下命令便可以使用默認結構和默認參數運行 TensorFlow 訓練序列標注模型。


python sequence_tagging_tensorflow.py


背景介紹


序列標注和命名實體識別


序列標注是自然語言處理任務中的重要基礎任務之一。常見的分詞,詞性標注,語義角色標注,命名實體識別,甚至自動問答(QA)都可以通過序列標注模型來實現。這一篇我們將訓練一個序列標注模型完成命名實體識別的任務。


我們先來看看,什么是序列標注問題呢?請看下面一幅圖:


▲?圖1. 序列標注問題


序列標注任務是為一個一維的線性輸入序列中的每個元素打上標簽集合中的某個標簽。在上面的例子中,序列標注就是為圖像序列中的每個元素貼上一個描述它們形狀的標簽。而序列標注任務的難點在于:序列中 元素的標記和 它們在序列中的位置密切相關。?


那么, 什么是命名實體識別呢?命名實體識別(Named Entity Recognition,NER)又稱作“專名識別”,是指識別文本中具有特定意義的實體,主要包括:人名、地名、機構名、專有名詞等。


BIO 表示法?


序列標注任務一般都會采用 BIO 表示方式來定義序列標注的標簽集,B 代表句子的開始,I 代表句子中間,O 代表句子結束。通過 B、I、O 三種標記將不同的語塊賦予不同的標簽,例如:對于一個標記為 A 的命名實體,將它所包含的第一個語塊賦予標簽 B-A,將它所包含的其它語塊賦予標簽 I-A,不屬于任何命名實體的語塊賦予標簽 O。圖 2 是用 BIO 表示標注序列中命名實體的具體示例。


▲?圖2. BIO標注方法示例


模型概覽


圖 3 是本篇模型的模型結構概覽。?


▲?圖3. 序列標注模型結構概覽


我們要訓練的序列標注模型,接受:一個文本序列作為輸入,另一個與輸入文本序列等長的標記序列作為學習的目標。首先通過上一篇介紹過的 word embedding 層的取詞作用得到詞向量, 接著經過一個雙向 LSTM 單元學習序列的特征表示,這個特別表示最終作為條件隨機場 CRF 的輸入完成最終的序列標注任務。?


下面是對各個子模塊的進一步說明。


雙向循環神經網絡?


在循環神經網絡模型中,t 時刻輸出的隱藏層向量編碼了到 t 時刻為止所有輸入的信息,但由于循環神經網絡單元計算的串行行:t 時刻循環神經網絡但愿可以看到歷史(t 時刻之前),卻無法看到未來(t 時刻之后)。


一些自然語言處理任務總是能一次性拿到整個句子,這種情況下,在 t 時刻計算時,如果能夠像獲取歷史信息一樣得到未來的信息,對序列學習任務會有很大幫助,雙向循環神經網絡的出現正是為了解決這一問題。


它的思想簡單且直接:使用兩個循環神經網絡單元( simple RNN,GRU 或者 LSTM 均可)分別以正向和反向順序學習輸入序列,再將兩者的輸出 向量進行橫向拼接。這樣的一個輸出向量中就既包含了 t 時刻之前的信息,也包含了 t 時刻之后的信息。


條件隨機場?


使用神經網絡模型解決問題的思路通常都是:前層網絡學習輸入的特征表示,網絡的最后一層在特征基礎上完成最終任務。在序列 標注任務中,雙向循環神經網絡學習輸入的特征表示,條件隨機場(Conditional Random Filed, CRF)正是在特征的基礎上完成序列標注的一種計算單元,處于整個網絡的末端。


CRF 是一種概率化結構模型,可以看作是一個概率無向圖模型(也叫作馬爾科夫隨機場),結點表示隨機變量,邊表示隨機變量之間的概率依賴關系。簡單來講 CRF 學習條件概率:P(X|Y),其中 X=(x1,x2,...,xn) 是輸入序列,Y=(y1,y2,...,yn) 是標記序列;解碼過程是給定 X 序列求解令 P(Y|X) 最大的 Y 序列,即


條件隨機場是的定義:設 G=(V,E) 是一個無向圖, V 是結點的集合,E 是無向邊的集合。V 中的每個結點對應一個隨機變量 Yv,,其取值范圍為可能的標記集合 {y},如果以隨機變量 X 為條件,每個隨機變量 Yv 都滿足以下馬爾科夫特性:?



其中,ω~v 表示兩個結點在圖 G 中是鄰近結點,那么,(X,Y) 是一個條件隨機場。


線性鏈條件隨機場?


上面的定義并沒有對 X 和 Y 的結構給出更多約束,理論上來講只要標記序列表示了一定的條件獨立性,G 的圖結構可以是任意的。對序列標注任務,只需要考慮 X 和 Y 都是一個序列,于是可以形成一個如圖 4 所示的簡單鏈式結構圖。在圖中,輸入序列 X 的元素之間并不存在圖結構,因為我們只是將它作為條件,并不做任何條件獨立假設。


▲?圖4. 輸入序列和標記序列具有相同結構的線性鏈條件隨機場


序列標注問題使用的是以上這種定義在線性鏈上的特殊條件隨機場,稱之為線性鏈條件隨機場(Linear Chain Conditional Random Field)。下面,我們給出線性鏈條件隨機場的數學定義:?


定義 2 :線性鏈條件隨機場 :設 X=(x1,x2,...,xn),Y=(y1,y2,...,yn) 均為線性鏈表示的隨機變量序列,若在給定隨機變量序列 X 的條件下,隨機變量序列 Y 的條件概率分布 P(Y|X) 滿足馬爾科夫性:



i=1,2,...,n(在i=1和n時只考慮單邊)則稱 P(Y|X) 為線性鏈條件隨機場。X 表示輸入序列,Y 表示與之對應的標記序列。


根據線性鏈條件隨機場上的因子分解定理,在給定觀測序列 X 時,一個特定標記序列 Y 的概率可以定義為:



其中:



是規范化因子。


上面的式子中 tj 是定義在邊上的特征函數,依賴于當前和前一個位置,稱為轉移特征,表示對于觀察序列 X 及其標注序列在 i 及 i?1 位置上標記的轉移概率。sk 是定義在結點上的特征函數,稱為狀態特征,依賴于當前位置,表示對于觀察序列 X 及其 i 位置的標記概率。λj 和 μk 分別是轉移特征函數和狀態特征函數對應的權值。


線性鏈條件隨機場的優化目標?


實際上 ,t 和 s 可以用相同的數學形式表示,s 可以同樣也寫為以下形式:



假設有 K1 個轉移特征,K2 個狀態特征,定義特征函數



再對轉移特征和狀態特在各個位置 i 求和有:



于是條件概率 P(Y|X) 可以寫為:




我們把 f 統稱為特征函數,ω 是權值,是 CRF 模型要求解的參數。


學習時,對于給定的輸入序列和對應的標記序列的集合 D=[(X1,Y1),(X2,Y2),...,(XN,YN)] ,通過正則化的極大似然估計,可以得到如下優化目標:



這個優化目標,可以通過反向傳播算法和整個神經網絡一起更新求解。?


解碼時,對于給定的輸入序列 X,通過解碼算法(通常有:維特比算法、Beam Search)求令出條件概率最大的輸出序列


CRF小結


條件隨機場是這一篇網絡中一個相對復雜的計算單元。值得慶幸的是,在各個深度學習框架的幫助下,大多數情況下,我們只需要知道其原理便可以非常方便的使用,而不必過于關注 其內部的實現細節。


這里我們再對上面的內容進行一個簡單的總結,方便大家使用 CRF 單元:


1. 在序列標注網絡中, CRF 以循環神經網絡單元輸出向量作為輸入,學習狀態特征和轉移特征。


2. 狀態特征只與當然輸入有關;轉移特征是一個矩陣,刻畫了標記兩兩之間互相轉移的強度。


3. 假設循環神經網絡單元輸出向量維度為 h ,序列中含有 t 個詞語,共有 d 個標記:


  • 循環神經網絡輸入矩陣的大小為:Out=t×h;

    ?

  • CRF 層以 Out 為輸入學習轉移特征:通過一個 全連接層將 Out 映射為一個 t×d 的矩陣,也就是轉移特征;?

  • 狀態特征是一個:(d+2)×d 維的矩陣,刻畫了標記之前轉移的強度。 這里的 +2 是需要學習序列開始 <s> 向句子首詞轉移和和句子末尾詞向序列結束 <e> 轉移這樣兩種特殊的狀態轉移;

  • CRF 本質上計算了一個 softmax:給定標記序列出現的概率。但困難之處在于 softmax 的歸一化分母是所有可能標記序列,計算量很大。但由于引入了馬爾科夫假設,這個歸一化分母可以巧妙地通過一個動態規劃算法求解。?


4. CRF 的學習準則是令 negative log likelihood 最大化。


數據集介紹


這一篇我們使用 Standford CS224d 課程中作業 2 [2] 的 NER 任務數據作為訓練數據源。 進入 data 目錄運行 data/download.sh 腳本下載數據并預處理訓練數據。預處理包括:1. 為輸入文本序列建立詞典;2. 組織輸入數據格式。?


運行結束將會在 data 目錄下看到如下內容。


data
├──?dev
├──?dev_src.txt
├──?dev_src.vocab
├──?dev_trg.txt
├──?dev_trg.vocab
├──?download.sh
├──?preprocess.py
├──?train
├──?train_src.txt
├──?train_src.vocab
├──?train_trg.txt
└──?train_trg.vocab


其中需要重點關注的是 train_src.txt train_trg.txt train_src.vocabtrain_trg.vocab 文件。它們分別是:輸入文本序列;文本對應的標記序列;輸入文本序列的詞典以及標記序列詞典。 train_src.txt train_trg.txt 的一行是一條訓練樣本,他們嚴格一一對應。分別執行 head -n 1 train_src.txt head -n 1 train_trg.t xt 會看到如下內容:


EU?rejects?German?call?to?boycott?British?lamb?.


B-ORG?O?B-MISC?O?O?O?B-MISC?O?O


程序結構


我們首先在此整體回顧一下使用 PaddleFluid 平臺和 TensorFlow 運行神經網絡模型的整體流程。


PaddleFluid


1. 調用 PaddleFluid API 描述神經網絡模型。PaddleFluid 中 一個神經網絡訓練任務被稱之為一段 Fluid Program 。?


2. 定義 Fluid Program 執行設備: place 。常見的有 fluid.CUDAPlace(0) fluid.CPUPlace()


place?=?fluid.CUDAPlace(0)?if?conf.use_gpu?else?fluid.CPUPlace()


注:PaddleFluid 支持混合設備運行,一些 運算(operator)沒有特定設備實現,或者為了提高全局資源利用率,可以為他們指定不同的計算設備。


3. 創建 PaddleFluid 執行器(Executor),需要為執行器指定運行設備。


exe?=?fluid.Executor(place)


4. 讓執行器執行 fluid.default_startup_program() ,初始化神經網絡中的可學習參數,完成必要的初始化工作。?


5. 定義 DataFeeder,編寫 data reader,只需要關注如何返回一條訓練/測試數據。?


6. 進入訓練的雙層循環(外層在 epoch 上循環,內層在 mini-batch 上循環),直到訓練結束。


TensorFlow?


1. 調用 TensorFlow API 描述神經網絡模型。 TensorFlow 中一個神經網絡模型是一個 Computation Graph。


2. 創建 TensorFlow Session 用來執行計算圖。


sess?=?tf.Session()


3. 調用 sess.run(tf.global_variables_initializer()) 初始化神經網絡中的可學習參數。


4. 編寫返回每個 mini-batch 數據的數據讀取腳本。


5. 進入訓練的雙層循環(外層在 epoch 上循環,內層在 mini-batch 上循環),直到訓練結束。


如果不顯示地指定使用何種設備進行訓練,TensorFlow 會對機器硬件進行檢測(是否有 GPU), 選擇能夠盡可能利用機器硬件資源的方式運行。?

構建網絡


基于 PaddleFluid 和 TensorFlow 的序列標注網絡分別定義在 sequence_tagging_fluid.py 和 sequence_tagging_tensorflow.py 的 NER_net 類中,詳細信息請參考完整代碼,這里對重要部分進行說明。?


加載訓練數據?


PaddleFluid:編寫Data Reader?


PaddleFluid 模型通過 fluid.layers.data 來接收輸入數據。序列標注網絡以圖片以及圖片對應的類別標簽作為網絡的輸入:


self.source?=?fluid.layers.data(
????name="source",?shape=[1],?dtype="int64",?lod_level=1)
self.target?=?fluid.layers.data(
????name="target",?shape=[1],?dtype="int64",?lod_level=1)


定義 data layer 的核心是指定輸入 Tensor 的形狀( shape )和類型。


序列標注中,輸入文本序列和標記序列都使用 one-hot 特征作為輸入,一個詞用一個和字典大小相同的向量表示,每一個位置對應了字典中的 一個詞語。one-hot 向量僅有一個維度為 1, 其余全部為 0。在上面定義的 data layer 中 source target 的形狀都是 1,類型是 int64 。?


PaddleFluid 支持非填充的序列輸入,這是通過 LoD Tensor 實現的。關于什么是 LoD Tensor 請參考上一篇使用 PaddleFluid 和 TensorFlow 訓練 RNN 語言模型中的介紹,這一篇不再贅述。有了 LoD Tensor 的概念后,在 PaddleFluid 中,通過 DataFeeder 模塊來為網絡中的 data layer 提供數據,調用方式如下面的代碼所示:


train_reader?=?paddle.batch(
????paddle.reader.shuffle(
????????data_reader(conf.train_src_file_name,?conf.train_trg_file_name,
????????????????????conf.src_vocab_file,?conf.trg_vocab_file),
????????buf_size=1024000),
????batch_size=conf.batch_size)

place?=?fluid.CUDAPlace(0)?if?conf.use_gpu?else?fluid.CPUPlace()
feeder?=?fluid.DataFeeder(feed_list=[net.source,?net.target],?place=place)


觀察以上代碼,需要用戶完成的僅有:編寫一個實現讀取一條數據的 python 函數: data_reader data_reader 的代碼非常簡單,我們再來看一下它的具體實現:


def?data_reader(src_file_name,?trg_file_name,?src_vocab_file,?trg_vocab_file):
????def?__load_dict(dict_file_path):
????????word_dict?=?{}
????????with?open(dict_file_path,?"r")?as?fdict:
????????????for?idx,?line?in?enumerate(fdict):
????????????????if?idx?<?2:?continue
????????????????word_dict[line.strip().split("\t")[0]]?=?idx?-?2

????????return?word_dict

????def?__reader():
????????src_dict?=?__load_dict(src_vocab_file)
????????trg_dict?=?__load_dict(trg_vocab_file)

????????with?open(src_file_name,?"r")?as?fsrc,?open(trg_file_name,
????????????????????????????????????????????????????"r")?as?ftrg:
????????????for?src,?trg?in?izip(fsrc,?ftrg):
????????????????src_words?=?src.strip().split()
????????????????trg_words?=?trg.strip().split()

????????????????src_ids?=?[src_dict[w]?for?w?in?src_words]
????????????????trg_ids?=?[trg_dict[w]?for?w?in?trg_words]
????????????????yield?src_ids,?trg_ids

????return?__reader


在上面的代碼中:?


1. data_reader 是一個 python generator ,函數名字可以任意指定,無需固定。?


2. data_reader 打開輸入序列文件和標記序列文件,每次從這兩個文件讀取一行,一行既是一條訓練數據,返回一個 python list,這個 python list 既是序列中所有時間步。具體的數據組織方式如下表所示,其中?i 代表一個整數:



3.?paddle.batch() 接口用來構造 mini-batch 輸入,會調用 data_reader 將數據讀入一個 pool 中,對 pool 中的數據進行 shuffle,然后依次返回每個 mini-batch 的數據。


TensorFlow:使用Dataset API


在之前的篇章中我們都使用 TensorFlow 的 placeholder 接入訓練數據,這一篇我們使用一種新的方式 TensorFlow 在 r1.3 版本之后引入的 Dataset API 來讀取數據。


參考 Google 官方給出的 Dataset API 中的類圖 [3],使用 TensorFlow 的 Dataset API,首先引入兩個抽象概念:


1. tf.data.Dataset 表示一系列元素,其中每個元素包含一個或多個 Tensor 對象。


2. tf.data.Iterator 提供了從數據集中取出元素的方法。 Iterator.get_next() 會在執行時生成 Dataset 的下一個 /mini-batch 元素。



定義 Dataset?


目前 Dataset API 還提供了三種預定義好的定義 Dataset 的方式。這一篇中我們主要面向文本數據的處理,使用其中的 TextLineDataset 接口。?


tf.data.TextLineDataset:接口的輸入是一個文件列表,輸出是一個 TensorFlow dataset dataset 中的每一個元素就對應了文件中的一行。通過下面的調用傳入輸入序列文本路徑和標記序列文本路徑便可返回一個 Dataset


src_dataset?=?tf.data.TextLineDataset(src_file_name)
trg_dataset?=?tf.data.TextLineDataset(trg_file_name)


獲取 Iterator?


需要說明的是,TensorFlow 中的循環神經網絡要求一個 mini-batch 之內序列長度相等,使用 Dynamic RNN 時,batch 和 batch 之間序列長度可以不相等,因此對一個 mini-batch 之內的數據需要進行填充。?


Dataset API 提供了 padded_batch 幫助構造填充后的 mini-batch 數據。?


提示:使用 bucket 分桶,從桶內取 mini-batch 數據,填充至一個 batch 中的最長序列長度能夠有效提高 dynamic rnn 的計算效率。?


下面的代碼返回 Iterator ,使用先分桶,然后再取 mini-batch 數據填充至? batch 中最長序列長度的方式。完整代碼請參考:iterator_helper_tf [4]


def?get_data_iterator(src_file_name,
??????????????????????trg_file_name,
??????????????????????src_vocab_file,
??????????????????????trg_vocab_file,
??????????????????????batch_size,
??????????????????????pad_token="</p>",
??????????????????????max_sequence_length=None,
??????????????????????unk_id=1,
??????????????????????num_parallel_calls=4,
??????????????????????num_buckets=5,
??????????????????????output_buffer_size=102400,
??????????????????????is_training=True)
:


????def?__get_word_dict(vocab_file_path,?unk_id):
????????return?tf.contrib.lookup.index_table_from_file(
????????????vocabulary_file=vocab_file_path,
????????????key_column_index=0,
????????????default_value=unk_id)

????src_dataset?=?tf.data.TextLineDataset(src_file_name)
????trg_dataset?=?tf.data.TextLineDataset(trg_file_name)

????dataset?=?tf.data.Dataset.zip((src_dataset,?trg_dataset))
????if?is_training:
????????dataset?=?dataset.shuffle(
????????????buffer_size=output_buffer_size,?reshuffle_each_iteration=True)

????src_trg_dataset?=?dataset.map(
????????lambda?src,?trg:?(tf.string_split([src]).values,?\
????????????????tf.string_split([trg]).values),
????????num_parallel_calls=num_parallel_calls).prefetch(output_buffer_size)

????src_dict?=?__get_word_dict(src_vocab_file,?unk_id)
????trg_dict?=?__get_word_dict(trg_vocab_file,?unk_id)

????src_pad_id?=?tf.cast(src_dict.lookup(tf.constant(pad_token)),?tf.int32)
????trg_pad_id?=?tf.cast(trg_dict.lookup(tf.constant(pad_token)),?tf.int32)

????#?convert?word?string?to?word?index
????src_trg_dataset?=?src_trg_dataset.map(
????????lambda?src,?trg:?(
????????????????tf.cast(src_dict.lookup(src),?tf.int32),
????????????????tf.cast(trg_dict.lookup(trg),?tf.int32)),
????????num_parallel_calls=num_parallel_calls).prefetch(output_buffer_size)

????#?Add?in?sequence?lengths.
????src_trg_dataset?=?src_trg_dataset.map(
????????lambda?src,?trg:?(src,?trg,?tf.size(src)),
????????num_parallel_calls=num_parallel_calls).prefetch(output_buffer_size)

????def?__batching_func(x):
????????return?x.padded_batch(
????????????batch_size,
????????????padded_shapes=(
????????????????tf.TensorShape([None]),??#?src
????????????????tf.TensorShape([None]),??#?trg
????????????????tf.TensorShape([]),??#seq_len
????????????),
????????????padding_values=(src_pad_id,?trg_pad_id,?0,?))

????if?num_buckets?>?1:

????????def?__key_func(unused_1,?unused_2,?seq_len):
????????????if?max_sequence_length:
????????????????bucket_width?=?(
????????????????????max_sequence_length?+?num_buckets?-?1)?//?num_buckets
????????????else:
????????????????bucket_width?=?10

????????????bucket_id?=?seq_len?//?bucket_width,
????????????return?tf.to_int64(tf.minimum(num_buckets,?bucket_id))

????????def?__reduce_func(unused_key,?windowed_data):
????????????return?__batching_func(windowed_data)

????????batched_dataset?=?src_trg_dataset.apply(
????????????tf.contrib.data.group_by_window(
????????????????key_func=__key_func,
????????????????reduce_func=__reduce_func,
????????????????window_size=batch_size))

????else:
????????batched_dataset?=?__batching_func(curwd_nxtwd_dataset)

????batched_iter?=?batched_dataset.make_initializable_iterator()
????src_ids,?trg_ids,?seq_len?=?batched_iter.get_next()

????return?BatchedInput(
????????initializer=batched_iter.initializer,
????????source=src_ids,
????????target=trg_ids,
????????sequence_length=seq_len)


構建網絡結構及運行


構建網絡結構及運行的過程對兩個平臺上都是常規流程。


1. 構建網絡時調用相關的 API 接口,令一個 計算單元的輸出成為下一個計算單元的輸入建立起網絡的連通性;具體請參考 sequence_tagging_fluid.py 和 sequence_tagging_tensorflow.py 中 NER_net 類的實現。


2. 運行訓練以及解碼具體請參考 sequence_tagging_fluid.py 和 sequence_tagging_tensorflow.py 中 train 函數的實現。


模型中核心模塊:LSTM 單元在兩個平臺下的差異及注意事項請參考上一篇:使用 PaddleFluid 和 TensorFlow 訓練 RNN 語言模型,這里不再贅述。

總結


這一篇繼續在序列標注模型中了解 PaddleFluid 和 TensorFlow 在接受序列輸入,序列處理策略上的不同。?


1. PaddleFluid 引入了 LoD Tensor 的概念,所有序列處理模塊(包括所有循環神經網絡單元,文本卷積)都支持非填充的序列輸入,使用時無需對 mini-batch 數據進行填充,也就避免了對填充位的各種特殊處理,這一點非常方便。?


2. TensorFlow 中的 Dynamic RNN 支持 mini-batch 之間序列不等長,但仍要求一個 mini-batch 內的數據填充至一樣長。?


3. PaddleFluid 中通過 Data Feeder 提供訓練數據,只需要編寫一個 python generator 實現從原始輸入文件中讀取一條訓練樣本, 框架會完成數據 shuffle 和組織 mini-batchd 工作。?


4. 這一篇使用了 TensorFlow r1.3 后 release 的 Dataset API,數據讀取部分也是一個 computation graph,能夠提高 I/O 效率,使用相對復雜一些。?


本篇代碼中提供了通過數據并行策略在 PaddleFluid 平臺下使用多塊 GPU 卡進行訓練,在 TensorFlow 中使用多卡相對復雜一些,這些主題會在下面繼續討論。


參考文獻


[1]. 本文配套代碼

https://github.com/JohnRabbbit/TF2Fluid/tree/master/05_sequence_tagging

[2].? Standford CS224d課程作業2

http://cs224d.stanford.edu/assignment2/index.html

[3].?Google官方Dataset API

https://developers.googleblog.com/2017/09/introducing-tensorflow-datasets.html

[4].?iterator_helper_tf

https://github.com/JohnRabbbit/TF2Fluid/blob/master/05_sequence_tagging/iterator_helper_tf.py



關于PaperWeekly


PaperWeekly 是一個推薦、解讀、討論、報道人工智能前沿論文成果的學術平臺。如果你研究或從事 AI 領域,歡迎在公眾號后臺點擊「交流群」,小助手將把你帶入 PaperWeekly 的交流群里。


▽ 點擊 |?閱讀原文?| 加入社區刷論文

總結

以上是生活随笔為你收集整理的使用PaddleFluid和TensorFlow训练序列标注模型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。