正在学习人工智能自然语言处理,学校布置的作业分享出来


文章目录

  • 1. 原理
  • 2. 代码实现
  • 2.1.导入的包
  • 2.2.分词去停用词
  • 2.3.Tfidf
  • 2.4.计算困惑度
  • 2.5.LDA模型构建
  • 2.6.主题与分词
  • 2.6.1.权重值
  • 2.6.2.每个主题前25个词
  • 3.可视化


1. 原理

(参考相关博客与教材)

隐含狄利克雷分布(Latent Dirichlet Allocation,LDA),是一种主题模型(topic model),典型的词袋模型,即它认为一篇文档是由一组词构成的一个集合,词与词之间没有顺序以及先后的关系。一篇文档可以包含多个主题,文档中每一个词都由其中的一个主题生成。它可以将文档集中每篇文档的主题按照概率分布的形式给出,对文章进行主题归纳,属于无监督学习。

需要区分的是,另外一种经典的降维方法线性判别分析(Linear Discriminant Analysis, 简称也为LDA)。此LDA在模式识别领域(比如人脸识别,舰艇识别等图形图像识别领域)中有非常广泛的应用

LDA在训练时不需要手工标注的训练集,需要的仅仅是文档集以及指定主题的数量k即可。此外LDA的另一个优点则是,对于每一个主题均可找出一些词语来描述它。选择模型中topic的数量——人为设置参数,之后输入的每篇文章都给一个topic的概率 每个topic再给其下单词概率,topic的具体实现由自己来定。

LDA 假设文档的生成过程如下:

lda模型可视化代码 lda 可视化_nlp

(1)对每个主题:

生成“主题-词项”分布参数:

lda模型可视化代码 lda 可视化_lda模型可视化代码_02

;(2)对每个文档:生成“文档-主题”分布参数:

lda模型可视化代码 lda 可视化_lda模型可视化代码_03


;

(3)对当前文档的每个位置。

(a)生成当前位置的所属主题:

lda模型可视化代码 lda 可视化_lda模型可视化代码_04


;

(b)根据当前位置的主题,以及“主题-词项”分布参数,生成当前位置对应的词项:

lda模型可视化代码 lda 可视化_人工智能_05

2. 代码实现

2.1.导入的包

from matplotlib import pyplot as plt
from sklearn.feature_extraction.text import TfidfTransformer,CountVectorizer
import pandas as pd
import jieba
from sklearn.decomposition import LatentDirichletAllocation

2.2.分词去停用词

with open('train.csv','r',encoding='utf-8') as f:
    data = pd.read_csv(f)
# print(data.info())
print(data.content.head())#content列的前5行
with open('中文stopwords.txt','r',encoding='utf-8') as f:
    stopwords=[x.strip() for x in f.readlines()]
# print(stopwords[:5])

def cut_stop(content):#分词和去停用词
    listx=[]
    for row in content:
        row=row.replace(" ","")
        crow=jieba.lcut(row)
        # print(jieba.lcut(row))
        for words in crow:
            if words in stopwords:
                crow.remove(words)
        listx.append(crow)
    return listx
lcontent=cut_stop(data.content[:1000])#生成分词列表

Lcontent[0]:

lda模型可视化代码 lda 可视化_nlp_06


生成语料

#语料
corpus=[]
for row in lcontent:
    text=" ".join(row)
    corpus.append(text)

corpus[0]:

lda模型可视化代码 lda 可视化_python_07

2.3.Tfidf

#tfidf
vectorizer = CountVectorizer()
vector=vectorizer.fit_transform(corpus)#转化为词频矩阵
transformer = TfidfTransformer()#该类会统计每个词语的tf-idf权值
tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))
tfidf_weight = tfidf.toarray()
word = vectorizer.get_feature_names()#获取词袋模型中的所有词语
print(f'查看矩阵维度:{vector.shape}')#查看矩阵维度

lda模型可视化代码 lda 可视化_python_08

2.4.计算困惑度

可以简单理解为指定不同聚类数,然后通过lda.perplexity()函数进行处理,或者通过lda.score()进行评分绘制。困惑度理论上选取最低点,或者第一个拐点。绘制可以使用最常用的matplotlib库。

plexs = []
scores = []
n_max_topics = 10
for i in range(1,n_max_topics):
    print('正在进行第',i,'轮计算')
    lda = LatentDirichletAllocation(n_components=i, max_iter=5,
                                    learning_method='online',
                                    learning_offset=50,random_state=0)
    lda.fit(tfidf_weight )
    plexs.append(lda.perplexity(tfidf_weight ))
    scores.append(lda.score(tfidf_weight ))
n_t=9                                      #区间最右侧的值。注意:不能大于等于n_max_topics
x=list(range(1,n_t))
plt.plot(x,plexs[1:n_t])
plt.xlabel("number of topics")
plt.ylabel("perplexity")
plt.show()

见下图,因此选择主题数为2

lda模型可视化代码 lda 可视化_权重_09

2.5.LDA模型构建

#LDA构建
n_topics = 2
lda=LatentDirichletAllocation(n_components=n_topics,#主题个数
                              max_iter=5,#EM算法最大迭代次数
                              learning_method='online',#只在fit方法中使用,总体说来,当数据尺寸特别大的时候,在线online更新会比批处理batch更新快得多
                              learning_offset=50.,#一个(正)参数,可以减轻online在线学习中的早期迭代的负担。
                              random_state=0
                              )
lda.fit(tfidf_weight )#拟合
topicc=lda.components_#主题-词项分布
topics=lda.transform(tfidf_weight )#文档-主题分布

2.6.主题与分词

2.6.1.权重值

#每个单词的主题权重值

id = 0
for tt_m in topicc:
    tt_dict = [(name, tt) for name, tt in zip(word, tt_m)]
    tt_dict = sorted(tt_dict, key=lambda x: x[1], reverse=True)
    # 打印权重值大于0.6的主题词:
    # tt_dict = [tt_threshold for tt_threshold in tt_dict if tt_threshold[1] > 0.6]
    # 打印每个类别前5个主题词:
    tt_dict = tt_dict[:8]
    print('主题%d:' % (id), tt_dict)
    id +=1

lda模型可视化代码 lda 可视化_nlp_10

2.6.2.每个主题前25个词

#输出每个主题对应词语
def print_top_words(model, feature_names, n_top_words):
    tword = []
    for topic_idx, topic in enumerate(model.components_):
        print("Topic #%d:" % topic_idx)
        topic_w = " ".join([feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]])
        tword.append(topic_w)
        print(topic_w)
    return tword
n_top_words = 25#前几个自己指定
topic_word = print_top_words(lda, word, n_top_words)

lda模型可视化代码 lda 可视化_权重_11

3.可视化

import pyLDAvis.sklearn
pic = pyLDAvis.sklearn.prepare(lda, vector, vectorizer)
pyLDAvis.save_html(pic, 'lda_pass'+str(n_topics)+'.html')
pyLDAvis.show(pic)

lda模型可视化代码 lda 可视化_nlp_12


lda模型可视化代码 lda 可视化_权重_13