更深層次的含義:Python 中的主題建模

已發表: 2022-03-11

計算機和為其提供動力的處理器是為處理數字而設計的。 相比之下,電子郵件和社交媒體帖子的日常語言結構鬆散,不適合計算。

這就是自然語言處理 (NLP) 的用武之地。NLP 是計算機科學的一個分支,它通過應用計算技術(即人工智能)來分析自然語言和語音,與語言學重疊。 主題建模側重於了解給定文本的主題。 主題建模使開發人員可以實現有用的功能,例如檢測社交媒體上的突發新聞、推薦個性化消息、檢測虛假用戶和表徵信息流。

開發人員如何哄騙專注於計算的計算機在這些複雜級別上理解人類通信?

一袋詞

要回答這個問題,我們需要能夠以數學方式描述文本。 我們將從最簡單的方法開始我們的主題建模 Python 教程:詞袋。

此方法將文本表示為一組單詞。 例如,句子This is an example可以描述為一組單詞,使用這些單詞出現的頻率:

 {"an": 1, "example": 1, "is": 1, "this": 1}

請注意此方法如何忽略詞序。 舉這些例子:

  • “我喜歡星球大戰,但我不喜歡哈利波特。”
  • “我喜歡哈利波特,但我不喜歡星球大戰。”

這些情感用相同的詞來表示,但它們具有相反的含義。 然而,為了分析文本的主題,這些差異並不重要。 在這兩種情況下,我們都在談論哈利波特和星球大戰的口味,無論這些口味是什麼。 因此,詞序無關緊要。

當我們有多個文本並試圖理解它們之間的差異時,我們需要為我們的整個語料庫單獨考慮每個文本的數學表示。 為此,我們可以使用矩陣,其中每一列代表一個單詞或術語,每一行代表一個文本。 語料庫的可能表示包括在每個單元格中記錄給定單詞(列)在特定文本(行)中使用的頻率。

在我們的示例中,語料庫由兩個句子(我們的矩陣行)組成:

 ["I like Harry Potter", "I like Star Wars"]

我們按照遇到的順序列出了這個語料庫中的單詞: I , like , Harry , Potter , Star , Wars 。 這些對應於我們的矩陣列。

矩陣中的值表示給定單詞在每個短語中使用的次數:

 [[1,1,1,1,0,0], [1,1,0,0,1,1]] 

圖像左側顯示兩行文字:我喜歡哈利波特和我喜歡星球大戰。然後這段文字在中間變成一袋單詞,每個單詞後面跟著該單詞的使用次數:“我喜歡哈利波特”變成“{I: 1, like: 1, Harry: 1, Potter : 1, Star: 0, Wars: 0}”和“我喜歡星球大戰”變成“{I: 1, like: 1, Harry: 0, Potter: 0, Star: 1, Wars: 1}” 向右,然後這些數字以矩陣表示形式排列:前者變為“1 1 1 1 0 0”行,後者變為“1 1 0 0 1 1”。
文本轉換為矩陣表示

請注意,矩陣的大小是通過將文本數量乘以至少一個文本中出現的不同單詞的數量來確定的。 後者通常不必要地大並且可以減小。 例如,一個矩陣可能包含兩列共軛動詞,例如“play”和“played”,不管它們的含義是否相似。

但是描述新概念的欄目可能會丟失。 例如,“古典”和“音樂”各有不同的含義,但當它們組合在一起時——“古典音樂”——它們又有不同的含義。

由於這些問題,有必要對文本進行預處理以獲得良好的結果。

預處理和主題聚類模型

