應用到文本領域的卷積方法

原文:Convolutional Methods for Text

tl;dr

  • RNNS對於文本非常有用,但是卷積網絡擁有更快的效率
  • 句子的任何部分都可能影響到一個單詞的語義。 因此,我們希望我們的網絡能夠一次看到整個輸入
  • 獲得這麼大的接受能使梯度消失,我們的網絡失敗
  • 我們可以解決DenseNets或擴張卷的消失梯度問題
  • 有時我們需要生成文本。 我們可以使用“deconvolutions”來產生任意長的輸出。

Intro

在過去三年中,由於深度學習的火熱,NLP領域經歷了巨大的革命。 這場革命的領導者是循環神經網絡,特別是其LSTM模型的表現。 同時,計算機視覺領域也被卷積神經網絡重塑。 這篇文章探討了我們“研究文本的人”可以從我們做計算機視覺的朋友那裏學到什麼。

Common NLP Tasks

爲了展示在詞彙基礎上的情景,我介紹了在NLP中介紹一些更常見的任務。 爲了保持一致性,我假設我們所有的模型的輸入是字符,我們的“觀察單位”是一個句子。 這兩個假設只是爲了方便起見,如果您願意,您可以用文字和句子替換字符。

Classification

這也許是這本書中最古老的技巧,我們經常想把句子分類。 例如,我們可能希望將電子郵件主題分類爲是否是垃圾郵件的指示,猜測產品評論的意見或將主題分配給文檔。

用RNN處理這種任務的直接方法是逐字輸入整個句子,然後觀察RNN的最終隱藏狀態。

Sequence Labeling

序列標籤任務是返回每個輸入對應的輸出的任務。 示例包括部分語音標籤或實體識別任務。 單純的LSTM雖然並不是當下最先進的技術,但易於實施並提供了令人信服的效果。 這篇文章 爲Sequence Labeling任務提供了更加豐富的架構:
這裏寫圖片描述

Sequence Generation

可以說,最近的NLP中最令人印象深刻的任務是翻譯。 翻譯是一個序列到另一個序列的映射,對輸出句子的長度沒有保證。 例如,將聖經的第一句話從希伯來語翻譯成英文是בראשית=“In the Beginning”。

fig2

A basic Encoder Decoder for English to German translation (source)

成功的關鍵是序列到序列(AKA編碼器解碼器)框架,一種將序列“壓縮”成代碼,然後將其解碼爲另一個序列的方法。 值得注意的例子包括翻譯(編碼希伯來語和解碼爲英文),圖像字幕(編碼圖像和解碼其內容的文本描述)

fig3

Image captioning with Sequence to Sequence models (Source)

基本的編碼器步驟類似於我們描述的分類的方案。最激動人心的是,我們可以構建一個學習生成任意長度輸出的解碼器。

上面的兩個例子都是翻譯,但序列生成的範圍比這更廣泛。 OpenAI最近發表了一篇文章,他們在控制輸出情緒的同時學會產生“Amazon Reviews”

fig4

Example outputs from OpenAI. They trained a charterer level language model on Amazon reviews. They discovered a single neuron in their model responsible for sentiment and by fixing its value were able to generate new reviews with a particular sentiment. (Source)

另一個個人最喜歡的論文是Generating Sentences from a Continuous Space。 在這篇文章中,他們基於文本訓練了一個變分自編碼器,從而擁有了兩句話之間的插值的能力,得到了一致的結果。

fig5

Interpolating between sentences (Homotopies) . (Source)

Requirements from an NLP architecture

我們所看到的所有實現都是基於循環的架構,通常是LSTM模型(如果你不確定這是什麼,這篇文章是一個很好的介紹)。 值得注意的是,沒有任何一個任務的名字中有循環,沒有人提到LSTM。考慮到這一點,讓我們花點時間來思考RNN,特別是LSTM提供了什麼,使它們在NLP中無處不在。

Arbitrary Input Size

一個標準的前饋神經網絡每個輸入都有一個參數。 在處理文本或圖像時,由於以下幾個原因,這將成爲一個問題。

  1. 它限制了我們可以處理的輸入大小。 我們的網絡將具有有限數量的輸入節點,並且將無法增長到更多。
  2. 我們失去了很多共同的信息。 考慮句子“I like to drink beer a lot”和“I like to drink a lot of beer”。 前饋網絡必須每次在不同的輸入節點中學習到“a lot”的概念。

