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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Seq2Seq之双向解码机制 | 附开源实现

發布時間:2024/10/8 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Seq2Seq之双向解码机制 | 附开源实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


作者丨蘇劍林

單位丨追一科技

研究方向丨NLP,神經網絡

個人主頁丨kexue.fm


在文章玩轉Keras之Seq2Seq自動生成標題中我們已經基本探討過 Seq2Seq,并且給出了參考的 Keras 實現。?


本文則將這個 Seq2Seq?再往前推一步,引入雙向的解碼機制,它在一定程度上能提高生成文本的質量(尤其是生成較長文本時)。本文所介紹的雙向解碼機制參考自 Synchronous Bidirectional Neural Machine Translation,最后筆者也是用 Keras 實現的。




背景介紹


研究過 Seq2Seq?的讀者都知道,常見的 Seq2Seq?的解碼過程是從左往右逐字(詞)生成的,即根據 encoder 的結果先生成第一個字;然后根據 encoder 的結果以及已經生成的第一個字,來去生成第二個字;再根據 encoder 的結果和前兩個字,來生成第三個詞;依此類推。總的來說,就是在建模如下概率分解。



當然,也可以從右往左生成,也就是先生成倒數第一個字,再生成倒數第二個字、倒數第三個字,等等。問題是,不管從哪個方向生成,都會有方向性傾斜的問題。比如,從左往右生成的話,前幾個字的生成準確率肯定會比后幾個字要高,反之亦然。在 Synchronous Bidirectional Neural Machine Translation 給出了如下的在機器翻譯任務上的統計結果:



L2R 和 R2L 分別是指從左往右和從右往左的解碼生成。從表中我們可以看到,如果從左往右解碼,那么前四個 token 的準確率有 40% 左右,但是最后 4 個 token 的準確率只有 35%;反過來也差不多。這就反映了解碼的不對稱性。?


為了消除這種不對稱性,Synchronous Bidirectional Neural Machine Translation 提出了一個雙向解碼機制,它維護兩個方向的解碼器,然后通過 Attention 來進一步對齊生成。


雙向解碼


雖然本文參考自?Synchronous Bidirectional Neural Machine Translation,但我沒有完全精讀原文,我只是憑自己的直覺粗讀了原文,大致理解了原理之后自己實現的模型,所以并不保證跟原文完全一致。此外,這篇論文并不是第一篇做雙向解碼生成的論文,但它是我看到的雙向解碼的第一篇論文,所以我就只實現了它,并沒有跟其他相關論文進行對比。?


基本思路


既然叫雙向“解碼”,那么改動就只是在 decoder 那里,而不涉及到 encoder,所以下面的介紹中也只側重描述 decoder 部分。還有,要注意的是雙向解碼只是一個策略,而下面只是一種參考實現,并不是標準的、唯一的,這就好比我們說的 Seq2Seq 也只是序列到序列生成模型的泛指,具體 encoder 和 decoder 怎么設計,有很多可調整的地方。?


首先,給出一個簡單的示意動圖,來演示雙向解碼機制的設計和交互過程:


?Seq2Seq的雙向解碼機制圖示


如圖所示,雙向解碼基本上可以看成是兩個不同方向的解碼模塊共存,為了便于描述,我們將上方稱為 L2R 模塊,而下方稱為 R2L 模塊。開始情況下,大家都輸入一個起始標記(上圖中的 S),然后 L2R 模塊負責預測第一個字,而 R2L 模塊負責預測最后一個字。


接著,將第一個字(以及歷史信息)傳入到 L2R 模塊中,來預測第二個字,為了預測第二個字,除了用到 L2R 模塊本身的編碼外,還用到 R2L 模塊已有的編碼結果;反之,將最后一個字(以及歷史信息)傳入到 R2L 模塊,再加上 L2R 模塊已有的編碼信息,來預測倒數第二個字;依此類推,直到出現了結束標記(上圖中的E)。?


數學描述