為了獲得最佳結果,有必要使用多種預處理技術。 以下是一些最常用的:

  1. 小寫字母。 使所有單詞小寫。 使所有單詞小寫。 無論單詞在句子中的位置如何,單詞的含義都不會改變。
  2. n-克。 將一行中的所有n 個單詞組視為新術語,稱為n-grams 。 這樣,諸如“白宮”之類的案例將被考慮並添加到詞彙表中。
  3. 詞幹。 識別單詞的前綴和後綴,將它們與詞根隔離開來。 這樣,“play”、“played”或“player”之類的詞就可以用“play”這個詞來表示了。 詞幹提取有助於減少詞彙表中的單詞數量,同時保留其含義,但它會大大減慢預處理,因為它必須應用於語料庫中的每個單詞。
  4. 停止的話。 不要考慮缺乏意義或實用性的詞組。 這些包括冠詞和介詞,但也可能包括對我們的特定案例研究無用的詞,例如某些常用動詞。
  5. 詞頻-逆文檔頻率(tf-idf)。 使用 tf–idf 的係數,而不是注意矩陣每個單元格中每個單詞的頻率。 它由兩個數字相乘:
    • tf——文本中給定術語或單詞的頻率,以及
    • idf——文檔總數除以包含該給定術語的文檔數的對數。

    tf-idf 衡量一個詞在語料庫中的使用頻率。 為了能夠將單詞細分為組,重要的是不僅要了解哪些單詞出現在每個文本中,還要了解哪些單詞在一個文本中經常出現,而在其他文本中根本不出現。

下圖顯示了這些預處理技術的一些簡單示例,其中修改了語料庫的原始文本以生成相關且可管理的單詞列表。

“小寫字母”技術轉換了句子“The White House”。成一個詞表:“the”、“white”、“house”。 “n-gram”技術將其轉換為更長的列表:“the”、“white”、“house”、“the white”、“white house”。 “詞幹”技術轉換了“足球運動員打得很好”這句話。進入這個列表:“the”、“football”、“play”、“a”、“good”、“game”。 “停用詞”技術將其轉換為更短的列表:“football”、“play”、“good”、“game”。
文本預處理技術示例

現在我們將演示如何在 Python 中應用其中一些技術。 一旦我們以數學方式表示了我們的語料庫,我們需要通過應用無監督機器學習算法來識別正在討論的主題。 在這種情況下,“無監督”意味著該算法沒有任何預定義的主題標籤,如“科幻小說”,可應用於其輸出。

為了對我們的語料庫進行聚類,我們可以從多種算法中進行選擇,包括非負矩陣分解 (NMF)、稀疏主成分分析 (sparse PCA) 和潛在狄利克雷分配 (LDA)。 我們將重點關注 LDA,因為它在社交媒體、醫學、政治學和軟件工程方面取得了良好的效果,因此被科學界廣泛使用。

LDA 是一種無監督主題分解模型:它根據文本包含的單詞和單詞屬於某個主題的概率對文本進行分組。 LDA算法輸出主題詞分佈。 有了這些信息,我們可以根據最有可能與之相關的詞來定義主要主題。 一旦我們確定了主要主題及其相關詞,我們就可以知道哪個或哪些主題適用於每個文本。

考慮以下由五個短句組成的語料庫(均取自《紐約時報》的頭條新聞):

 corpus = [ "Rafael Nadal Joins Roger Federer in Missing US Open", "Rafael Nadal Is Out of the Australian Open", "Biden Announces Virus Measures", "Biden's Virus Plans Meet Reality", "Where Biden's Virus Plan Stands"]

該算法應該清楚地識別出一個與政治和冠狀病毒有關的話題,以及第二個與納達爾和網球有關的話題。

在 Python 中應用策略

為了檢測主題,我們必須導入必要的庫。 Python 有一些用於 NLP 和機器學習的有用庫,包括 NLTK 和 Scikit-learn (sklearn)。

 from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer from sklearn.decomposition import LatentDirichletAllocation as LDA from nltk.corpus import stopwords

