使用CNN,RNN和HAN進行文本分類的對比報告

介紹

你好,世界!!我最近加入Jatana.ai 擔任NLP研究員(實習生and),並被要求使用深度學習模型研究文本分類用例。html

在本文中,我將分享個人經驗和學習,同時嘗試各類神經網絡架構。git

我將介紹3種主要算法,例如:github

  1. 卷積神經網絡(CNN)
  2. 遞歸神經網絡(RNN)
  3. 分層注意網絡(HAN)

對具備丹麥語,意大利語,德語,英語和土耳其語的數據集進行文本分類。算法

咱們來吧。✅bash

關於天然語言處理(NLP)

在不一樣業務問題中普遍使用的網絡

天然語言處理和監督機器學習(ML)
任務之一是 「文本分類」,它是監督機器學習任務的一個例子,由於包含文本文檔及其標籤的標記數據集用於訓練分類器。

文本分類的目標是自動將文本文檔分類爲一個或多個預約義類別。架構

文本分類的一些示例是:app

  • 從社交媒體中瞭解受衆情緒(😁😐😥)
  • 檢測垃圾郵件和非垃圾郵件
  • 自動標記客戶查詢
  • 將新聞文章分類爲預約義主題

文本分類是學術界和工業界很是活躍的研究領域。在這篇文章中,我將嘗試介紹一些不一樣的方法,並比較它們的性能,其中實現基於Keras機器學習

全部源代碼和實驗結果均可以在jatana_research 存儲庫中找到函數

端到端文本分類管道由如下組件組成:

  1. 培訓文本:它是咱們的監督學習模型可以學習和預測所需課程的輸入文本。
  2. 特徵向量:特徵向量是包含描述輸入數據特徵的信息的向量。
  3. 標籤:這些是咱們的模型預測的預約義類別/類
  4. ML Algo:這是咱們的模型可以處理文本分類的算法(在咱們的例子中:CNN,RNN,HAN)
  5. 預測模型:在歷史數據集上訓練的模型,能夠執行標籤預測。

分析咱們的數據:

咱們使用3種類型的數據集,其中包含各類類,以下表所示:

使用卷積神經網絡(CNN)的文本分類:

CNN是一類深度前饋人工神經網絡(節點之間的鏈接

造成循環)並使用多層感知器的變體,其設計須要最少的預處理。這些靈感來自動物視覺皮層。

我參考了Yoon Kim 論文和Denny Britz撰寫的這篇博客

CNN一般用於計算機視覺,但它們最近已應用於各類NLP任務,結果頗有但願 🙌

讓咱們簡要地看一下當咱們經過圖表在文本數據上使用CNN時會發生什麼。當檢測到特殊模式時,每一個卷積的結果都將觸發。經過改變內核的大小並鏈接它們的輸出,你能夠本身檢測多個大小的模式(2,3或5個相鄰的單詞).Patterns能夠是表達式(單詞ngrams?),如「我討厭」,「很是好「所以CNN能夠在句子中識別它們而無論它們的位置如何。

在本節中,我使用簡化的CNN來構建分類器。因此首先使用Beautiful Soup來刪除一些HTML標籤和一些不須要的字符。