換句話說,每個模塊預測每一個字時,除了用到模塊內部的信息外,還用到另一模塊已經編碼好的信息序列,而這個“用”是通過 Attention 來實現的。用公式來說,假設當前情況下 L2R 模塊要預測第 n 個字,以及 R2L 模塊要預測倒數第 n 個字。假設經過若干層編碼后,得到的 R2L 向量序列(對應圖中左上方的第二行)為:?



而 R2L 的向量序列(對應圖中左下方的倒數第二行)為:



如果是單向解碼的話,我們會用為特征來預測第 n 個字,或者用作為特征來預測倒數第 n 個字。?


在雙向解碼機制下,我們以為 query,然后以為 key 和 value 來做一個 Attention,用 Attention 的輸出作為特征來預測第 n 個字,這樣在預測第 n 個字的時候,就可以提前“感知”到后面的字了。


同樣地,我們以為 query,然后以為 key 和 value 來做一個 Attention,用 Attention 的輸出作為特征來預測倒數第 n 個字,這樣在預測倒數第 n 個字的時候,就可以提前“感知”到前面的字了。


上面示意圖中,上面兩層和下面兩層之間的交互,就是指 Attention。在下面的代碼中,用到的是最普通的乘性 Attention(參考一文讀懂「Attention is All You Need」| 附代碼實現)。


模型實現


上面就是雙向解碼的基本原理和做法。可以感覺到,這樣一來,Seq2Seq 的 decoder 也變得對稱起來了,這是一個很漂亮的特點。當然,為了完全實現這個模型,還需要思考一些問題:1. 怎么訓練?2. 怎么預測??


訓練方案?


跟普通的 Seq2Seq 一樣,基本的訓練方案就是用所謂的 Teacher-Forcing 的方式來進行訓練,即 L2R 方向在預測第 n 個字的時候,假設前 n?1 個字都是準確知道的,而 R2L 方向在預測倒數第 n 個字的時候,假設倒數第 n?1,n?2,…,1 個字都是準確知道的。最終的 loss 是兩個方向的逐字交叉熵的平均。?


不過這樣的訓練方案實在是無可奈何之舉,后面我們會分析它信息泄漏的弊端。?


雙向束搜索


現在討論預測過程。?


如果是常規的單向解碼的 Seq2Seq,我們會使用 beam search(束搜索)的算法,給出概率盡可能大的序列。所謂 beam search,指的是依次逐字解碼,每次只保留概率最大的 topk 條“臨時路徑”,直到出現結束標記為止。?


到了雙向解碼這里,情況變得復雜了一些。我們依然用 beam search 的思路,但是同時緩存兩個方向的 topk 結果,也就是說,L2R 和 R2L 兩個方向各存 topk 條臨時路徑。此外,由于雙向解碼時,L2R 的解碼是要參考 R2L 已有的解碼結果的,所以當我們要預測下一個字時,除了要枚舉概率最高的 topk 個字、枚舉 topk 條 L2R 的臨時路徑外,還要枚舉 topk 條 R2L 的臨時路徑,所以一共要計算 topk3 那么多個組合。


而計算完成后,采用了一種最簡單的思路:對每種“字 - L2R 臨時路徑”的得分在“R2L 臨時路徑”這一維度上做了平均,使得的分數變回 topk2個,作為每種“字 - L2R 臨時路徑”的得分,再從這 topk2 個組合中,選出分數最高的 topk 個。而 R2L 這邊的解碼,則要進行反向的、相同的處理。最后,如果 L2R 和 R2L 兩個方向都解碼出了完成的句子,那么就選擇概率(得分)最高的那個。?


這樣的整個過程,我們稱之為“雙向束搜索(雙向beam search)”。如果讀者自己比較熟悉單向的 beam search,甚至自己都寫過 beam search 的話,上述過程其實不難理解(看看代碼就更容易懂了),它算是單向 beam search 自然延伸。


