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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

使用PaddleFluid和TensorFlow训练RNN语言模型

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


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


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

在圖像領域,最流行的 building block 大多以卷積網絡為主。上一篇我們介紹了如何在 PaddleFluid 和 TensorFlow 上訓練圖像分類任務。卷積網絡本質上依然是一個前饋網絡,在神經網絡基本單元中循環神經網絡是建模序列問題最有力的工具, 有著非常重要的價值。自然語言天生是一個序列,在自然語言處理領域(Nature Language Processing,NLP)中,許多經典模型都基于循環神經網絡單元。可以說自然語言處理領域是 RNN 的天下。


這一篇以 NLP 領域的 RNN 語言模型(RNN Language Model,RNN LM)為實驗任務,對比如何使用 PaddleFluid 和 TensorFlow 兩個平臺實現序列模型。 這一篇中我們會看到 PaddleFluid 和 TensorFlow 在處理序列輸入時有著較大的差異:PaddleFluid 默認支持非填充的 RNN 單元,在如何組織 mini-batch 數據提供序列輸入上也簡化很多。


如何使用代碼


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



注意:在運行模型訓練之前,請首先進入 data 文件夾,在終端運行 sh download.sh 下載訓練數據。?


在終端運行以下命令便可以使用默認結構和默認參數運行 PaddleFluid 訓練 RNN LM。


python rnnlm_fluid.py


在終端運行以下命令便可以使用默認結構和默認參數運行 TensorFlow 訓練 RNN LM。


python rnnlm_tensorflow.py


背景介紹


one-hot和詞向量表示法?


計算機如何表示語言是處理 NLP 任務的首要問題。這里介紹將會使用到的 one-hot 和詞向量表示法。?


one-hot 表示方法:一個編碼單元表示一個個體,也就是一個詞。于是,一個詞被表示成一個長度為字典大小的實數向量,每個維度對應字典里的一個詞,除了該詞對應維度上的值是 1,其余維度都是 0。?


詞向量表示法:與 one-hot 表示相對的是 distributed representation ,也就是常說的詞向量:用一個更低維度的實向量表示詞語,向量的每個維度在實數域 RR 取值。?


在自然語言處理任務中,一套好的詞向量能夠提供豐富的領域知識,可以通過預訓練獲取,或者與最終任務端到端學習而來。?


循環神經網絡?


循環神經網絡(Recurrent Neural Network)是一種對序列數據建模的重要單元,模擬了離散時間(這里我們只考慮離散時間)動態系統的狀態演化。“循環” 兩字刻畫了模型的核心:上一時刻的輸出作為下一個時刻的輸入,始終留在系統中如下面的圖 1 所示,這種循環反饋能夠形成復雜的歷史。自然語言是一個天生的序列輸入,RNN 恰好有能力去刻畫詞匯與詞匯之間的前后關聯關系,因此,在自然語言處理任務中占有重要的地位。


▲?圖1. 最簡單的RNN單元


RNN 形成“循環反饋” 的過程是一個函數不斷復合的過程,可以等價為一個層數等于輸入序列長度的前饋神經網絡,如果輸入序列有 100 個時間步,相當于一個 100 層的前饋網絡,梯度消失和梯度爆炸的問題對 RNN 尤為嚴峻。


直覺上大于 1 的數連乘越乘越大,極端時會引起梯度爆炸;小于 1 的數連乘越乘越小,極端時會引起梯度消失。梯度消失也會令在循環神經網絡中,后面時間步的信息總是會”壓過”前面時間步。如果 t 時刻隱層狀態依賴于 t 之前所有時刻,梯度需要通過所有的中間隱層逐時間步回傳,這會形成如圖 2 所示的一個很深的求導鏈。


▲?圖2. t時刻依賴t時刻之前所有時刻


在許多實際問題中時間步之間相互依賴的鏈條并沒有那么長,t 時刻也許僅僅依賴于它之前有限的若干時刻。很自然會聯想到:如果模型能夠自適應地學習出一些如圖 3 所示的信息傳播捷徑來縮短梯度的傳播路徑,是不是可以一定程度減梯度消失和梯度爆炸呢?答案是肯定的,這也就是 LSTM 和 GRU 這類帶有 “門控”思想的神經網絡單元。