循環神經網絡解決了這個問題。不再爲每個輸入設置一個節點,我們有一個大的“box”的節點,我們一次又一次地應用於輸入。 “box”學習一種過渡函數,這意味着輸出遵循一些循環關係。

請記住,研究計算機視覺的人對圖像使用卷積取得了相同的效果。卷積允許跨整個圖像重用相同的小的參數集合而非爲每個像素設置一個輸入節點。

Long Term Dependencies

RNN的承諾是他們模擬長期依賴的能力。 以下圖片取自OpenAI。 他們訓練了一個模型,最終以模型的輸出,逐字識別情感和色彩。 請注意模型如何看待“best”一詞,觸發超過100個字符的積極情緒。 這是捕獲長距離的依賴。

fig6

RNN的理論承諾我們長序列依賴於box的輸出。 這種做法有點困難。 當我們通過反向傳播學習時,我們需要通過整個遞歸關係傳播信號。 事情是,在每一步,我們最終乘以一個數字。 如果這些數字一般小於1,我們的信號會很快進入0。如果它們大於1,那麼我們的信號將會爆炸。

這些問題被稱爲消失和爆炸的梯度,通常可以通過LSTM和幾個聰明的技巧來解決。 之所以提到這些,因爲我們會再次遇到這些問題,並且需要另外一種解決方法。

Advantages of convolutions

到目前爲止,我們已經看到了LSTM的偉大,但是這篇文章是關於卷積的。 本着don’t fix what ain’t broken的精神,我們必須問自己爲什麼要使用卷積。

一個答案是“Because we can”。

但是還有另外兩個令人信服的理由來使用卷積,速度和上下文。

Parrelalisation

RNN依次運行,第二個輸入的輸出取決於第一個輸入,因此我們無法使RNN並行化。 卷積沒有這樣的問題,卷積內核的每個“patch”都是獨立的,我們可以同時遍歷整個輸入層。

要爲此付出的代價是,我們必須將卷積疊加到深層,以便查看整個輸入,並且按順序計算每個層。 但是,每層的計算同時發生,每個單獨的計算都很小(與LSTM相比),因此實際上我們得到了很大的加速。

當我開始寫這個時,我只有自己的經驗和Google的ByteNet來支持這個說法。 就在本週,Facebook發佈了完整的卷積翻譯模型,是LSTM的9倍速度。

View the whole input at once

LSTM從左到右(或從右到左)讀取他們的輸入,但有時候我們想讓句子結尾的上下文影響網絡對其開始的想法。 例如,我們可能會有一個句子,如“I’d love to buy your product. Not!“我們希望最後的否定會影響整個句子。

Borat learns to tell a “Not” joke

使用LSTM的話,我們必須通過運行兩個LSTM來實現這一點,一個從左到右,另一個從左到右並連接其輸出。 這在實踐中運行良好,但是我們的計算負載增加了一倍。

另一方面,當我們堆疊越來越多的層時,卷積增長了一個更大的“接受領域”。 這意味着默認情況下,卷積表示中的每個“步驟”都會從其前後觀察其接受領域中的所有輸入。 我不知道有什麼明確的論據,證明這本質上比LSTM更好,但它確實以可控的方式給我們帶來了希望的效果,而且計算成本低。

到目前爲止,我們已經設置了我們的問題域,並且談了NLP中卷積的概念優勢。 從這裏出發,我想將這些概念轉化爲可用於分析和構建網絡的實際方法。

Practical convolutions for text

fig7

Source

你可能已經看到一個像上面那樣的動畫,說明了卷積的作用。 底部是輸入圖像,頂部是結果,灰色陰影是重複應用的卷積核。

除了圖片中描述的輸入是具有兩個空間尺寸(高度和寬度)的圖像之外,這一切都是完美的。 我們正在談論的文本只有一個維度,而且它的時間不是空間的。

對於實際目的,這並不重要。 我們只需要將我們的文本視爲寬度n和高度1的圖像。Tensorflow提供了一個對我們執行的conv1d函數,但它並沒有在其1d版本中公開其他卷積運算。

爲了使“文本=高度1的圖像”具體化,讓我們看看在Tensorflow中如何在一系列嵌入式草種牌中使用2d卷積運算。

