深度学习与自然语言处理第三次作业——LDA段落主题分布问题
深度学习与自然语言处理第三次作业——LDA段落主题分布问题利用LDA模型解决段落主体分布问题
深度学习与自然语言处理第三次作业——LDA段落主题分布问题
利用LDA模型解决段落主体分布问题
文章目录
一、解题背景
从给定的语料库中均匀抽取200个段落(每个段落大于500个词), 每个段落的标签就是对应段落所属的小说。利用LDA模型对于文本建模,并把每个段落表示为主题分布后进行分类。验证与分析分类结果。
二、解题原理
1、LDA描述
LDA(Linear Discriminant Analysis),是一种文档主题生成模型,,它可以将文档中每篇文档的主题按照概率分布的形式给出。也称为一个三层贝叶斯概率模型,包含词、主题和文档三层结构。所谓生成模型,就是说,我们认为一篇文章的每个词都是通过“以一定概率选择了某个主题,并从这个主题中以一定概率选择某个词语”这样一个过程得到。文档到主题服从多项式分布,主题到词服从多项式分布。
LDA是一种非监督机器学习技术,可以用来识别大规模文档集(document collection)或语料库(corpus)中潜藏的主题信息。它采用了词袋(bag of words)的方法,这种方法将每一篇文档视为一个词频向量,从而将文本信息转化为了易于建模的数字信息。但是词袋方法没有考虑词与词之间的顺序,这简化了问题的复杂性,同时也为模型的改进提供了契机。每一篇文档代表了一些主题所构成的一个概率分布,而每一个主题又代表了很多单词所构成的一个概率分布。
LDA的核心思想是寻找到最佳的投影方法,将高维的样本投影到特征空间(feature space),使得不同类别间的数据“距离”最大,而同一类别内的数据“距离”最小。
2、LDA模型生成
首先定义文章集合为 D o c Doc Doc,文章主题集合为 T o p i c Topic Topic, D o c Doc Doc中的每个文档 d o c doc doc可以看作为一个单词序列 < w 1 , w 2 , . . . , w n > <w_1,w_2,...,w_n> <w1,w2,...,wn>,其中 w i w_i wi表示为第 i i i个单词, d o c doc doc共有 n n n个单词。
D o c Doc Doc中的所有不同单词组成一个集合 V o c Voc Voc,LDA模型以文档集合 D o c Doc Doc作为输入,最终训练处两个结果向量, k k k表示Topi词, m m m表示 V o c Voc Voc中包含的词语数量。
对每个 D o c Doc Doc中对应到不同 T o p i c Topic Topic的概率 θ d = < p t 1 , . . . , p t k > \theta_d=<p_{t_1},...,p_{t_k}> θd=<pt1,...,ptk>,其中 p t i p_{t_i} pti表示 d o c doc doc对应 T o p i c Topic Topic中第 i i i个Topic词的概率。
其中 p t i = n t i n p_{t_i}=\frac{n_{t_i}}{n} pti=nnti n t i n_{t_i} nti表示 d o c doc doc中对应的第 i i i个Topic的词的数目, n n n表示 d o c doc doc中所有词的总数。
对每个 T o p i c Topic Topic中的Topic,生成不同单词的概率 φ t = < p w 1 , . . . , p w m > \varphi_t=<p_{w_1},...,p_{w_m}> φt=<pw1,...,pwm>,其中 p w i p_{w_i} pwi表示 t t t生成 V o c Voc Voc中的第 i i i个单词的概率。
其中 p w i = N w i N p_{w_i}=\frac{N_{w_i}}{N} pwi=NNwi N w i N_{w_i} Nwi表示对应到Topic的 V o c Voc Voc中的第 i i i个单词的数目, N N N表示所有对应到Topic的单词总数。
LDA 的核心公式如下所示:
P ( 词 ∣ 文 档 ) = P ( 词 ∣ 主 题 ) ∗ P ( 主 题 ∣ 文 档 ) P(词|文档)=P(词|主题)*P(主题|文档) P(词∣文档)=P(词∣主题)∗P(主题∣文档)
即 P ( w ∣ d ) = P ( w ∣ t ) ∗ P ( t ∣ d ) P(w|d)=P(w|t)*P(t|d) P(w∣d)=P(w∣t)∗P(t∣d)
公式以Topic作为中间层,通过当前的 θ d \theta_d θd和 φ t \varphi_t φt给出了文档 d d d中出现单词 w w w的概率。其中的 P ( t ∣ d ) P(t|d) P(t∣d)可通过 θ d \theta_d θd计算得到, P ( w ∣ t ) P(w|t) P(w∣t)利用 φ t \varphi_t φt计算得到。因此,我们利用当前的 θ d \theta_d θd和 φ t \varphi_t φt,我们可以为一个文档中的单词计算它对应任意一个Topic时的 P ( w ∣ d ) P(w|d) P(w∣d)值,然后根据这些结果来更新这个词对应的Topic。相对应的,如果这个更新改变了这个单词所对应的Topic值,反过来也会影响 θ d \theta_d θd和 φ t \varphi_t φt。
三、实验分析
1、语料处理
题目要求均匀抽取200个段落(每个段落大于500个词), 每个段落的标签就是对应段落所属的小说。
对给定语料库进行分析可知,语料库内共有16篇文章,从每一篇文章内抽取13个段落,共有208个段落;对每篇文章分词之后,将一篇文章的总词数除以13,即每篇文章共有13个区间,所选取的段落为每个区间抽取前500个词。
代码如下(读取语料内容):
def read_novel(path): # 读取语料内容
content = []
names = os.listdir(path)
for name in names:
con_temp = []
novel_name = path + '\\' + name
with open(novel_name, 'r', encoding='ANSI') as f:
con = f.read()
con = content_deal(con)
con = jieba.lcut(con) # 结巴分词
con_list = list(con)
pos = int(len(con)//13) ####16篇文章,分词后,每篇均匀选取13个500词段落进行建模
for i in range(13):
con_temp = con_temp + con_list[i*pos:i*pos+500]
content.append(con_temp)
f.close()
return content, names
代码如下(语料预处理):
def content_deal(content): # 语料预处理,进行断句,去除一些广告和无意义内容
ad = ['本书来自www.cr173.com免费txt小说下载站\n更多更新免费电子书请关注www.cr173.com', '----〖新语丝电子文库(www.xys.org)〗', '新语丝电子文库',
'\u3000', '\n', '。', '?', '!', ',', ';', ':', '、', '《', '》', '“', '”', '‘', '’', '[', ']', '....', '......',
'『', '』', '(', ')', '…', '「', '」', '\ue41b', '<', '>', '+', '\x1a', '\ue42b']
for a in ad:
content = content.replace(a, '')
return content
2、模型训练
首先进行初始化,每篇文章的每个词语随机赋予一个初始的Topic值,然后分别统计每篇文章的总词数、每篇文章的词频、每个Topic的总词数、每个Topic的词频;
再计算每个topic被选中的概率,然后进行迭代,训练模型,具体步骤如下所示:
代码如下(模型训练):
[data_txt, files] = read_novel("金庸小说集")
Topic_All = [] # 每篇文章中的每个词来自哪个topic
Topic_count = {} # 每个topic有多少词
Topic_fre0 = {}; Topic_fre1 = {}; Topic_fre2 = {}; Topic_fre3 = {};
Topic_fre4 = {}; Topic_fre5 = {}; Topic_fre6 = {}; Topic_fre7 = {};
Topic_fre8 = {}; Topic_fre9 = {}; Topic_fre10 = {}; Topic_fre11 = {};
Topic_fre12 = {}; Topic_fre13 = {}; Topic_fre14 = {}; Topic_fre15 = {} # 每个topic的词频
Doc_count = [] # 每篇文章中有多少个词
Doc_fre = [] # 每篇文章有多少各个topic的词
i = 0
for data in data_txt:
topic = []
docfre = {}
for word in data:
a = random.randint(0, len(data_txt)-1) # 为每个单词赋予一个随机初始topic
topic.append(a)
if '\u4e00' <= word <= '\u9fa5':
Topic_count[a] = Topic_count.get(a, 0) + 1 # 统计每个topic总词数
docfre[a] = docfre.get(a, 0) + 1 # 统计每篇文章的词频
exec('Topic_fre{}[word]=Topic_fre{}.get(word, 0) + 1'.format(i, i)) # 统计每个topic的词频
Topic_All.append(topic)
docfre = list(dict(sorted(docfre.items(), key=lambda x: x[0], reverse=False)).values())
Doc_fre.append(docfre)
Doc_count.append(sum(docfre)) # 统计每篇文章的总词数
# exec('print(len(Topic_fre{}))'.format(i))
i += 1
Topic_count = list(dict(sorted(Topic_count.items(), key=lambda x: x[0], reverse=False)).values())
# print(Topic_All[0])
Doc_fre = np.array(Doc_fre) # 转为array方便后续计算
Topic_count = np.array(Topic_count) # 转为array方便后续计算
Doc_count = np.array(Doc_count) # 转为array方便后续计算
print(Doc_fre)
print(Topic_count)
print(Doc_count)
# print(Topic_fre0)
Doc_pro = [] # 每个topic被选中的概率
Doc_pronew = [] # 记录每次迭代后每个topic被选中的新概率
for i in range(len(data_txt)):
doc = np.divide(Doc_fre[i], Doc_count[i])
Doc_pro.append(doc)
Doc_pro = np.array(Doc_pro)
print(Doc_pro)
stop = 0 # 迭代停止标志
loopcount = 1 # 迭代次数
while stop == 0:
i = 0
for data in data_txt:
top = Topic_All[i]
for w in range(len(data)):
word = data[w]
pro = []
topfre = []
if '\u4e00' <= word <= '\u9fa5':
for j in range(len(data_txt)):
exec('topfre.append(Topic_fre{}.get(word, 0))'.format(j)) # 读取该词语在每个topic中出现的频数
pro = Doc_pro[i] * topfre / Topic_count # 计算每篇文章选中各个topic的概率乘以该词语在每个topic中出现的概率,得到该词出现的概率向量
m = np.argmax(pro) # 认为该词是由上述概率之积最大的那个topic产生的
Doc_fre[i][top[w]] -= 1 # 更新每个文档有多少各个topic的词
Doc_fre[i][m] += 1
Topic_count[top[w]] -= 1 # 更新每个topic的总词数
Topic_count[m] += 1
exec('Topic_fre{}[word] = Topic_fre{}.get(word, 0) - 1'.format(top[w], top[w])) # 更新每个topic该词的频数
exec('Topic_fre{}[word] = Topic_fre{}.get(word, 0) + 1'.format(m, m))
top[w] = m
Topic_All[i] = top
i += 1
print(Doc_fre, 'new')
print(Topic_count, 'new')
if loopcount == 1: # 计算新的每篇文章选中各个topic的概率
for i in range(len(data_txt)):
doc = np.divide(Doc_fre[i], Doc_count[i])
Doc_pronew.append(doc)
Doc_pronew = np.array(Doc_pronew)
else:
for i in range(len(data_txt)):
doc = np.divide(Doc_fre[i], Doc_count[i])
Doc_pronew[i] = doc
print(Doc_pro)
print(Doc_pronew)
if (Doc_pronew == Doc_pro).all(): # 如果每篇文章选中各个topic的概率不再变化,则认为模型已经训练完毕
stop = 1
else:
Doc_pro = Doc_pronew.copy()
loopcount += 1
print(Doc_pronew) # 输出最终训练的到的每篇文章选中各个topic的概率
print(loopcount) # 输出迭代次数
# print(Doc_pro0)
# print(Doc_pronew0)
print('模型训练完毕!')
3、模型测试
仍然在对应的16部小说中选择段落作为测试集,在之前训练集中选取的是208个段落中的第0-500个单词,因此在测试集中选取第501-1000单词形成测试段落,最终形成待分类文章。
def read_novel1(path): # 读取语料内容——测试集
content = []
names = os.listdir(path)
for name in names:
con_temp = []
novel_name = path + '\\' + name
with open(novel_name, 'r', encoding='ANSI') as f:
con = f.read()
con = content_deal(con)
con = jieba.lcut(con) # 结巴分词
con_list = list(con)
pos = int(len(con)//13) ####16篇文章,分词后,每篇均匀选取13个500词段落进行建模
for i in range(13):
con_temp = con_temp + con_list[i*pos+501:i*pos+1000]##测试集
content.append(con_temp)
f.close()
return content, names
首先仍然在读取后对15篇待分类文章进行预处理,之后将15篇待分类文章中的每个词赋予一个随机的初始Topic,并同样统计每篇文章的总词数、每篇文章的词频,分别记录下来,但此时与模型训练时不同的是,每个Topic的总词数、每个Topic的词频,将不再需要统计,这两个量是模型训练已经完成了的,将作为已知量来对数据进行测试。
接下来,则需要根据这些概率结果,区分每篇待分类文章究竟来自哪一本小说,此处采用的是欧式距离的方式,即比较待分类文章与已知的小说,两者对于各个Topic的概率向量之间的距离最近,即认为是来自该本小说。
[test_txt, files] = read_novel("金庸小说集")
Doc_count_test = [] # 每篇文章中有多少个词
Doc_fre_test = [] # 每篇文章有多少各个topic的词
Topic_All_test = [] # 每篇文章中的每个词来自哪个topic
i = 0
for data in test_txt:
topic = []
docfre = {}
for word in data:
a = random.randint(0, len(data_txt) - 1) # 为每个单词赋予一个随机初始topic
topic.append(a)
if '\u4e00' <= word <= '\u9fa5':
docfre[a] = docfre.get(a, 0) + 1 # 统计每篇文章的词频
Topic_All_test.append(topic)
docfre = list(dict(sorted(docfre.items(), key=lambda x: x[0], reverse=False)).values())
Doc_fre_test.append(docfre)
Doc_count_test.append(sum(docfre)) # 统计每篇文章的总词数
i += 1
# print(Topic_All[0])
Doc_fre_test = np.array(Doc_fre_test)
Doc_count_test = np.array(Doc_count_test)
print(Doc_fre_test)
print(Doc_count_test)
Doc_pro_test = [] # 每个topic被选中的概率
Doc_pronew_test = [] # 记录每次迭代后每个topic被选中的新概率
for i in range(len(test_txt)):
doc = np.divide(Doc_fre_test[i], Doc_count_test[i])
Doc_pro_test.append(doc)
Doc_pro_test = np.array(Doc_pro_test)
print(Doc_pro_test)
stop = 0 # 迭代停止标志
loopcount = 1 # 迭代次数
while stop == 0:
i = 0
for data in test_txt:
top = Topic_All_test[i]
for w in range(len(data)):
word = data[w]
pro = []
topfre = []
if '\u4e00' <= word <= '\u9fa5':
for j in range(len(data_txt)):
exec('topfre.append(Topic_fre{}.get(word, 0))'.format(j)) # 读取该词语在每个topic中出现的频数
pro = Doc_pro_test[i] * topfre / Topic_count # 计算每篇文章选中各个topic的概率乘以该词语在每个topic中出现的概率,得到该词出现的概率向量
m = np.argmax(pro) # 认为该词是由上述概率之积最大的那个topic产生的
Doc_fre_test[i][top[w]] -= 1 # 更新每个文档有多少各个topic的词
Doc_fre_test[i][m] += 1
top[w] = m
Topic_All_test[i] = top
i += 1
print(Doc_fre_test, 'new')
if loopcount == 1: # 计算新的每篇文章选中各个topic的概率
for i in range(len(test_txt)):
doc = np.divide(Doc_fre_test[i], Doc_count_test[i])
Doc_pronew_test.append(doc)
Doc_pronew_test = np.array(Doc_pronew_test)
else:
for i in range(len(test_txt)):
doc = np.divide(Doc_fre_test[i], Doc_count_test[i])
Doc_pronew_test[i] = doc
print(Doc_pro_test)
print(Doc_pronew_test)
if (Doc_pronew_test == Doc_pro_test).all(): # 如果每篇文章选中各个topic的概率不再变化,则认为训练集已分类完毕
stop = 1
else:
Doc_pro_test = Doc_pronew_test.copy()
loopcount += 1
print(Doc_pronew)
print(Doc_pronew_test)
print(loopcount)
print('测试集测试完毕!')
result = []
for k in range(len(test_txt)):
pro = []
for i in range(len(data_txt)):
dis = 0
for j in range(len(data_txt)):
dis += (Doc_pro[i][j] - Doc_pro_test[k][j])**2 # 计算欧式距离
pro.append(dis)
m = pro.index(min(pro))
print(pro)
result.append(m)
print(files)
print(result)
以上代码参考前辈代码,与前人代码相比,本人代码新增段落处理模块,针对作业给出段落要求,对段落进行分割。
https://blog.csdn.net/shzx_55733/article/details/116280982?spm=1001.2014.3001.5501
四、实验总结
1、实验结果
本次应用了LDA模型对语料进行了模型训练与测试,从实验结果看出:
- 在模型训练阶段,经过15次迭代(
见下图
),得到最终构建的LDA模型
-最终测试集的(部分
)结果如下所示:每一篇对应的顺序与在该文章在语料库内摆放的顺序一致。
其他实验txt结果及相关代码见网盘NLP-3所示。
2、实验分析
本次实验通过构建LDA模型,来对金庸小说集主题进行分类,测试效果非常好。
通过这次作业,加深了我对自然语言处理用途的理解,但本次任务仍存在不足之处,本次代码的运行时间较长,在未来,可以考虑对Topic进行精炼,选取重要的关键词进行处理,这将明显降低运行的时间。
附录
实验txt结果及相关代码见网盘NLP-3所示。
本次实验的完整代码如下所示,实验代码使用python
实现:
import math
import jieba
import os # 用于处理文件路径
import random
import numpy as np
def read_novel(path): # 读取语料内容
content = []
names = os.listdir(path)
for name in names:
con_temp = []
novel_name = path + '\\' + name
with open(novel_name, 'r', encoding='ANSI') as f:
con = f.read()
con = content_deal(con)
con = jieba.lcut(con) # 结巴分词
con_list = list(con)
pos = int(len(con)//13) ####16篇文章,分词后,每篇均匀选取13个500词段落进行建模
for i in range(13):
con_temp = con_temp + con_list[i*pos:i*pos+500]
content.append(con_temp)
f.close()
return content, names
def read_novel1(path): # 读取语料内容
content = []
names = os.listdir(path)
for name in names:
con_temp = []
novel_name = path + '\\' + name
with open(novel_name, 'r', encoding='ANSI') as f:
con = f.read()
con = content_deal(con)
con = jieba.lcut(con) # 结巴分词
con_list = list(con)
pos = int(len(con)//13) ####16篇文章,分词后,每篇均匀选取13个500词段落进行建模
for i in range(13):
con_temp = con_temp + con_list[i*pos+501:i*pos+1000]
content.append(con_temp)
f.close()
return content, names
def content_deal(content): # 语料预处理,进行断句,去除一些广告和无意义内容
ad = ['本书来自www.cr173.com免费txt小说下载站\n更多更新免费电子书请关注www.cr173.com', '----〖新语丝电子文库(www.xys.org)〗', '新语丝电子文库',
'\u3000', '\n', '。', '?', '!', ',', ';', ':', '、', '《', '》', '“', '”', '‘', '’', '[', ']', '....', '......',
'『', '』', '(', ')', '…', '「', '」', '\ue41b', '<', '>', '+', '\x1a', '\ue42b']
for a in ad:
content = content.replace(a, '')
return content
if __name__ == '__main__':
[data_txt, files] = read_novel("金庸小说集")
Topic_All = [] # 每篇文章中的每个词来自哪个topic
Topic_count = {} # 每个topic有多少词
Topic_fre0 = {}; Topic_fre1 = {}; Topic_fre2 = {}; Topic_fre3 = {};
Topic_fre4 = {}; Topic_fre5 = {}; Topic_fre6 = {}; Topic_fre7 = {};
Topic_fre8 = {}; Topic_fre9 = {}; Topic_fre10 = {}; Topic_fre11 = {};
Topic_fre12 = {}; Topic_fre13 = {}; Topic_fre14 = {}; Topic_fre15 = {} # 每个topic的词频
Doc_count = [] # 每篇文章中有多少个词
Doc_fre = [] # 每篇文章有多少各个topic的词
i = 0
for data in data_txt:
topic = []
docfre = {}
for word in data:
a = random.randint(0, len(data_txt)-1) # 为每个单词赋予一个随机初始topic
topic.append(a)
if '\u4e00' <= word <= '\u9fa5':
Topic_count[a] = Topic_count.get(a, 0) + 1 # 统计每个topic总词数
docfre[a] = docfre.get(a, 0) + 1 # 统计每篇文章的词频
exec('Topic_fre{}[word]=Topic_fre{}.get(word, 0) + 1'.format(i, i)) # 统计每个topic的词频
Topic_All.append(topic)
docfre = list(dict(sorted(docfre.items(), key=lambda x: x[0], reverse=False)).values())
Doc_fre.append(docfre)
Doc_count.append(sum(docfre)) # 统计每篇文章的总词数
# exec('print(len(Topic_fre{}))'.format(i))
i += 1
Topic_count = list(dict(sorted(Topic_count.items(), key=lambda x: x[0], reverse=False)).values())
# print(Topic_All[0])
Doc_fre = np.array(Doc_fre) # 转为array方便后续计算
Topic_count = np.array(Topic_count) # 转为array方便后续计算
Doc_count = np.array(Doc_count) # 转为array方便后续计算
print(Doc_fre)
print(Topic_count)
print(Doc_count)
# print(Topic_fre0)
Doc_pro = [] # 每个topic被选中的概率
Doc_pronew = [] # 记录每次迭代后每个topic被选中的新概率
for i in range(len(data_txt)):
doc = np.divide(Doc_fre[i], Doc_count[i])
Doc_pro.append(doc)
Doc_pro = np.array(Doc_pro)
print(Doc_pro)
stop = 0 # 迭代停止标志
loopcount = 1 # 迭代次数
while stop == 0:
i = 0
for data in data_txt:
top = Topic_All[i]
for w in range(len(data)):
word = data[w]
pro = []
topfre = []
if '\u4e00' <= word <= '\u9fa5':
for j in range(len(data_txt)):
exec('topfre.append(Topic_fre{}.get(word, 0))'.format(j)) # 读取该词语在每个topic中出现的频数
pro = Doc_pro[i] * topfre / Topic_count # 计算每篇文章选中各个topic的概率乘以该词语在每个topic中出现的概率,得到该词出现的概率向量
m = np.argmax(pro) # 认为该词是由上述概率之积最大的那个topic产生的
Doc_fre[i][top[w]] -= 1 # 更新每个文档有多少各个topic的词
Doc_fre[i][m] += 1
Topic_count[top[w]] -= 1 # 更新每个topic的总词数
Topic_count[m] += 1
exec('Topic_fre{}[word] = Topic_fre{}.get(word, 0) - 1'.format(top[w], top[w])) # 更新每个topic该词的频数
exec('Topic_fre{}[word] = Topic_fre{}.get(word, 0) + 1'.format(m, m))
top[w] = m
Topic_All[i] = top
i += 1
print(Doc_fre, 'new')
print(Topic_count, 'new')
if loopcount == 1: # 计算新的每篇文章选中各个topic的概率
for i in range(len(data_txt)):
doc = np.divide(Doc_fre[i], Doc_count[i])
Doc_pronew.append(doc)
Doc_pronew = np.array(Doc_pronew)
else:
for i in range(len(data_txt)):
doc = np.divide(Doc_fre[i], Doc_count[i])
Doc_pronew[i] = doc
print(Doc_pro)
print(Doc_pronew)
if (Doc_pronew == Doc_pro).all(): # 如果每篇文章选中各个topic的概率不再变化,则认为模型已经训练完毕
stop = 1
else:
Doc_pro = Doc_pronew.copy()
loopcount += 1
print(Doc_pronew) # 输出最终训练的到的每篇文章选中各个topic的概率
print(loopcount) # 输出迭代次数
# print(Doc_pro0)
# print(Doc_pronew0)
print('模型训练完毕!')
[test_txt, files] = read_novel1("金庸小说集")
Doc_count_test = [] # 每篇文章中有多少个词
Doc_fre_test = [] # 每篇文章有多少各个topic的词
Topic_All_test = [] # 每篇文章中的每个词来自哪个topic
i = 0
for data in test_txt:
topic = []
docfre = {}
for word in data:
a = random.randint(0, len(data_txt) - 1) # 为每个单词赋予一个随机初始topic
topic.append(a)
if '\u4e00' <= word <= '\u9fa5':
docfre[a] = docfre.get(a, 0) + 1 # 统计每篇文章的词频
Topic_All_test.append(topic)
docfre = list(dict(sorted(docfre.items(), key=lambda x: x[0], reverse=False)).values())
Doc_fre_test.append(docfre)
Doc_count_test.append(sum(docfre)) # 统计每篇文章的总词数
i += 1
# print(Topic_All[0])
Doc_fre_test = np.array(Doc_fre_test)
Doc_count_test = np.array(Doc_count_test)
print(Doc_fre_test)
print(Doc_count_test)
Doc_pro_test = [] # 每个topic被选中的概率
Doc_pronew_test = [] # 记录每次迭代后每个topic被选中的新概率
for i in range(len(test_txt)):
doc = np.divide(Doc_fre_test[i], Doc_count_test[i])
Doc_pro_test.append(doc)
Doc_pro_test = np.array(Doc_pro_test)
print(Doc_pro_test)
stop = 0 # 迭代停止标志
loopcount = 1 # 迭代次数
while stop == 0:
i = 0
for data in test_txt:
top = Topic_All_test[i]
for w in range(len(data)):
word = data[w]
pro = []
topfre = []
if '\u4e00' <= word <= '\u9fa5':
for j in range(len(data_txt)):
exec('topfre.append(Topic_fre{}.get(word, 0))'.format(j)) # 读取该词语在每个topic中出现的频数
pro = Doc_pro_test[i] * topfre / Topic_count # 计算每篇文章选中各个topic的概率乘以该词语在每个topic中出现的概率,得到该词出现的概率向量
m = np.argmax(pro) # 认为该词是由上述概率之积最大的那个topic产生的
Doc_fre_test[i][top[w]] -= 1 # 更新每个文档有多少各个topic的词
Doc_fre_test[i][m] += 1
top[w] = m
Topic_All_test[i] = top
i += 1
print(Doc_fre_test, 'new')
if loopcount == 1: # 计算新的每篇文章选中各个topic的概率
for i in range(len(test_txt)):
doc = np.divide(Doc_fre_test[i], Doc_count_test[i])
Doc_pronew_test.append(doc)
Doc_pronew_test = np.array(Doc_pronew_test)
else:
for i in range(len(test_txt)):
doc = np.divide(Doc_fre_test[i], Doc_count_test[i])
Doc_pronew_test[i] = doc
print(Doc_pro_test)
print(Doc_pronew_test)
if (Doc_pronew_test == Doc_pro_test).all(): # 如果每篇文章选中各个topic的概率不再变化,则认为训练集已分类完毕
stop = 1
else:
Doc_pro_test = Doc_pronew_test.copy()
loopcount += 1
print(Doc_pronew)
print(Doc_pronew_test)
print(loopcount)
print('测试集测试完毕!')
result = []
for k in range(len(test_txt)):
pro = []
for i in range(len(data_txt)):
dis = 0
for j in range(len(data_txt)):
dis += (Doc_pro[i][j] - Doc_pro_test[k][j])**2 # 计算欧式距离
pro.append(dis)
m = pro.index(min(pro))
print(pro)
result.append(m)
print(files)
print(result)
更多推荐
所有评论(0)