▲?圖3. 自適應地形成一些信息傳播的“捷徑”


關于 LSTM 更詳細的介紹請參考文獻 [2],這里不再贅述,只需了解 LSTM/GUR 這些門控循環神經網絡單元提出的動機即可。


RNN LM?


語言模型是 NLP 領域的基礎任務之一。語言模型是計算一個序列的概率,判斷一個序列是否屬于一個語言的模型,描述了這樣一個條件概率,其中是輸入序列中的 T 個詞語,用 one-hot 表示法表示。


言模型顧名思義是建模一種語言的模型,這一過程如圖 4 所示:


▲?圖4. RNN語言模型


RNN LM的工作流程如下:?


1. 給定一段 one-hot 表示的輸入序列 {x1,x2,...,xT},將它們嵌入到實向量空間,得到詞向量表示 :{ω1,ω2,...,ωt}。?


2. 以詞向量序列為輸入,使用 RNN 模型(可以選擇LSTM或者GRU),計算輸入序列到 t 時刻的編碼 ht。?


3. softmax 層以 ht 為輸入,預測下一個最可能的詞的概率。?


4.?,根據計算誤差信號。


PTB數據集介紹


至此,介紹完 RNN LM 模型的原理和基本結構,下面準備開始分別使用 PaddleFluid 和 TensorFlow 來構建我們的 訓練任務。這里首先介紹這一篇我們使用 Mikolov 與處理過的 PTB 數據,這是語言模型任務中使用最為廣泛的公開數據之一。 PTB 數據集包含 10000 個不同的詞語(包含句子結束符 <eos> ,以及表示 低頻詞的特殊符號 <unk> )。?


通過運行 data 目錄下的 download.sh 下載數據,我們將使用其中的 ptb.train.txt 文件進行訓練,文件中一行是一句話,文本中的低頻詞已經全部被替換為 <unk> 預處理時我們會在 每一行的末尾附加上句子結束符 <e>


程序結構


這一節我們首先整體總結一下使用 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)


讓執行器執行 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 程序的整體結構非常相似,使用經驗可以非常容易的遷移。


構建網絡結構及運行訓練


加載訓練數據


PaddleFluid?


定義 輸入data layers


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


word?=?fluid.layers.data(
????????name="current_word",?shape=[1],?dtype="int64",?lod_level=1)
lbl?=?fluid.layers.data(
????????name="next_word",?shape=[1],?dtype="int64",?lod_level=1)


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


2. RNN LM 使用 one-hot 作為輸入,一個詞用一個和字典大小相同的向量表示,每一個位置對應了字典中的 一個詞語。one-hot 向量僅有一個維度為 1, 其余全部為 0。因此為了節約存儲空間,通常都直接用一個整型數表示給出詞語在字典中的 id,而不是真的創建一個和詞典同樣大小的向量 ,因此在上面定義的 data layer 中 word lbl 的形狀都是 1,類型是 int64 。?


3. 需要特別說明的是,實際上 word ?lbl 是兩個 [batch_size x 1] 的向量,這里的 batch size 是指一個 mini-batch 中序列中的總詞數。對序列學習任務, mini-batch 中每個序列長度 總是在發生變化,因此實際的 batch_size 只有在運行時才可以確定。 batch size 總是一個輸入 Tensor 的第 0 維,在 PaddleFluid 中指定 data layer 的 shape 時,不需要指定 batch size 的大小,也不需要考慮占位。框架會自動補充占位符,并且在運行時 設置正確的維度信息。因此,上面的兩個 data layer 的 shape 都只需要設置第二個維度,也就是 1。


LoD Tensor和Non-Padding的序列輸入?


與前兩篇文章中的任務相比,在上面的代碼片段中定義 data layer 時,出現了一個新的 lod_level 字段,并設置為 1。這里就要介紹在 Fluid 系統中表示序列輸入的一個重要概念 LoDTensor。?


那么,什么是 LoD(Level-of-Detail) Tensor 呢??


1. Tensor 是 nn-dimensional arry 的推廣,LoDTensor 是在 Tensor 基礎上附加了序列信息。?