import tensorflow as tf
def conv1d(input_, output_size, width, stride):
    '''
    :param input_: A tensor of embedded tokens with shape [batch_size,max_length,embedding_size]
    :param output_size: The number of feature maps we'd like to calculate
    :param width: The filter width
    :param stride: The stride
    :return: A tensor of the concolved input with shape [batch_size,max_length,output_size]
    '''
    inputSize = input_.get_shape()[-1] # How many channels on the input (The size of our embedding for instance)

    #This is the kicker where we make our text an image of height 1
    input_ = tf.expand_dims(input_, axis=1) #  Change the shape to [batch_size,1,max_length,output_size]

    #Make sure the height of the filter is 1
    filter_ = tf.get_variable("conv_filter",shape=[1, width, inputSize, output_size])

    #Run the convolution as if this were an image
    convolved = tf.nn.conv2d(input_, filter=filter_,strides=[1, 1, stride, 1], padding="SAME")
    #Remove the extra dimension, eg make the shape [batch_size,max_length,output_size]
    result = tf.squeeze(convolved, axis=1)
    return result

所以我們在這裏做的是用tf.expand_dims來改變輸入的形狀,使其成爲一個“高度1”的圖像。 運行2d卷積運算符後,我們擠出了額外的維度。

Hierarchy and Receptive Fields

fig8

我們中許多人已經看過像上面那樣的照片。 它大致顯示了CNN學習圖像的抽象層次。 在第一層,網絡學習基本的邊緣。 在下一層,它結合了這些邊緣來學習更多的抽象概念,如眼睛和鼻子。 最後,它結合了那些識別個人面孔。

考慮到這一點,我們需要記住,每個層不僅僅是學習上一層的更多抽象組合。 連續層次隱含或明確地看到更多的輸入

fig9

Increasing Receptive Field

在視覺領域,我們會希望網絡識別圖片中的一個或多個對象,而忽略其他對象。 也就是說,我們會對一些局部現象感興趣,但並不在於跨越整個投入的關係。

fig10

A convolutional network learns to recognize hotdogs. It doesn’t care what the hot dog is on, that the table is made of wood etc. It only cares if it saw a hotdog. (Source)

文本更微妙,我們經常希望我們的數據的中間表示,儘可能多考慮上下文環境。 換句話說,我們希望擁有儘可能大的接受領域。 這裏有幾個方法來解決這個問題。

Larger Filters

第一個最明顯的方法是增加Filter的大小,即進行[1x5]卷積而不是[1x3]。 在我的文字工作中,這種方法並沒有取得很好的結果,我會提供我的推測爲什麼會這樣。

在我的研究領域中,我主要處理字符級別的輸入和形式非常豐富的文本。 我想到(至少第一個)卷積的層次作爲學習n-gram,使得過濾器的寬度對應於二進制,三元組等。網絡學習較大的n-gram早期暴露於較少的示例,因爲有更多的 在文本中出現的“ab”比“abb”。

我從來沒有證明過這種解釋,但濾波器寬度大於3的結果一直較差。

Adding Layers

正如我們在上圖中看到的,添加更多的層將增加接受野。 Dang Ha The Hien寫了一個great guide,我建議您閱讀。

添加圖層有兩個不同但相關的效果。 被提到的很多的是,該模型將學習對其獲得的輸入進行更高級別的抽象(Pixels => Edges => Eyes => Face)。 另一個是接受場在每一步都會增長。

This means that given enough depth, our network could look at the entire input layer though perhaps through a haze of abstractions. Unfortunately this is where the vanishing gradient problem may rear its ugly head.

The Gradient / Receptive field trade off

神經網絡是信息流經的網絡。 在輸入流和轉化的前向過程中,希望成爲更適合我們任務的表示。 在後期階段,我們通過網絡回傳信號,梯度。 就像在RNN一樣,該信號經常被倍增,如果它經過一系列小於1的數字,那麼它會消失到0。這意味着我們的網絡最終會得到很少的信號來學習。

這讓我們有了一些權衡。 一方面,我們希望能夠儘可能多考慮上下文。 另一方面,如果我們嘗試通過堆疊層來增加我們的接受野,我們會冒着消失的梯度和沒有學習任何東西的風險。

Two Solutions to the Vanishing Gradient Problem

幸運的是,很多大牛一直在思考這些問題。 更幸運的是,這些不是文本獨有的問題,研究視覺的人們也希望更大的接受領域和信息豐富的梯度。 讓我們來看看他們的一些瘋狂的想法,並用它們來進一步推動自己的文本的榮耀。

Residual Connections

對於研究計算機視覺的研究者們,2016年是另一個偉大的年份,至少有兩個非常受歡迎的架構出現, ResNetsDenseNets(特別是DenseNet論文,寫得非常好,非常值得閱讀)。 他們都解決同樣的問題—“如何使我的網絡非常深而不失去梯度信號?”

