構建文本分類程序:NLP 教程

已發表: 2022-03-11

深度學習是一種技術,已成為機器學習工作流程的重要組成部分。 利用並行計算能力和支持工具的改進,曾經不切實際的複雜和深度神經網絡現在變得可行。

Tensorflow、Torch 和 Deeplearning4j 等功能強大且易於訪問的庫的出現,也為大型科技公司的學術界和研究部門以外的用戶打開了開發大門。 為了證明其日益普及,華為和蘋果等公司現在在其最新設備中包含專用的深度學習優化處理器,以支持深度學習應用程序。

深度學習已經在許多領域證明了它的力量。 最值得注意的是,谷歌的 AlphaGo 能夠在圍棋遊戲中擊敗人類玩家,該遊戲的複雜性令人難以置信,曾經被認為是計算機與人類玩家競爭的幾乎不可逾越的障礙。 索尼的 Flow Machines 項目開發了一種神經網絡,可以按照過去著名音樂家的風格創作音樂。 FaceID 是 Apple 開發的一項安全功能,它使用深度學習來識別用戶的面部並跟踪用戶面部隨時間的變化。

在本文中,我們將深度學習應用到我最喜歡的兩個主題:自然語言處理和葡萄酒。 我們將建立一個模型來理解專家的自然語言葡萄酒評論,並推斷他們正在評論的葡萄酒的種類。

NLP 的深度學習

深度學習已廣泛用於自然語言處理(NLP),因為它非常適合學習句子的複雜底層結構和各種單詞的語義接近度。 例如,當前的情感分析技術使用深度學習來捕捉難以建模的語言概念,例如否定和混合情感。

與其他 NLP 算法相比,深度學習有幾個優勢:

  1. 靈活的模型:深度學習模型比其他 ML 模型靈活得多​​。 我們可以輕鬆地嘗試不同的結構,根據需要添加和刪除層。 深度學習模型還允許構建具有靈活輸出的模型。 靈活性是開發非常適合理解複雜語言結構的模型的關鍵。 它對於開發 NLP 應用程序(例如翻譯、聊天機器人和文本轉語音應用程序)也至關重要。
  2. 需要更少的領域知識:雖然開發一個好的深度學習模型當然需要一些領域知識和直覺,但深度學習算法自身學習特徵層次結構的能力意味著開發人員不需要深入了解開發深度學習 NLP 算法的問題空間。 對於像自然語言這樣複雜的問題空間,這是一個非常受歡迎的優勢。
  3. 更容易進行持續學習:隨著新數據的到來,深度學習算法很容易訓練。一些機器學習算法需要通過模型發送整個數據集以進行更新,這對於實時的大型數據集來說是一個問題。

今天的問題

今天,我們將構建一個深度學習算法,根據評論文本來確定被評論的葡萄酒的品種。 我們將在 https://www.kaggle.com/zynicide/wine-reviews 使用由 Kaggle 用戶zackthoutt提供的葡萄酒雜誌數據集。

從概念上講,問題是,我們可以像…

香氣包括熱帶水果、掃帚、硫磺和乾香草。 口感並不過分錶現力,提供未成熟的蘋果、柑橘和乾鼠尾草以及清爽的酸度。

......並認識到它是關於白色混合物的? 一些葡萄酒愛好者可能會識別出白葡萄酒的明顯跡象,例如蘋果、柑橘和明顯的酸度,但我們可以訓練我們的神經網絡來識別這些信號嗎? 此外,我們能否訓練我們的神經網絡來識別白色混合評論和灰比諾評論之間的細微差別?

類似的算法

我們今天處理的問題本質上是一個 NLP 分類問題。 有幾種 NLP 分類算法已應用於 NLP 中的各種問題。 例如,樸素貝葉斯已用於各種垃圾郵件檢測算法,支持向量機 (SVM) 已用於對醫療機構的進度說明等文本進行分類。 實現這些算法的簡單版本作為我們深度學習模型的基線會很有趣。

樸素貝葉斯

用於 NLP 的樸素貝葉斯的一種流行實現涉及使用 TF-IDF 預處理文本,然後在預處理的輸出上運行多項樸素貝葉斯。 這允許算法在文檔中最突出的單詞上運行。 我們可以如下實現樸素貝葉斯:

 import numpy as np from sklearn.naive_bayes import MultinomialNB from sklearn.feature_extraction.text import CountVectorizer import pandas as pd from collections import Counter from sklearn.model_selection import train_test_split from sklearn.feature_extraction.text import TfidfTransformer df = pd.read_csv('data/wine_data.csv') counter = Counter(df['variety'].tolist()) top_10_varieties = {i[0]: idx for idx, i in enumerate(counter.most_common(10))} df = df[df['variety'].map(lambda x: x in top_10_varieties)] description_list = df['description'].tolist() varietal_list = [top_10_varieties[i] for i in df['variety'].tolist()] varietal_list = np.array(varietal_list) count_vect = CountVectorizer() x_train_counts = count_vect.fit_transform(description_list) tfidf_transformer = TfidfTransformer() x_train_tfidf = tfidf_transformer.fit_transform(x_train_counts) train_x, test_x, train_y, test_y = train_test_split(x_train_tfidf, varietal_list, test_size=0.3) clf = MultinomialNB().fit(train_x, train_y) y_score = clf.predict(test_x) n_right = 0 for i in range(len(y_score)): if y_score[i] == test_y[i]: n_right += 1 print("Accuracy: %.2f%%" % ((n_right/float(len(test_y)) * 100)))