2. Fluid 中輸入、輸出,網絡中的可學習參數全部統一使用 LoDTensor(n-dimension array)表示,對非序列數據,LoD 信息為空。一個 mini-batch 輸入數據是一個 LoDTensor。?


3. 在 Fluid 中,RNN 處理變長序列無需 padding,得益于 LoDTensor表示。?


4. 可以簡單將 LoD 理解為:std::vector<std::vector>


下圖是 LoDTensor 示意圖(圖片來自 Paddle 官方文檔):


▲?圖5. LoD Tensor示意圖


LoD 信息是附著在一個 Tensor 的第 0 維(也就是 batch size 對應的維度),來對一個 batch 中的數據進一步進行劃分,表示了一個序列在整個 batch 中的起始位置。?


LoD 信息可以嵌套,形成嵌套序列。例如,NLP 領域中的段落是一種天然的嵌套序列,段落是句子的序列,句子是詞語的序列。?


LoD 中的 level 就表示了序列信息的嵌套:


  • 圖 (a) 的 LoD 信息 [0, 5, 8, 10, 14] :這個 batch 中共含有 4 條序列。

  • 圖 (b) 的 LoD 信息 [[0, 5, 8, 10, 14] /*level=1*/, [0, 2, 3, 5, 7, 8, 10, 13, 14] /*level=2*/] :這個 batch 中含有嵌套的雙層序列。


有了 LoDTensor 這樣的數據表示方式,用戶不需要對輸入序列進行填充,框架會自動完成 RNN 的并行計算處理。


如何構造序列輸入信息?


明白了 LoD Tensor 的概念之后,另一個重要的問題是應該如何構造序列輸入。在 PaddleFluid 中,通過 DataFeeder 模塊來為網絡中的 data layer 提供數據,調用方式如下面的代碼所示:


train_reader?=?paddle.batch(
????????paddle.reader.shuffle(train_data,?buf_size=51200),
????????batch_size=conf.batch_size)

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


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


def?train_data(data_dir="data"):
????data_path?=?os.path.join(data_dir,?"ptb.train.txt")
????_,?word_to_id?=?build_vocab(data_path)

????with?open(data_path,?"r")?as?ftrain:
????????for?line?in?ftrain:
????????????words?=?line.strip().split()
????????????word_ids?=?[word_to_id[w]?for?w?in?words]
????????????yield?word_ids[0:-1],?word_ids[1:]


在上面的代碼中:?


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


2. train_data 打開原始數據數據文件,讀取一行(一行既是一條數據),返回一個 python list,這個 python list 既是序列中所有時間步。具體的數據組織方式如下表所示(其中,f 代表一個浮點數,i 代表一個整數):



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


TensorFlow?


TensorFlow 中使用占位符 placeholder 接收 訓練數據,可以認為其概念等價于 PaddleFluid 中的 data layer。同樣的,我們定義了如下兩個 placeholder 用于接收當前詞與下一個詞語:


def?placeholders(self):
????self._inputs?=?tf.placeholder(tf.int32,
??????????????????????????????????[None,?self.max_sequence_length])
????self._targets?=?tf.placeholder(tf.int32,?[None,?self.vocab_size])


1. placeholder 只存儲一個 mini-batch 的輸入數據。與 PaddleFluid 中相同, _inputs 這里接收的是 one-hot 輸入,也就是該詞語在詞典中的 index,one-hot 表示 會進一步通過此詞向量層的作用轉化為實值的詞向量表示。


2. 需要注意的是,TensorFlow 模型中網絡輸入數據需要進行填充,保證一個 mini-batch 中序列長度 相等。也就是一個 mini-batch 中的數據長度都是 max_seq_length ,這一點與 PaddleFluid 非常不同。?


通常做法 是對不等長序列進行填充,在這一篇示例中我們使用一種簡化的做法,每條訓練樣本都按照 max_sequence_length 來切割,保證一個 mini-batch 中的序列是等長的。?


于是, _input shape=[batch_size, max_sequence_length]? max_sequence_length 即為 RNN 可以展開長度。


構建網絡結構?


PaddleFluid?RNN LM?


