介紹
你好,世界!!我最近加入Jatana.ai 擔任NLP研究員(實習生and),並被要求使用深度學習模型研究文字分類用例。
在本文中,我將分享我的經驗和學習,同時嘗試各種神經網路架構。
我將介紹3種主要演算法,例如:
- 卷積神經網路(CNN)
- 遞迴神經網路(RNN)
- 分層注意網路(HAN)
對具有丹麥語,義大利語,德語,英語和土耳其語的資料集進行文字分類。
我們來吧。✅
關於自然語言處理(NLP)
在不同業務問題中廣泛使用的
文字分類的目標是自動將文字文件分類為一個或多個預定義類別。
文字分類的一些示例是:
- 從社交媒體中瞭解受眾情緒(???)
- 檢測垃圾郵件和非垃圾郵件
- 自動標記客戶查詢
- 將新聞文章分類為預定義主題
文字分類是學術界和工業界非常活躍的研究領域。在這篇文章中,我將嘗試介紹一些不同的方法,並比較它們的效能,其中實現基於Keras。
所有原始碼和實驗結果都可以在jatana_research 儲存庫中找到。
端到端文字分類管道由以下元件組成:
- 培訓文字:它是我們的監督學習模型能夠學習和預測所需課程的輸入文字。
- 特徵向量:特徵向量是包含描述輸入資料特徵的資訊的向量。
- 標籤:這些是我們的模型預測的預定義類別/類
- ML Algo:這是我們的模型能夠處理文字分類的演算法(在我們的例子中:CNN,RNN,HAN)
- 預測模型:在歷史資料集上訓練的模型,可以執行標籤預測。
分析我們的資料:
我們使用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。其官方檔案:
對於未知單詞,以下程式碼將隨機化其向量。下面是一個非常簡單的卷積架構,使用了總共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已達到最佳驗證準確度。
績效改進:
為了達到最佳表現?,我們可以:
- 微調超引數:超引數是在訓練之前設定的變數,用於確定網路結構以及網路的訓練方式。(例如:學習率,批量大小,時期數)。微調可以通過以下方式完成:手動搜尋,網格搜尋,隨機搜尋......
- 改進文字預處理:可以根據資料集的需要更好地預處理輸入資料,例如刪除一些特殊符號,數字,停用詞等等...
- 使用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
(未經同意,請勿轉載)