運行上面的代碼,你應該會看到類似下面的內容: 73.56%

考慮到我們正在查看 10 個類,這是一個相當不錯的結果。

我們也可以使用支持向量機,看看它會怎麼做。 要查看它的執行情況,只需將分類器定義替換為

 clf = SVC(kernel='linear').fit(train_x, train_y)

運行它,您應該會看到以下輸出:

準確度: 80.66%

也不會太破舊。

讓我們看看我們是否可以建立一個可以超越或至少匹配這些結果的深度學習模型。 如果我們能做到這一點,這將是一個很好的跡象,表明我們的深度學習模型至少可以有效地複制由領域專業知識提供的流行機器學習模型的結果。

構建模型

今天,我們將使用 Keras 和 Tensorflow 來構建我們的模型。 Keras 是一個 Python 庫,與 Tensorflow API 的相對低級接口相比,它使構建深度學習模型變得非常容易。 除了密集層之外,我們還將使用嵌入層和卷積層來學習單詞的底層語義信息和數據中潛在的結構模式。

數據清洗

首先,我們必須以我們的神經網絡可以輕鬆處理和理解的方式重組數據。 我們可以通過用唯一標識數字替換單詞來做到這一點。 結合嵌入向量,我們能夠以靈活且語義敏感的方式表示單詞。

在實踐中,我們希望對這種預處理更聰明一點。 將重點放在常用詞上,同時過濾掉最常用的詞(例如,the、this、a)是有意義的。

我們可以使用 Defaultdict 和 NLTK 來實現這個功能。 將以下代碼寫入單獨的 Python 模塊。 我把它放在lib/get_top_x_words.py中。

 from nltk import word_tokenize from collections import defaultdict def count_top_x_words(corpus, top_x, skip_top_n): count = defaultdict(lambda: 0) for c in corpus: for w in word_tokenize(c): count[w] += 1 count_tuples = sorted([(w, c) for w, c in count.items()], key=lambda x: x[1], reverse=True) return [i[0] for i in count_tuples[skip_top_n: skip_top_n + top_x]] def replace_top_x_words_with_vectors(corpus, top_x): topx_dict = {top_x[i]: i for i in range(len(top_x))} return [ [topx_dict[w] for w in word_tokenize(s) if w in topx_dict] for s in corpus ], topx_dict def filter_to_top_x(corpus, n_top, skip_n_top=0): top_x = count_top_x_words(corpus, n_top, skip_n_top) return replace_top_x_words_with_vectors(corpus, top_x)

現在我們準備好構建模型了。 我們想要一個嵌入層、一個卷積層和一個密集層來利用所有對我們的應用程序有幫助的深度學習特徵。 使用 Keras,我們可以非常簡單地構建模型:

 from keras.models import Sequential from keras.layers import Dense, Conv1D, Flatten from keras.layers.embeddings import Embedding from keras.preprocessing import sequence from keras.utils import to_categorical import pandas as pd from collections import Counter from sklearn.model_selection import train_test_split from lib.get_top_xwords import filter_to_top_x df = pd.read_csv('data/wine_data.csv') counter = Counter(df['variety'].tolist()) top_10_varieties = {i[0]: idx for idx, i in enumerate(counter.most_common(10))} df = df[df['variety'].map(lambda x: x in top_10_varieties)] description_list = df['description'].tolist() mapped_list, word_list = filter_to_top_x(description_list, 2500, 10) varietal_list_o = [top_10_varieties[i] for i in df['variety'].tolist()] varietal_list = to_categorical(varietal_list_o) max_review_length = 150 mapped_list = sequence.pad_sequences(mapped_list, maxlen=max_review_length) train_x, test_x, train_y, test_y = train_test_split(mapped_list, varietal_list, test_size=0.3) max_review_length = 150 embedding_vector_length = 64 model = Sequential() model.add(Embedding(2500, embedding_vector_length, input_length=max_review_length)) model.add(Conv1D(50, 5)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(max(varietal_list_o) + 1, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(train_x, train_y, epochs=3, batch_size=64) y_score = model.predict(test_x) y_score = [[1 if i == max(sc) else 0 for i in sc] for sc in y_score] n_right = 0 for i in range(len(y_score)): if all(y_score[i][j] == test_y[i][j] for j in range(len(y_score[i]))): n_right += 1 print("Accuracy: %.2f%%" % ((n_right/float(len(test_y)) * 100)))

運行代碼,您應該會看到以下輸出。

準確度: 77.20%

回想一下,樸素貝葉斯和 SVC 的準確率分別為 73.56% 和 80.66%。 因此,我們的神經網絡非常適合一些更常見的文本分類方法。

結論

今天,我們介紹了構建分類深度學習模型來分析葡萄酒評論。

我們發現我們能夠構建一個能夠與其他一些機器學習算法競爭並優於其他一些機器學習算法的模型。 我們希望您受到啟發,使用這些信息來構建分析更複雜數據集並生成更複雜輸出的應用程序!

注意:你可以在 GitHub 上找到我用於本文的代碼。


進一步閱讀 Toptal 工程博客:

  • 更深層次的含義:Python 中的主題建模
  • 如何構建電子郵件情緒分析機器人:NLP 教程