深度学习与自然语言处理第三次作业


问题提出

在给定的数据库上利用Topic Model做无监督学习,学习到主题的分布。可以在数据库中随机选定K本小说,在每本小说中随机抽出M个段落作为训练数据,并抽出N个段落作为测试,利用topic model和其他的分类器对给定的段落属于哪一本小说进行分类。 其中K至少为3.


一、Topic Model

Topic model 是一种统计建模,用于发现出现在文档集合中的抽象主题。潜在 Dirichlet 分配(Latent Dirichlet Allocation, LDA)是Topic model的一种,用于将文档中的文本分类为特定的主题。本文就采用了LDA模型对语料进行学习与分类。

二、LDA模型

1.LDA概述

LDA(Latent Dirichlet Allocation)是一种文档主题生成模型,也称为一个三层贝叶斯概率模型,包含词、主题和文档三层结构。所谓生成模型,就是说,我们认为一篇文章的每个词都是通过“以一定概率选择了某个主题,并从这个主题中以一定概率选择某个词语”这样一个过程得到。文档到主题服从多项式分布,主题到词服从多项式分布。
LDA是一种非监督机器学习技术,可以用来识别大规模文档集(document collection)或语料库(corpus)中潜藏的主题信息。它采用了词袋(bag of words)的方法,这种方法将每一篇文档视为一个词频向量,从而将文本信息转化为了易于建模的数字信息。但是词袋方法没有考虑词与词之间的顺序,这简化了问题的复杂性,同时也为模型的改进提供了契机。每一篇文档代表了一些主题所构成的一个概率分布,而每一个主题又代表了很多单词所构成的一个概率分布。

2.LDA生成过程

首先定义文档集合 D D D,主题(topic)集合 T T T
D D D中每个文档 d d d看作一个单词序列 < w 1 , w 2 , . . . , w n > <w1,w2,...,wn> <w1,w2,...,wn> w i wi wi表示第 i i i个单词,设 d d d n n n个单词。
D D D中涉及的所有不同单词组成一个大集合VOC,LDA以文档集合 D D D作为输入,希望训练出的两个结果向量(设聚成 k k k个Topic,VOC中共包含 m m m个词):
·对每个 D D D中的文档 d d d,对应到不同Topic的概率 θ d < p t 1 , . . . , p t k > θd<pt1,...,ptk> θd<pt1,...,ptk>,其中, p t i pti pti表示 d d d对应 T T T中第 i i i个Topic的概率。计算方法是直观的, p t i = n t i / n pti=nti/n pti=nti/n,其中 n t i nti nti表示 d d d中对应第 i i i个Topic的词的数目, n n n d d d中所有词的总数。
·对每个 T T T中的Topic,生成不同单词的概率 φ t < p w 1 , . . . , p w m > φt<pw1,...,pwm> φt<pw1,...,pwm>,其中, p w i pwi pwi表示 t t t生成VOC中第 i i i个单词的概率。计算方法同样很直观, p w i = N w i / N pwi=Nwi/N pwi=Nwi/N,其中 N w i Nwi Nwi表示对应到Topic的VOC中第 i i i个单词的数目,N表示所有对应到Topic的单词总数。
LDA的核心公式如下:
p ( w ∣ d ) = p ( w ∣ t ) ∗ p ( t ∣ d ) p(w|d)=p(w|t)*p(t|d) p(wd)=p(wt)p(td)
直观的看这个公式,就是以Topic作为中间层,可以通过当前的 θ d θd θd φ t φt φt给出了文档 d d d中出现单词 w w w的概率。其中 p ( t ∣ d ) p(t|d) p(td)利用θd计算得到, p ( w ∣ t ) p(w|t) p(wt)利用 φ t φt φt计算得到。利用当前的 θ d θd θd φ t φt φt,我们可以为一个文档中的一个单词计算它对应任意一个Topic时的 p ( w ∣ d ) p(w|d) p(wd),然后根据这些结果来更新这个词应该对应的Topic。然后,如果这个更新改变了这个单词所对应的Topic,就会反过来影响 θ d θd θd φ t φt φt

三、实验过程

1.预处理

代码如下:

def read_novel(path):  # 读取语料内容
    content = []
    names = os.listdir(path)
    for name in names:
            novel_name = path + '\\' + name
            with open(novel_name, 'r', encoding='ANSI') as f:
                con = f.read()
                con = content_deal(con)  # 语料预处理
                con = jieba.lcut(con)  # 结巴分词
                content.append(con)
            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_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.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方便后续计算

