想象一下,走进一家书店想要购买一本关于世界经济的书籍,却发现书店没有将书籍按照类型分区,所有书籍杂乱无章地堆放在一起。这时,意识到将书店按照书籍类型进行分区是多么重要。主题建模(Topic Modelling)就像是根据书籍内容对书店进行分区一样,它指的是在文本集合中发现主题,并根据识别出的主题对文档进行标注的过程。
当需要对大量文档集合进行分割、理解和总结时,主题建模就显得非常有用。主题建模使用LDA(Latent Dirichlet Allocation,潜在狄利克雷分配)算法实现,这是一种生成概率模型,假设每篇文档由不同比例的主题组成。
LDA算法的工作原理如下:
最后一步重复多次,直到达到稳态,即主题分配不再变化。然后根据这些主题分配确定每篇文档的主题比例。
下面是一个LDA的示例。假设有以下4篇文档作为语料库,并希望对这些文档进行主题建模。
Document 1: 在YouTube上观看了很多视频。
Document 2: YouTube视频非常有信息量。
Document 3: 阅读技术博客让更容易理解事物。
Document 4: 更喜欢博客而不是YouTube视频。
LDA建模帮助在上述语料库中发现主题,并为每篇文档分配主题混合。例如,模型可能会输出以下内容:
Topic 1: 40%视频, 60%YouTube
Topic 2: 95%博客, 5%YouTube
Document 1和2将100%属于主题1。Document 3将100%属于主题2。Document 4将80%属于主题2,20%属于主题1。
这些文档的主题分配是通过在前一节讨论的步骤由LDA建模完成的。现在,让将LDA应用于一些文本数据,并在Python中分析实际输出。
将使用Kaggle上的‘Amazon Fine Food Reviews’数据集()来说明如何在Python中使用LDA进行主题建模。
首先,导入Pandas库来读取CSV文件并保存到数据框中。
import pandas as pd
import nltk
from nltk.corpus import stopwords # 停用词
from nltk.stem import WordNetLemmatizer # 词形还原
from nltk.tokenize import word_tokenize
# from sklearn.feature_extraction.text import TfidfVectorizer
对‘Text’列进行主题建模。
rev = pd.read_csv(r"Reviews.csv")
print(rev.head())
导入必要的库:
import nltk
from nltk.corpus import stopwords # 停用词
from nltk.stem import WordNetLemmatizer # 词形还原
from sklearn.feature_extraction.text import TfidfVectorizer
预处理文本:
stop_words=set(nltk.corpus.stopwords.words('english'))
def clean_text(headline):
le=WordNetLemmatizer()
word_tokens=word_tokenize(headline)
tokens=[le.lemmatize(w) for w in word_tokens if w not in stop_words and len(w)>3]
cleaned_text=" ".join(tokens)
return cleaned_text
rev['cleaned_text']=rev['Text'].apply(clean_text)
对文本列进行TFIDF向量化:
vect =TfidfVectorizer(stop_words=stop_words,max_features=1000)
vect_text=vect.fit_transform(rev['cleaned_text'])
对向量化的文本进行LDA:
from sklearn.decomposition import LatentDirichletAllocation
lda_model=LatentDirichletAllocation(n_components=10,
learning_method='online',random_state=42,max_iter=1)
lda_top=lda_model.fit_transform(vect_text)
检查结果:
print("Document 0: ")
for i,topic in enumerate(lda_top[0]):
print("Topic ",i,": ",topic*100,"%")
vocab = vect.get_feature_names()
for i, comp in enumerate(lda_model.components_):
vocab_comp = zip(vocab, comp)
sorted_words = sorted(vocab_comp, key= lambda x:x[1], reverse=True)[:10]
print("Topic "+str(i)+": ")
for t in sorted_words:
print(t[0],end=" ")
print("n")