Arthur Juliani 寫下了關於Resnet, DenseNets and Highway networks的精彩概述,爲您尋找他們之間的細節和對比。 我將簡要介紹將核心概念推向極致的DenseNets。

fig11

A densenet architecture (Source)

一般的想法是減少來自網絡loss的信號與每個單獨層之間的距離。 這樣做的方法是通過在每個層與其前身之間添加一個 residual/direct連接。 這樣,梯度可以直接從每一層流向其前一層。

DenseNets以一種特別有趣的方式做到這一點。 它們將每個層的輸出連接到其輸入,使得:

  1. 我們從輸入的嵌入開始,就是說維度10。
  2. 我們的第一層計算10個特徵圖。 它的輸出連接到原始嵌入的10個特徵映射。
  3. 第二層作爲輸入20維向量(來自輸入的10個,前一層的10個),並計算另外10個特徵圖。 因此,它輸出30維向量。

等等,等等你想要的層數。 該文獻描述了一系列技巧,使事情可以管理和高效,但這是基本前提,梯度消失的問題得到解決。

還有另外兩件事我想指出。

  1. 我之前提到,上層可以看到可能被抽象層所掩蓋的原始輸入的視圖。連接每層輸出的亮點之一是,原始信號完整地達到下列層,以便所有層都具有較低層次特徵的直觀視圖,從而基本上去除了一些霧度。
  2. Residual 連接技巧要求我們所有的層都具有相同的形狀。這意味着我們需要填充每個層,使其輸入和輸出具有相同的空間維度[1Xwidth]。這意味着,這種架構本身就適用於序列標籤任務(輸入和輸出具有相同的空間維度),但是需要更多的編碼和分類任務(我們需要將輸入減少到一個固定大小的向量或一組向量)。 DenseNet論文實際上處理這個問題,因爲他們的目標是做分類,我們稍後會在這一點上展開。

Dilated Convolutions

Dilated convolutions AKA atrous convolutions AKA convolutions with holes 是增加接受場而不會激怒梯度的另一種方法。目前爲止,當我們看堆疊層時,我們看到接收場隨深度線性增長。Dilated convolutions使我們隨着深度指數地增長接受場。

您可以在論文 Multi scale context aggregation by dilated convolutions 中找到擴展卷積的幾乎合理的解釋。雖然在概念上很簡單,但花了我一段時間才能明確地瞭解他們的工作,我可能還是不太瞭解。

基本思想是在每個過濾器中引入“holes”,使其不在輸入的相鄰部分上操作,而是跳過它們到更遠的部分。請注意,這與使用stride> 1的卷積不同。當我們跨越過濾器時,我們跳過卷積應用之間的部分輸入。隨着卷積的擴大,我們在卷積的單個應用中跳過了部分輸入。通過巧妙地安排日益擴大的擴張,我們可以實現接受場的指數增長。

fig12

Here we have a 3X3 filter applied with a dilation of 1,2 and 3. With a dilation of 1 we have a standard convolution. With a dilation of 2 we apply the same 3X3 filter but use every second pixel.

到目前爲止,我們已經談到了很多理論,但是我們終於可以看到他們的實際作用了!

個人最喜歡的文章是Neural Machine Translation in Linear Time。 它遵循我們在開始時談到的編碼器解碼器結構。 我們仍然沒有工具來談論解碼器,但我們可以看到編碼器在實際運行。

fig13

The Encoder part of bytenet based on dilated convolutions. Notice how four layers in the effective receptive field is 16. even though the filter widths are just 3. (Source)

這裏有一個英文輸入:

Director Jon Favreau, who is currently working on Disney’s forthcoming Jungle Book film, told the website Hollywood Reporter: “I think times are changing.”

通過擴大的卷積給你的翻譯:

Regisseur Jon Favreau, der zur Zeit an Disneys kommendem Jungle Book Film arbeitet, hat der Website Hollywood Reporter gesagt: “Ich denke, die Zeiten andern sich”.

作爲一個獎勵,請記住,聲音就像文本一樣,它只具有一個空間/時間維度。 查看DeepMind的Wavenet,它使用擴大的卷積(和許多其他魔法)來生成human sounding speechpiano music

Getting Stuff Out of your network

當我們討論DenseNets時,我提到使用residual connections迫使我們保持序列的輸入和輸出長度相同,這是通過填充完成的。 這對於我們需要在序列中標記每個項目的任務非常有用,例如:

  • 在詞性標註中,每個單詞都是語音的一部分。
  • 在實體識別中,我們可以將“人物”,“公司”和“其他”標記爲其他內容