使用CountVectorizer() ,我們使用CountVectorizer() () 生成表示每個文本單詞頻率的矩陣。 請注意,如果您包含參數,例如stop_words以包含停用詞, ngram_range包含n -gram,或lowercase=True將所有字符轉換為小寫,則 CountVectorizer 允許進行預處理。

 count_vect = CountVectorizer(stop_words=stopwords.words('english'), lowercase=True) x_counts = count_vect.fit_transform(corpus) x_counts.todense() matrix([[0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0], [0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0], [1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1]], dtype=int64)

要定義我們語料庫的詞彙表,我們可以簡單地使用屬性.get_feature_names()

 count_vect.get_feature_names() ['announces', 'australian', 'biden', 'federer', 'joins', 'measures', 'meet', 'missing', 'nadal', 'open', 'plan', 'plans', 'rafael', 'reality', 'roger', 'stands', 'virus']

然後,我們使用 sklearn 函數執行 tf-idf 計算:

 tfidf_transformer = TfidfTransformer() x_tfidf = tfidf_transformer.fit_transform(x_counts)

為了執行 LDA 分解,我們必須定義主題的數量。 在這個簡單的例子中,我們知道有兩個主題或“維度”。 但在一般情況下,這是一個需要調整的超參數,可以使用隨機搜索或網格搜索等算法來完成:

 dimension = 2 lda = LDA(n_components = dimension) lda_array = lda.fit_transform(x_tfidf) lda_array array([[0.8516198 , 0.1483802 ], [0.82359501, 0.17640499], [0.18072751, 0.81927249], [0.1695452 , 0.8304548 ], [0.18072805, 0.81927195]])

LDA 是一種概率方法。 在這裡,我們可以看到五個標題中的每一個屬於兩個主題的概率。 我們可以看到,前兩個文本屬於第一個主題的概率更高,接下來的三個文本屬於第二個主題的概率更高,正如預期的那樣。

最後,如果我們想了解這兩個主題是關於什麼的,我們可以看到每個主題中最重要的詞:

 components = [lda.components_[i] for i in range(len(lda.components_))] features = count_vect.get_feature_names() important_words = [sorted(features, key = lambda x: components[j][features.index(x)], reverse = True)[:3] for j in range(len(components))] important_words [['open', 'nadal', 'rafael'], ['virus', 'biden', 'measures']]

正如預期的那樣,LDA 正確地將與網球錦標賽和納達爾相關的詞分配到第一個主題,將與拜登和病毒相關的詞正確分配到第二個主題。

大規模分析和實際用例

本文對主題建模進行了大規模分析; 我研究了 2016 年美國總統大選期間的主要新聞話題,並觀察了一些大眾媒體——比如紐約時報和福克斯新聞——在他們的報導中包含的話題,比如腐敗和移民。 在本文中,我還分析了大眾媒體內容與選舉結果之間的相關性和因果關係。

主題建模在學術界之外也被廣泛用於發現大量文本中隱藏的主題模式。 例如,它可以用於推薦系統或確定客戶/用戶在調查、反饋表或社交媒體上談論的內容。

Toptal 工程博客對 Juan Manuel Ortiz de Zarate 對本文中提供的代碼示例的審閱表示感謝。

主題建模推薦讀物

Twitter 中改進的主題建模
Albanese、Federico 和 Esteban Feuerstein。 “通過社區池改進 Twitter 中的主題建模。” (2021 年 12 月 20 日):arXiv:2201.00690 [cs.IR]

為公共衛生分析 Twitter
保羅、邁克爾和馬克·德雷澤。 “你就是你的推文:分析 Twitter 以促進公共衛生。” 2021 年 8 月 3 日。

在 Twitter 上對政治傾向進行分類
科恩、拉維夫和德里克·魯斯。 “在 Twitter 上對政治傾向進行分類:這並不容易!” 2021 年 8 月 3 日。

使用關係主題模型捕獲耦合
蓋瑟斯、馬爾科姆和丹尼斯·波希瓦尼克。 “使用關係主題模型捕獲面向對象軟件系統中類之間的耦合。” 2010 年 10 月 25 日。