這里主要關注最核心的 LSTM 單元如何定義:


def?__rnn(self,?input):
????for?i?in?range(self.num_layers):
????????hidden?=?fluid.layers.fc(
????????????size=self.hidden_dim?*?4,
????????????bias_attr=fluid.ParamAttr(
????????????????initializer=NormalInitializer(loc=0.0,?scale=1.0)),
????????????input=hidden?if?i?else?input)
????????lstm?=?fluid.layers.dynamic_lstm(
????????????input=hidden,
????????????size=self.hidden_dim?*?4,
????????????candidate_activation="tanh",
????????????gate_activation="sigmoid",
????????????cell_activation="sigmoid",
????????????bias_attr=fluid.ParamAttr(
????????????????initializer=NormalInitializer(loc=0.0,?scale=1.0)),
????????????is_reverse=False)
????return?lstm


PaddleFluid 中的所有 RNN 單元(RNN/LSTM/GRU)都支持非填充序列作為輸入,框架會自動完成不等長序列的并行處理。當需要堆疊多個 LSTM 作為輸入時,只需利用 Python 的 for 循環語句,讓一個 LSTM 的輸出成為下一個 LSTM 的輸入即可。在上面的代碼片段中有一點需要特別注意:PaddleFluid 中的 LSTM 單元是由 fluid.layers.fc+ fluid.layers.dynamic_lstm 共同構成的。


▲?圖6. LSTM計算公式


圖 6 是 LSTM 計算公式,圖中用紅色圈起來的計算是每一時刻輸入矩陣流入三個門和 memory cell 的之前的映射。PaddleFluid 將這個四個矩陣運算合并為一個大矩陣一次性計算完畢, fluid.layers.dynamic_lstm 不包含這部分運算。因此:?


1. PaddleFluid 中的 LSTM 單元是由 fluid.layers.fc + fluid.layers.dynamic_lstm 。?


2. 假設 LSTM 單元的隱層大小是 128 維, fluid.layers.fc fluid.layers.dynamic_lstm 的 size 都應該設置為 128 * 4,而不是 128。?


TensorFlow RNN LM?


這里主要關注最核心的 LSTM 單元如何定義:


def?rnn(self):
????def?lstm_cell():
????????return?tf.contrib.rnn.BasicLSTMCell(
????????????self.hidden_dim,?state_is_tuple=True)

????cells?=?[lstm_cell()?for?_?in?range(self.num_layers)]
????cell?=?tf.contrib.rnn.MultiRNNCell(cells,?state_is_tuple=True)

????_inputs?=?self.input_embedding()
????_outputs,?_?=?tf.nn.dynamic_rnn(
????????cell=cell,?inputs=_inputs,?dtype=tf.float32)

????last?=?_outputs[:,?-1,?:]
????logits?=?tf.layers.dense(inputs=last,?units=self.vocab_size)
????prediction?=?tf.nn.softmax(logits)


?tf.nn.rnn_cell.BasicLSTMCell(n_hidden, state_is_tuple=True) : 是最基本的 LSTM 單元。 n_hidden 表示 LSTM 單元隱層大小。 state_is_tuple=True 表示返回的狀態用一個元祖表示。?


?tf.contrib.rnn.MultiRNNCell : 用來 wrap 一組序列調用的 RNN 單元的 wrapper。?


?tf.nn.dynamic_rnn :?通過指定 mini-batch 中序列的長度,可以跳過 padding 部分的計算,減少計算量。這一篇的例子中由于我們對輸入數據進行了處理,將它們都按照 max_sequence_length 切割。?


但是, dynamic_rnn 可以讓不同 mini-batch 的 batch size 長度不同,但同一次迭代一個 batch 內部的所有數據長度仍然是固定的。


運行訓練?


運行訓練任務對兩個平臺都是常規流程,可以參考上文在程序結構一節介紹的流程,以及代碼部分:PaddleFluid vs. TensorFlow,這里不再贅述。

總結


這一篇我們第一次接觸 PaddleFluid 和 TensorFlow 平臺的序列模型。了解 PaddleFluid 和 TensorFlow 在接受序列輸入,序列處理策略上的不同。序列模型是神經網絡模型中較為復雜的一類模型結構,可以衍生出非常復雜的模型結構。?