其他時候,我們要將輸入序列減少到矢量表示,並用它來預測整個句子的內容

  • 我們可能會根據其內容或主題將電子郵件標記爲垃圾郵件
  • 預測某句話是否諷刺

在這些情況下,我們可以按照傳統的計算式視覺研究者們的觀點,並以不具有填充和/或使用池操作的卷積層來覆蓋我們的網絡。

但是有時候,我們想要遵循Seq2Seq範式, Matthew Honnibal 簡潔地稱之爲Embed, encode, attend, predict。 在這種情況下,我們將輸入減少到一些向量表示,然後需要以某種方式將該向量的樣本返回到適當長度的序列。

這個任務需要兩個問題

  • 我們如何用卷積進行上採樣?
  • 我們如何做正確的抽樣數量?

我還沒有找到第二個問題的答案,至少還沒有明白。 在實踐中,我已經足夠讓我在輸出的最大長度上假設一些上限,然後向上補充。 我估計Facebook的 translation paper論文可能會解決這個問題,但還沒有深入閱讀它來評論。

Upsampling with deconvolutions

反捲積是我們上採樣的工具。 很容易通過可視化來了解他們怎麼做的。 幸運的是,幾個大牛在Distill出版了一個關於deconvolutions的 great post on deconvolutions ,幷包括一些有趣的可視化。 讓我們從那些開始。

fig14

考慮頂部的圖像。 如果我們把底層作爲輸入,我們有一個步幅1和寬度3的標準卷積。但是,我們也可以從上到下,即頂層作爲輸入,得到稍大的底層。

如果您停止思考一秒鐘,則當您進行反向傳播時,這種“自頂向下”操作已經在您的卷積網絡中發生,因爲梯度信號需要以完全如圖所示的方式傳播。 更好的是,事實證明,這個操作只是卷積操作的轉置,因此這個操作的另一個常用(和技術上正確的)名稱被轉置卷積。

這裏是它的樂趣。 We can stride our convolutions to shrink our input。 因此,我們可以stride 我們的deconvolutions來增加我們的輸入。 我認爲了解如何使用deconvolutions工作的最簡單的方法是查看以下圖片。

fig15

我們已經看到了最上面的一個。 請注意,每個輸入(頂層)輸入三個輸出,每個輸出由三個輸入(邊沿除外)饋送。

fig16

在第二張照片中,我們在輸入中放置虛構的孔。 請注意,現在每個輸出都由最多兩個輸入饋送。

fig17

在第三張照片中,我們在輸出層中添加了兩個虛擬孔,因此每個輸出都只有一個輸入。 這將使輸出的序列長度相對於輸入的序列長度增加三倍。

最後,我們可以堆疊多個解卷積層,逐漸將我們的輸出層增長到所需的大小。

一些值得思考的事情:

  1. 從底部看這些圖紙,他們最終成爲標準的階梯卷積,我們剛剛在輸出層中添加了虛構的孔(白色塊)
  2. 在實踐中,每個“輸入”不是單個數字而是向量。 在圖像世界中,它可能是3維RGB值。 在文本中可能是一個300維字嵌入。 如果你(de)捲入網絡中間,每個點都將是從最後一層出來的任何大小的向量。
  3. 我指出,爲了說服你,他們在反捲積的輸入層中有足夠的信息來分散在輸出的幾個點上。
  4. 在實踐中,我已經成功地運行了在反捲積之後一些保留填充長度相同後的卷積。 我想象,儘管沒有證明,這就像是信息的重新分配。 像燒烤後讓牛排休息,讓果汁重新分配。

fig18

Summary

你可能想在你的工作中考慮卷積的主要原因是因爲它們很快。 我認爲,使研究和探索更快更有效率是至關重要的。 更快的網絡縮短了我們的反饋週期。

與文字遇到的大部分任務最終都具有相同的體系結構要求:在保持足夠的梯度流程的同時,最大限度地提高接受場。 我們已經看到使用DenseNets和dilated convolutions來實現這一點。

最後,有時候我們想將一個序列或一個向量擴展成一個更大的序列。 我們將deconvolutions視爲對文本進行“上採樣”的一種方式,並作爲獎勵,相比之下添加捲積,然後放牛排休息並重新分配果汁。

我想更多地瞭解關於這些模型中你的想法和經驗。 請在Twitter @thetalperry評論

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章