3.模型训练

首先计算每个topic被选中的概率:

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)

然后进行迭代,训练模型,具体步骤参加注释,已十分详细:

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('模型训练完毕!')

本次训练使用了白马啸西风、碧血剑、飞狐外传三本小说作为语料库,训练的到的每本小说分属各个Topic的概率如下:

Topic1Topic2Topic3
0.242748570.449005150.30824628
0.003968270.720402280.27562945
0.005283000.373103830.62161317

4.数据测试

在三本小说中分别节选了5个部分作为测试数据集,即最终形成了15篇待分类文章。
首先仍然在读取后对15篇待分类文章进行预处理,之后将15篇待分类文章中的每个词赋予一个随机的初始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)

在完成这些后,同样通过迭代,但迭代中计算概率时,每个词在每个Topic中出现的概率时固定的,每个Topic有多少词也是固定的,即我们的 K K K个Topic的骰子已经固定:

    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('测试集测试完毕!')

迭代完成后,得到的每篇测试文章分别属于各个Topic的概率如下:

序号Topic1Topic2Topic3
10.210465120.398837210.39069767
20.249084250.505494510.24542125
30.230110160.449204410.32068543
40.222222220.401851850.37592593
50.290873280.502954690.20617203
60.004062680.665699360.33023796
70.006843960.742080560.25107548
80.002525680.682774880.31469944
90.003541670.718958330.2775000
100.00303030.841991340.15497835
110.007990870.398401830.59360731
120.001895440.362817880.63528668
130.002235470.340536510.65722802
140.001155850.391639380.60720478
150.004199640.344209340.65159102

接下来,则需要根据这些概率结果,区分每篇待分类文章究竟来自哪一本小说,此处我采用的是欧式距离的方式,即比较待分类文章与已知的小说,两者对于各个Topic的概率向量之间的距离最近,即认为是来自该本小说,欧式距离的计算过程如下:

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)

最终得到的欧式距离如下:

序号白马啸西风碧血剑飞狐外传
10.0103572765857025420.159285741395810060.09608387544877363
20.0071781726215325580.107179731423895430.2184867066907407
30.00031450173220526630.126718484440840580.1468960532992692
40.0072252993809722740.15916854878513130.1082512986030865
50.0156456929187835760.134422269165739320.2710143976392976
60.104410967599233340.0059745080254992540.17051315054588634
70.144812682720379730.00108111469337609370.27344444857253625
80.112396965845176030.002944367470934770.19009979736829433
90.131039996087700625.765953987083401e-060.23803224531248673
100.235394049049651060.0293414647673991350.4376086266135305
110.1391027913857220.20481039481800740.0014316497501364188
120.172393905608306560.25722423110921720.00030424127748361716
130.19140025173505960.289918476276003640.0023383347939665523
140.151034060382393980.218035159431851140.0005682016960899776
150.185773363845531670.282868291488141240.0017347367165797397

最终根据欧式距离最短,得到最终的分类结果为1-5为白马啸西风、6-10为碧血剑、11-15为飞狐外传,与实际情况完全吻合,正确率100%。
之所以这么按照顺序来则是与我在测试集中拜访这些文章的顺序有关,测试集文件夹如图所示,修改摆放顺序同样能够100%判断正确。
测试集情况
程序中的输出截图如下:
在这里插入图片描述

总结

本次应用Topic Model中的一例,即LDA模型对语料进行了模型训练与测试,测试效果非常好,通过实践也加深了我对自然语言处理的认识和理解,但本次任务完成仍然存在不足之处,例如代码的复杂度有些高,在我已经进行简化后仍然需要220s左右的时间才能完成全部过程,而随着语料库的增加整体时间则会拉得更长,后续我将继续优化算法,例如每篇文章、每个Topic应该只选取重点的词来处理,而不是全部,这将显著降低算法的时间复杂度。


附录

所有代码如下:

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:
            novel_name = path + '\\' + name
            with open(novel_name, 'r', encoding='ANSI') as f:
                con = f.read()
                con = content_deal(con)
                con = jieba.lcut(con)  # 结巴分词
                content.append(con)
            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("../深度学习与自然语言处理/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_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)

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值