當然,如果對 beam search 本身不了解的話,看上述搜索的過程應該是云里霧里的。所以想要弄清楚原理的讀者,應該要從常規的單向 beam search 出發,先把它弄懂了,然后再看上述解碼過程的描述,最后再看看下面給出的參考代碼,就容易弄懂了。?


代碼參考


下面是筆者給出了雙向解碼的參考實現,整體還是跟之前的玩轉Keras之Seq2Seq自動生成標題一致,只是解碼端從雙向換成單向了:?


https://github.com/bojone/seq2seq/blob/master/seq2seq_bidecoder.py?

注:測試環境還是跟之前差不多,大概是 Python 2.7 + Keras 2.2.4 + Tensorflow 1.8。用 Python 3.x 或者其他環境的朋友,如果你們能自己改,那就做相應的改動,如果你們自己不會改,那也請你們別來問我了,我實在沒有空也沒有義務幫你們跑通每一個環境。本文只討論 Seq2Seq 技術相關的內容可否??


在這個實現里,我覺得有必要解釋一下起始標記和結束標記的事情。在之前的單向解碼的例子中,筆者是用 2 作為起始標記,用 3 作為結束標記。到了雙向解碼這里,一個很自然的問題就是:L2R 和 R2L 兩個方向是不是應該要用兩套起始和結束標記呢??


其實這個應該沒有什么標準答案,我覺得不管是共用一套還是維護兩套起止標記,結果可能都差不多。至于我在上面的參考代碼中,使用的方案有點另類,但我認為比較符合直覺,具體是:依然是只用一套,但是在 L2R 方向中,用 2 作為起始標記、3 作為結束標記,而在 R2L 方向中,用 3 作為起始標記、2 作為結束標記。?


思考分析


最后,我們進一步思考一下這種雙向解碼方案。盡管將解碼過程對稱化是一個很漂亮的特點,但也不代表它完全沒有問題了,將它思考得更深入一些,有助于我們更好地理解和使用它。?


1. 改進生成的原因?


一個有意思的問題是:看上去雙向解碼確實能提高句子首尾的生成質量,但會不會同時降低中間部分的生成質量??


當然,理論上這是有可能的,但實際測試時不是很嚴重。一方面,seq2seq架構的信息編碼和解碼能力還是很強的,所以不會輕易損失信息;另一方面,我們自己去評估一個句子的質量的時候,往往會重點關注首尾部分,如果首尾部分都很合理,而中間部分不至于太糟糕的話,那么我們都認為它是一個合理的句子;反過來,如果首或尾不合理的話,我們會覺得這個句子很糟糕。這樣一來,把句子首尾的生成質量提高了,整體的生成質量也就提高了。


?原論文中雙向解碼相對其它單向模型帶來的提升


2. 對應不上概率模型?


對于單向解碼,我們有清晰的概率解釋,即在估計條件概率 p(Y|X)(也就是 (1))。但是在雙向解碼的時候,我們發現壓根兒不知道怎么對應上一個概率模型,換句話說,我們感覺我們是在算概率,感覺效果也有了,卻不知道真正算得是啥,因為條件概率的條件依賴完全已經被打亂了。?


當然,如果真的有實效的話,理論美感差點也無妨,我說的這一點只是理論審美的追求,大家見仁見智就好。?


3. 信息提前泄漏?


所謂信息泄漏,指的是本來作為預測目標的標簽被用來做輸入了,從而導致訓練階段的 loss 虛低(或者準確率虛高)。?


由于在雙向解碼中,L2R 端的解碼要去讀取 R2L 端已有的向量序列,而在訓練階段,為了預測 R2L 端的第 n 個字,是需要傳入前 n?1 個字的,這樣一來,越解碼到后面,信息泄漏就越嚴重。如下圖所示:


?信息泄漏示意圖。訓練階段,當L2R端在預測“你”的時候,事實上用到了傳入到R2L端的“你”標簽;反之,R2L端預測“北”字的時候,同樣存在這個問題,即用到了L2R的“北”字標簽


