Python中的LDA算法

454 阅读6分钟

各位读者大家好,在这篇文章中,我们将尝试了解什么是LDA算法,它是如何工作的,以及它是如何在python中实现的。Latent Dirichlet Allocation是一种主要属于自然语言处理(NLP)领域的算法。

它被用于主题建模。主题建模是一种机器学习技术,对文本数据进行分析,并在文档集合中找到一个抽象的类似主题。

什么是LDA?

LDA是专门为文本数据设计的主题建模算法之一。这种技术将每个文档看作是算法产生的一些主题的混合物,作为最终结果。这些主题是数据集中所有文档中出现的单词的概率分布。

预处理数据的结果将提供一个关键词或标记数组,LDA算法将把这些预处理数据作为输入,并试图根据这些关键词的概率分布找到隐藏/潜在的主题。最初,该算法将把文档中的每个词分配给 "*n "*个主题中的一个随机主题。

例如,考虑以下文本数据

  • 文本1:对IPL感到兴奋,今年让我们回到板球场,享受比赛。
  • 文本2:今年8月,我们可能会面临第四波的科维德!
  • 文本3:尽快接种疫苗,现在是时候了。
  • 文本4:联邦预算今年增加了体育的配额,这都要归功于今年的奥运会冠军。

理论上,让我们考虑两个主题体育和Covid供算法工作。该算法可能会将第一个写着 "IPL "的词分配给主题2 Covid。我们知道这个分配是错误的,但是算法会在未来的迭代中根据两个因素,即话题在文档中出现的频率和该词在话题中出现的频率,尝试纠正这个问题。由于文本1中与Covid相关的词汇不多,而且 "IPL "一词在话题2 Covid中不会出现很多次,因此算法可能会将 "IPL "一词分配到新的话题,即话题1(体育)。通过多次这样的迭代,该算法将实现话题识别和单词在各话题中分布的稳定性。最后,每个文档都可以被表示为一个确定的主题的混合物。

LDA是如何工作的?

在LDA中进行以下步骤,为每个文档分配主题:

  1. 对于每个文档,随机地将每个词初始化为K个主题中的一个,其中K是预先定义的主题的数量。

2)对于每个文档d。

对于文档中的每个词w,计算:

  • P(话题t|文档d)。文档d中被分配到主题t的词的比例
  • P(单词w|话题t)。在所有文档中,来自w的词被分配到话题t的比例
  1. 考虑到所有其他词和它们的主题分配,以p(t'|d)*p(w|t')的概率将主题T'重新分配给词w。

最后一步重复多次,直到我们达到一个稳定状态,即话题分配不再发生变化。然后根据这些主题分配来确定每个文档的主题比例。

LDA的说明性例子

假设我们有以下4个文档作为语料库,我们希望对这些文档进行主题建模。

  • 文档1:我们在YouTube上观看了很多视频。
  • 文档2:YouTube的视频信息量很大。
  • 文档3:阅读技术博客使我更容易理解事物。
  • 文档4:相比YouTube视频,我更喜欢博客。

LDA模型帮助我们在上述语料库中发现主题,并为每个文件分配主题混合物。作为一个例子,该模型可能会输出如下的内容。

主题1:40%的视频,60%的YouTube

主题2:95%的博客,5%的YouTube

文件1和2将100%属于主题1。文件3将100%属于主题2。文件4将80%属于主题2,20%属于主题1。

如何在Python中实现LDA?

以下是实现LDA算法的步骤:

  1. 收集数据并将其作为输入
  2. 对数据进行预处理(去除不必要的数据)
  3. 为LDA分析修改数据
  4. 建立和训练LDA模型
  5. 分析LDA模型的结果

在这里,我们从Twitter收集了输入数据,并将其转换成CSV文件,因为社交媒体上的数据是多种多样的,我们可以建立一个有效的模型。

导入LDA所需的库

import numpy as np
import pandas as pd 
import re

import gensim
from gensim import corpora, models, similarities
from gensim.parsing.preprocessing import STOPWORDS
from nltk.corpus import stopwords

清理数据

归一化白色空间

def normalize_whitespace(tweet):
    tweet = re.sub('[\s]+', ' ', tweet)
    return tweet

text = "         We        are the students    of    Science. "
print("Text Before: ",text)
text = normalize_whitespace(text)
print("Text After: ",text)

OUTPUT:

 Text Before:    We        are the students    of    Science. 

文本之后。我们是科学的学生。

去除停顿词

import nltk
nltk.download('stopwords')
import gensim
from gensim.parsing.preprocessing import STOPWORDS
from nltk.corpus import stopwords

stop_words = stopwords.words('english')


def remove_stopwords(text):
  final_s=""
  text_arr= text.split(" ")                              #splits sentence when space occurs
  print(text_arr)
  for word in text_arr:                             
    if word not in stop_words:                     # if word is not in stopword then append(join) it to string 
      final_s= final_s + word + " "

  return final_s 

词根化和标记化

import nltk
# nltk.download('wordnet')
from nltk.stem import WordNetLemmatizer, SnowballStemmer, PorterStemmer

stemmer = PorterStemmer()

def tokenize_stemming(text):
    text = re.sub(r'[^\w\s]','',text)
    #replace multiple spaces with one space
    text = re.sub(r'[\s]+',' ',text)
    #transfer text to lowercase
    text = text.lower() 
    # tokenize text
    tokens = re.split(" ", text)

    # Remove stop words 
    result = []
    for token in tokens :
        if token not in stop_words and len(token) > 1:
            result.append(stemmer.stem(token))

    return result

还可以阅读。使用NLTK在Python中进行标记化

术语频率(TF-IDF)

它是术语频率-逆向文档频率的简称,是一种数字统计,旨在反映一个词在一个集合或语料库中对一个文档的重要性。它经常被用作一个加权因素。

corpus_doc2bow_vectors = [dictionary.doc2bow(tok_doc) for tok_doc in tokens]
print("# Term Frequency : ")
corpus_doc2bow_vectors[:5]

tfidf_model = models.TfidfModel(corpus_doc2bow_vectors, id2word=dictionary, normalize=False)
corpus_tfidf_vectors = tfidf_model[corpus_doc2bow_vectors]

print("\n# TF_IDF: ")
print(corpus_tfidf_vectors[5])

使用语料袋运行LDA

lda_model = gensim.models.LdaMulticore(corpus_doc2bow_vectors, num_topics=10, id2word=dictionary, passes=2, workers=2)

使用TF-IDF运行LDA

lda_model_tfidf = gensim.models.LdaMulticore(corpus_tfidf_vectors, num_topics=10, id2word=dictionary, passes=2, workers=4)
for idx, topic in lda_model_tfidf.print_topics(-1):
    print('Topic: {} Word: {}'.format(idx, topic))

主题的分类

通过使用LDA词袋模型对样本文件进行分类来进行性能评估 我们将检查我们的测试文件会被分类到哪里。

for index, score in sorted(lda_model[corpus_doc2bow_vectors[1]], key=lambda tup: -1*tup[1]):
    print("\nScore: {}\t \nTopic: {}".format(score, lda_model.print_topic(index, 10)))

通过使用LDA TF-IDF模型对样本文件进行分类的性能评估。

for index, score in sorted(lda_model_tfidf[corpus_doc2bow_vectors[1]], key=lambda tup: -1*tup[1]):
    print("\nScore: {}\t \nTopic: {}".format(score, lda_model_tfidf.print_topic(index, 10)))

总结

在这篇文章中,我们试图了解自然语言处理领域中最常用的算法。LDA是主题建模的基础--一种统计建模和数据挖掘的类型。