def clean_str(string):
    string = re.sub(r「\\」,「」,string)     
    string = re.sub(r「\'」,「」,string) string = re.sub(r「\」 「,」,「string」 return string.strip()。lower() texts = []; labels = [] for i in range(df.message.shape [0]): text = BeautifulSoup(df.message [i ]) text.append(clean_str(str(text.get_text()。encode()))) for for in df ['class']: labels.append(i) 複製代碼

這裏我使用了Google Glove 6B vector 100d。其官方文件:

'''
GloVe是一種無監督學習算法,用於獲取單詞的向量表示。對來自語料庫的聚合全局詞 - 詞共現統計進行訓練,而且所獲得的表示展現詞向量空間的有趣線性子結構。
「」」

對於未知單詞,如下代碼將隨機化其向量。下面是一個很是簡單的卷積架構,使用了總共​​128個過濾器,大小爲5,最大池爲5和35,遵循此博客的示例。

sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
embedded_sequences = embedding_layer(sequence_input)
l_cov1= Conv1D(128, 5, activation='relu')(embedded_sequences)
l_pool1 = MaxPooling1D(5)(l_cov1)
l_cov2 = Conv1D(128, 5, activation='relu')(l_pool1)
l_pool2 = MaxPooling1D(5)(l_cov2)
l_cov3 = Conv1D(128, 5, activation='relu')(l_pool2)
l_pool3 = MaxPooling1D(35)(l_cov3)  # global max pooling
l_flat = Flatten()(l_pool3)
l_dense = Dense(128, activation='relu')(l_flat)
preds = Dense(len(macronum), activation='softmax')(l_dense)
複製代碼

這是CNN模型的架構。

使用遞歸神經網絡(RNN)進行文本分類:

迴歸神經網絡(RNN)是一類神經網絡,其中節點之間的鏈接造成沿着一序列的有向圖的。這容許它展現時間序列的動態時間行爲。

使用外部嵌入的知識能夠提升RNN的精確度,由於它集成了關於單詞的新信息(詞彙和語義),這些信息已經在一個很是大的數據集上訓練和提煉。預先訓練嵌入咱們將要使用的是GloVe

RNN可能看起來很嚇人😱。雖然它們很難理解,但它們很是有趣。它們封裝了一個很是漂亮的設計,克服了傳統神經網絡在處理序列數據時出現的缺點:文本,時間序列,視頻,DNA序列等。

RNN是一系列神經網絡塊,它們像鏈同樣彼此連接。每一個人都將消息傳遞給繼任者。若是你想深刻了解內部機制,我強烈推薦Colah的博客

使用Beautiful Soup也能夠完成相同的預處理。咱們將處理文本數據,這是一種序列類型。單詞的順序對意義很是重要。但願RNN可以處理這個問題並捕獲長期依賴關係。

要在文本數據上使用Keras,咱們首先必須對其進行預處理。爲此,咱們可使用Keras的Tokenizer類。該對象採用num_words參數做爲參數,這是基於字頻率進行標記化後保留的最大字數。

MAX_NB_WORDS = 20000
tokenizer = Tokenizer (num_words=MAX_NB_WORDS) tokenizer.fit_on_texts(texts)
複製代碼

一旦將標記化器安裝在數據上,咱們就可使用它將文本字符串轉換爲數字序列。這些數字表明字典中每一個單詞的位置(將其視爲映射)。

  • 在本節中,我將嘗試使用遞歸神經網絡和基於注意力的LSTM編碼器來解決該問題。
  • 經過使用LSTM編碼器,咱們打算在運行前饋網絡進行分類以前,對遞歸神經網絡的最後一個輸出中的文本的全部信息進行編碼。
  • 這與神經翻譯機器和序列學習序列很是類似。如下是段落和文檔的分層神經自動編碼器的圖。
  • 我在Keras中使用LSTM層來實現這一點。除了正向LSTM以外,這裏我使用了雙向LSTM並鏈接了LSTM輸出的最後一個輸出。
  • Keras提供了一個很是好的包裝器,稱爲雙向,這將使這種編碼工做絕不費力。您能夠在此處查看示例代碼
sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
embedded_sequences = embedding_layer(sequence_input)
l_lstm = Bidirectional(LSTM(100))(embedded_sequences)
preds = Dense(len(macronum), activation='softmax')(l_lstm)
model = Model(sequence_input, preds)
model.compile(loss='categorical_crossentropy',optimizer='rmsprop',  metrics=['acc'])
複製代碼

這是RNN模型的架構。

使用分層注意網絡(HAN)的文本分類:

我參考了這篇研究論文「 分層注意網絡文檔分類」。它能夠成爲使用HAN進行文檔分類的絕佳指南。使用Beautiful Soup也能夠進行相同的預處理。咱們將使用的預訓練嵌入是GloVe

  • 在這裏,我正在構建一個Hierarchical LSTM網絡。我必須將數據輸入構造爲3D而不是2D,如上面兩節所述。
  • 所以輸入張量將是[每批評論數,句子數,每一個句子中的單詞數]。
tokenizer = Tokenizer(nb_words=MAX_NB_WORDS)
tokenizer.fit_on_texts(texts)
data = np.zeros((len(texts), MAX_SENTS, MAX_SENT_LENGTH), dtype='int32')
for i, sentences in enumerate(reviews):
    for j, sent in enumerate(sentences):
        if j< MAX_SENTS:
            wordTokens = text_to_word_sequence(sent)
            k=0
            for _, word in enumerate(wordTokens):
                if(k<MAX_SENT_LENGTH and tokenizer.word_index[word]<MAX_NB_WORDS):
                    data[i,j,k] = tokenizer.word_index[word]
                    k=k+1
複製代碼

在此以後,咱們可使用Keras魔術函數TimeDistributed構建以下的Hierarchical輸入層。咱們也能夠參考這篇文章

embedding_layer=Embedding(len(word_index)+1,EMBEDDING_DIM,weights=[embedding_matrix],
input_length=MAX_SENT_LENGTH,trainable=True)
sentence_input = Input(shape=(MAX_SENT_LENGTH,), dtype='int32')
embedded_sequences = embedding_layer(sentence_input)
l_lstm = Bidirectional(LSTM(100))(embedded_sequences)
sentEncoder = Model(sentence_input, l_lstm)

review_input = Input(shape=(MAX_SENTS,MAX_SENT_LENGTH), dtype='int32')
review_encoder = TimeDistributed(sentEncoder)(review_input)
l_lstm_sent = Bidirectional(LSTM(100))(review_encoder)
preds = Dense(len(macronum), activation='softmax')(l_lstm_sent)
model = Model(review_input, preds)
複製代碼

這是HAN模型的架構。

結果

如下是準確度Loss和損失pl的圖表

觀察👇:

  • 基於上述圖表,CNN已經得到了良好的驗證準確性和高一致性,RNN和HAN也實現了高精度,但它們在全部數據集中並不一致。
  • 發現RNN是生產就緒場景中最糟糕的架構。
  • CNN模型在訓練時間方面優於其餘兩個模型(RNN和HAN),可是若是咱們有龐大的數據集,HAN能夠比CNN和RNN表現更好。
  • 對於訓練樣本較多的數據集1和數據集2,HAN已經達到最佳驗證準確度,而當訓練樣本很是低時,HAN沒有表現出那麼好(數據集3)。
  • 當訓練樣本較少時(數據集3),CNN已達到最佳驗證準確度。

績效改進:

爲了達到最佳表現😉,咱們能夠:

  1. 微調超參數:超參數是在訓練以前設置的變量,用於肯定網絡結構以及網絡的訓練方式。(例如:學習率,批量大小,時期數)。微調能夠經過如下方式完成:手動搜索,網格搜索,隨機搜索......
  2. 改進文本預處理:能夠根據數據集的須要更好地預處理輸入數據,例如刪除一些特殊符號,數字,停用詞等等...
  3. 使用Dropout Layer : Dropout是正則化技術,可避免過分擬合(提升驗證精度),從而提升泛化能力。

基礎設施設置

全部上述實驗均在具備Nvidia Tesla K80 GPU的 8核vCPU上進行

此外,全部實驗均在Rahul Kumar guidance 的指導下進行。

此外,我還要感謝Jatana.ai 爲我提供了一個很是好的基礎設施和全程支持😃。

感謝 Rahul Kumar

英文原文:Report on Text Classification using CNN, RNN & HAN

更多文章歡迎訪問: www.apexyun.com

公衆號:銀河系1號

聯繫郵箱:public@space-explore.com(未經贊成,請勿轉載)

相關文章
相關標籤/搜索