不論是 PaddleFluid 以及 TensorFlow 都實現了多種不同的序列建模單元,如何選擇使用這些不同的序列建模單元有很大的學問。到目前為止平臺使用的一些其它重要主題:例如多線程多卡,如何利用混合設備計算等我們還尚未涉及。接下來的篇章將會繼續深入 PaddleFluid 和 TensorFlow 平臺的序列模型處理機制,以及更多重要功能如何在兩個平臺之間實現。


參考文獻


[1]. 本文配套代碼

https://github.com/JohnRabbbit/TF2Fluid/tree/master/03_rnnlm

[2].?Understanding LSTM Networks

http://colah.github.io/posts/2015-08-Understanding-LSTMs/

[3].?train_data具體實現

https://github.com/JohnRabbbit/TF2Fluid/blob/master/03_rnnlm/load_data_fluid.py



關于PaperWeekly


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


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

總結

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

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

主站蜘蛛池模板: 色欲狠狠躁天天躁无码中文字幕 | xxx视频在线观看 | 手机av网址 | 97超碰人人草 | 91青青草视频 | 国产成人精品无码免费看81 | 久久免费在线观看 | 国产剧情在线 | 一区二区三区中文字幕 | 夜夜操导航 | 精品人伦一区二区三区蜜桃免费 | wwwxxx在线观看 | 欧美 亚洲 | 无码精品人妻一区二区 | 成年人视频网站 | 中国黄色小视频 | 操穴网站 | 打屁股调教视频 | 亚洲福利国产 | 被黑人啪到哭的番号922在线 | 中文字幕欧美一区 | 99在线无码精品入口 | 91精品在线免费观看 | 性感美女在线观看 | 国产xxx| 老司机精品视频网站 | 欧美做爰全过程免费观看 | 国产欧美精品 | 少妇性高潮视频 | 亚洲精品97久久中文字幕无码 | 色88久久久久高潮综合影院 | 中文字幕日韩在线播放 | 在线播放www | 在线香蕉 | 日韩av成人网 | 91精品国产一区二区在线观看 | 亚洲xx网| 中文字幕淫 | 大桥未久av一区二区三区中文 | 国产一区二区精品丝袜 | 欧美日韩中文国产 | аⅴ资源中文在线天堂 | 岛国片免费在线观看 | 中文字幕亚洲欧美日韩在线不卡 | 久久久久久久黄色 | 色视频免费观看 | 鲁丝片一区二区三区 | 日本不卡一区二区在线观看 | 一道本久久 | 麻豆观看 | 精品人妻中文无码av在线 | 午夜久久 | 久久久久性 | 成全世界免费高清观看 | 亚洲黄色网页 | 日本免费网站视频 | 国产91av在线播放 | 欧美区一区二 | 在线精品一区二区三区 | 婷婷亚洲一区 | 成人亚洲欧美 | 久操这里只有精品 | 一级性生活毛片 | 亚洲av日韩av在线观看 | 性色av一区二区三区免费 | 狂野欧美性猛交xxⅹ李丽珍 | 深夜老司机福利 | 91在线免费视频 | 久久国产人妻一区二区免色戒电影 | 99国产精品国产精品九九 | 久久久久久久久网站 | 91蝌蚪在线| 99久久久无码国产精品免费麻豆 | 无套暴操 | 无遮挡毛片 | 国产一区二区三区精品在线 | 精品久久久久国产 | 自拍偷拍国产 | 99久久久国产精品无码网爆 | 少妇看片| 日韩欧美亚洲 | 自拍偷拍视频在线观看 | 日韩av视屏 | 精品人妻久久久久一区二区三区 | 蜜桃av免费 | 久久爱影视i | 波多野结衣办公室双飞 | 青草视频在线观看视频 | 五月av在线 | 黑人一区二区三区 | 欧美 亚洲 激情 一区 | 琪琪色av | www.jizzjizz | 黄色性视频| 插插看| 高清乱码毛片 | 欧美视频第一区 | 色多多在线看 | 久久尹人 |