信息泄漏的一個表觀現象是:訓練到后期,雙向解碼中 L2R 和 R2L 兩個方向的交叉熵之和,比單獨訓練單向解碼模型時的單個交叉熵還要小,這并不是因為雙向解碼帶來多大的擬合提升,而正是信息泄漏的體現。


既然訓練過程中把信息泄漏了,那為什么這樣的模型還有用呢?我想,大概的原因在文章一開頭的表格中就給出了。還是剛才的例子,L2R 端在預測最后一個字“你”的時候,會用到了 R2L 端所有的已知信息;而 R2L 端是從右往左逐字解碼的,按照文章一開頭的表格的統計數據,我們不難想象到,對于 R2L 端來說,倒數第一個字的預測準確率應該是最高的。


這樣一來,假設 R2L 的倒數第一個字真的能以很高的準確率預測成功的話,那信息泄漏也變成不泄漏了——因為信息泄漏是因為我們人為地傳入了標簽,但如果預測的結果本身就跟標簽一致,那泄漏也不再是泄漏了。


當然,原論文還提供了一個策略來緩解這個泄漏問題,大概做法是先用上述方式訓練一版模型,然后對于每個訓練樣本,用模型生成對應的預測結果(偽標簽),接著再去訓練模型,這一次訓練模型是傳入偽標簽來預測正確標簽,這樣就盡可能地保持了訓練和預測的一致性。


文章小結


本文介紹并實現了一種 Seq2Seq 的雙向解碼機制,它將整個解碼過程對稱化了,從而在一定程度上使得生成質量更高了。個人認為這種改進的嘗試還是有一定的價值的,尤其是對于追求形式美的讀者來說。所以就將其介紹一番。


除此之外,文章也分析了這種雙向解碼可能存在的問題,給出了筆者自己的看法。敬請各位讀者多多交流指教。




點擊以下標題查看作者其他文章:?


  • 變分自編碼器VAE:原來是這么一回事 | 附源碼

  • 再談變分自編碼器VAE:從貝葉斯觀點出發

  • 變分自編碼器VAE:這樣做為什么能成?

  • 簡單修改,讓GAN的判別器秒變編碼器

  • 深度學習中的互信息:無監督提取特征

  • 全新視角:用變分推斷統一理解生成模型

  • 細水長flow之NICE:流模型的基本概念與實現

  • 細水長flow之f-VAEs:Glow與VAEs的聯姻

  • 深度學習中的Lipschitz約束:泛化與生成模型




#投 稿 通 道#

?讓你的論文被更多人看到?



如何才能讓更多的優質內容以更短路徑到達讀者群體,縮短讀者尋找優質內容的成本呢?答案就是:你不認識的人。


總有一些你不認識的人,知道你想知道的東西。PaperWeekly 或許可以成為一座橋梁,促使不同背景、不同方向的學者和學術靈感相互碰撞,迸發出更多的可能性。


PaperWeekly 鼓勵高校實驗室或個人,在我們的平臺上分享各類優質內容,可以是最新論文解讀,也可以是學習心得技術干貨。我們的目的只有一個,讓知識真正流動起來。


??來稿標準:

? 稿件確系個人原創作品,來稿需注明作者個人信息(姓名+學校/工作單位+學歷/職位+研究方向)?

? 如果文章并非首發,請在投稿時提醒并附上所有已發布鏈接?

? PaperWeekly 默認每篇文章都是首發,均會添加“原創”標志


? 投稿郵箱:

? 投稿郵箱:hr@paperweekly.site?

? 所有文章配圖,請單獨在附件中發送?

? 請留下即時聯系方式(微信或手機),以便我們在編輯發布時和作者溝通




?


現在,在「知乎」也能找到我們了

進入知乎首頁搜索「PaperWeekly」

點擊「關注」訂閱我們的專欄吧



關于PaperWeekly


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


▽ 點擊 |?閱讀原文?| 查看作者博客

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的Seq2Seq之双向解码机制 | 附开源实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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