热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

这篇文章主要介绍Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完

这篇文章主要介绍Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

    数据处理与分析

    本次大赛提供的材料是由csv格式编写,只需调用python中的pandas库读取即可。为了更直观的观察数据,我计算了文档的平均长度,以及每个标签分别对应的文档。(sen字典与tag字典的获取方法会在后文中展示,此步只用来呈现数据分布,运行时可先跳过)

    import matplotlib.pyplot as plt
    from tqdm import tqdm
    import time
    from numpy import *
    import pandas as pd
    
    print('count: 200000') #词典sen中,每个标签对应其所有句子的二维列表
    print('average: '+str(sum([[sum(sen[i][j]) for j in range(len(sen[i]))] for i in sen])/200000))
    x = []
    y = []
    for key,value in tag.items(): #词典tag中,每个标签对应该标签下的句子数目
        x.append(key)
        y.append(value)
    plt.bar(x,y)
    plt.show()

    最终我们得到了以下结果:

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    平均文档长约907词,每个标签对应的文档数从标签0至13逐个减少。

    基于机器学习的文本分类–朴素贝叶斯

    1. 模型介绍

    朴素贝叶斯分类器的基本思想是利用特征项和类别的联合概率来估计给定文档的类别概率。假设文本是基于词的一元模型,即文本中当前词的出现依赖于文本类别,但不依赖于其他词及文本的长度,也就是说,词与词之间是独立的。根据贝叶斯公式,文档Doc属于Ci类的概率为

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    文档Doc采用TF向量表示法,即文档向量V的分量为相应特征在该文档中出现的频度,文档Doc属于Ci类文档的概率为

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    其中,TF(ti,Doc)是文档Doc中特征ti出现的频度,为了防止出现不在词典中的词导致概率为0的情况,我们取P(ti|Ci)是对Ci类文档中特征ti出现的条件概率的拉普拉斯概率估计:

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    这里,TF(ti,Ci)是Ci类文档中特征ti出现的频度,|V|为特征集的大小,即文档表示中所包含的不同特征的总数目。

    2. 代码结构

    我直接通过python自带的open()函数读取文件,并建立对应词典,设定停用词,这里的停用词选择了words字典中出现在100000个文档以上的所有词。训练集取前19万个文档,测试集取最后一万个文档。

    train_df = open('./data/train_set.csv').readlines()[1:]
    train = train_df[0:190000]
    test = train_df[190000:200000]
    true_test = open('./data/test_a.csv').readlines()[1:]
    tag = {str(i):0 for i in range(0,14)}
    sen = {str(i):{} for i in range(0,14)}
    words={}
    stop_words = {'4149': 1, '1519': 1, '2465': 1, '7539': 1, ...... }

    接着,我们需要建立标签词典和句子词典,用tqdm函数来显示进度。

    for line in tqdm(train_df):
        cur_line = line.split('\t')
        cur_tag = cur_line[0]
        tag[cur_tag] += 1
        cur_line = cur_line[1][:-1].split(' ')
        for i in cur_line:
            if i not in words:
                words[i] = 1
            else:    
                words[i] += 1
            if i not in sen[cur_tag]:
                sen[cur_tag][i] = 1
            else:
                sen[cur_tag][i] += 1

    为了便于计算,我定义了如下函数,其中mul()用来计算列表中所有数的乘积,prob_clas() 用来计算P(Ci|Doc),用probability()来计算P(ti|Ci),在probability() 函数中,我将输出结果中分子+1,分母加上字典长度,实现拉普拉斯平滑处理。

    def mul(l):
        res = 1
        for i in l:
            res *= i
        return res
    def prob_clas(clas):
        return tag[clas]/(sum([tag[i] for i in tag]))
    def probability(char,clas):  #P(特征|类别)
        if char not in sen[clas]:
            num_char = 0
        else:
            num_char = sen[clas][char]
        return (1+num_char)/(len(sen[clas])+len(words))

    在做好所有准备工作,定义好函数后,分别对测试集中的每一句话计算十四个标签对应概率,并将概率最大的标签储存在预测列表中,用tqdm函数来显示进度。

    PRED = []
    for line in tqdm(true_test):
        result = {str(i):0 for i in range(0,14)}
        cur_line = line[:-1].split(' ')
        clas = cur_tag
        for i in result:
            prob = []
            for j in cur_line:
                if j in stop_words:
                    continue
                prob.append(log(probability(j,i)))
            result[i] = log(prob_clas(i))+sum(prob)
        for key,value in result.items():
            if(value == max(result.values())):
                pred = int(key)
        PRED.append(pred)

    最后把结果储存在csv文件中上传网站,提交后查看成绩。(用此方法编写的csv文件需要打开后删去第一列再上传)

    res=pd.DataFrame()
    res['label']=PRED
    res.to_csv('test_TL.csv')

    3. 结果分析

    在训练前19万个文档,测试后一万个文档的过程中,我不断调整停用词取用列表,分别用TF和TF-IDF向量表示法进行了测试,结果发现使用TF表示法准确性较高,最后取用停用词为出现在十万个文档以上的词。最终得出最高效率为0.622。

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    在提交至网站后,对五万个文档进行测试的F1值仅有 0.29左右,效果较差。

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    基于深度学习的文本分类–LSTM

    1. 模型介绍

    除了传统的机器学习方法,我使用了深度学习中的LSTM(Long Short-Term Memory)长短期记忆网络,来尝试处理新闻文本分类,希望能有更高的准确率。LSTM它是一种时间循环神经网络,适合于处理和预测时间序列中间隔和延迟相对较长的重要事件。LSTM 已经在科技领域有了多种应用。基于 LSTM 的系统可以学习翻译语言、控制机器人、图像分析、文档摘要、语音识别图像识别、手写识别、控制聊天机器人、预测疾病、点击率和股票、合成音乐等等任务。我采用深度学习库Keras来建立LSTM模型,进行文本分类。

    对于卷积神经网络CNN和循环网络RNN而言,随着时间的不断增加,隐藏层一次又一次地乘以权重W。假如某个权重w是一个接近于0或者大于1的数,随着乘法次数的增加,这个权重值会变得很小或者很大,造成反向传播时梯度计算变得很困难,造成梯度爆炸或者梯度消失的情况,模型难以训练。也就是说一般的RNN模型对于长时间距离的信息记忆很差,因此LSTM应运而生。

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    LSTM长短期记忆网络可以更好地解决这个问题。在LSTM的一个单元中,有四个显示为黄色框的网络层,每个层都有自己的权重,如以 σ 标记的层是 sigmoid 层,tanh是一个激发函数。这些红圈表示逐点或逐元素操作。单元状态在通过 LSTM 单元时几乎没有交互,使得大部分信息得以保留,单元状态仅通过这些控制门(gate)进行修改。第一个控制门是遗忘门,用来决定我们会从单元状态中丢弃什么信息。第二个门是更新门,用以确定什么样的新信息被存放到单元状态中。最后一个门是输出门,我们需要确定输出什么样的值。总结来说 LSTM 单元由单元状态和一堆用于更新信息的控制门组成,让信息部分传递到隐藏层状态。

    2. 代码结构

    首先是初始数据的设定和包的调用。考虑到平均句长约900,这里取最大读取长度为平均长度的2/3,即max_len为600,之后可通过调整该参数来调整学习效率。

    from tqdm import tqdm
    import pandas as pd
    import time
    import matplotlib.pyplot as plt
    import seaborn as sns
    from numpy import *
    from sklearn import metrics
    from sklearn.preprocessing import LabelEncoder,OneHotEncoder
    from keras.models import Model
    from keras.layers import LSTM, Activation, Dense, Dropout, Input, Embedding
    from keras.optimizers import rmsprop_v2
    from keras.preprocessing import sequence
    from keras.callbacks import EarlyStopping
    from keras.models import load_model
    import os.path
    
    max_words = 7549 #字典最大编号
    # 可通过调节max_len调整模型效果和学习速度
    max_len = 600 #句子的最大长度
    stop_words = {}

    接下来,我们定义一个将DataFrame的格式转化为矩阵的函数。该函数输出一个长度为600的二维文档列表和其对应的标签值。

    def to_seq(dataframe):
        x = []
        y = array([[0]*int(i)+[1]+[0]*(13-int(i)) for i in dataframe['label']])
        for i in tqdm(dataframe['text']):
            cur_sentense = []
            for word in i.split(' '):
                if word not in stop_words: #最终并未采用停用词列表
                    cur_sentense.append(word)
            x.append(cur_sentense)
        return sequence.pad_sequences(x,maxlen=max_len),y

    接下来是模型的主体函数。该函数输入测试的文档,测试集的真值,训练集和检验集,输出预测得到的混淆矩阵。具体代码介绍,见下列代码中的注释。

    def test_file(text,value,train,val):
        ## 定义LSTM模型
        inputs = Input(name='inputs',shape=[max_len])
        ## Embedding(词汇表大小,batch大小,每个新闻的词长)
        layer = Embedding(max_words+1,128,input_length=max_len)(inputs)
        layer = LSTM(128)(layer)
        layer = Dense(128,activation="relu",name="FC1")(layer)
        layer = Dropout(0.5)(layer)
        layer = Dense(14,activation="softmax",name="FC2")(layer)
        model = Model(inputs=inputs,outputs=layer)
        model.summary()
        model.compile(loss="categorical_crossentropy",optimizer=rmsprop_v2.RMSprop(),metrics=["accuracy"])
        
        ## 模型建立好之后开始训练,如果已经保存训练文件(.h6格式),则直接调取即可
        if os.path.exists('my_model.h6') == True:
            model = load_model('my_model.h6')
        else:
            train_seq_mat,train_y = to_seq(train)
            val_seq_mat,val_y = to_seq(val)
            model.fit(train_seq_mat,train_y,batch_size=128,epochs=10,  #可通过epochs数来调整准确率和运算速度
                          validation_data=(val_seq_mat,val_y))
            model.save('my_model.h6') 
        ## 开始预测
        test_pre = model.predict(text)
        ##计算混淆函数
        confm = metrics.confusion_matrix(argmax(test_pre,axis=1),argmax(value,axis=1))
        print(metrics.classification_report(argmax(test_pre,axis=1),argmax(value,axis=1)))
        return confm

    训练过程如下图所示。

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    为了更直观的表现结果,定义如下函数绘制图像。

    def plot_fig(matrix):
        Labname = [str(i) for i in range(14)]
        plt.figure(figsize=(8,8))
        sns.heatmap(matrix.T, square=True, annot=True,
                    fmt='d', cbar=False,linewidths=.8,
                    cmap="YlGnBu")
        plt.xlabel('True label',size = 14)
        plt.ylabel('Predicted label',size = 14)
        plt.xticks(arange(14)+0.5,Labname,size = 12)
        plt.yticks(arange(14)+0.3,Labname,size = 12)
        plt.show()
        return

    最后,只需要通过pandas读取csv文件,按照比例分为训练集、检验集和测试集(这里选用比例为15:2:3),即可完成全部的预测过程。

    def test_main():
        train_df = pd.read_csv("./data/train_set.csv",sep='\t',nrows=200000)
        train = train_df.iloc[0:150000,:]
        test = train_df.iloc[150000:180000,:]
        val = train_df.iloc[180000:,:]
        test_seq_mat,test_y = to_seq(test)
        Confm = test_file(test_seq_mat,test_y,train,val)
        plot_fig(Confm)

    在获得预测结果最高的一组参数的选取后,我们训练整个train_set文件,训练过程如下,训练之前需删除已有的训练文件(.h6),此函数中的test行可随意选取,只是为了满足test_file()函数的变量足够。此函数只是用于训练出学习效果最好的数据并储存。

    def train():
        train_df = pd.read_csv("./data/train_set.csv",sep='\t',nrows=200000)
        train = train_df.iloc[0:170000,:]
        test = train_df.iloc[0:10000,:]
        val = train_df.iloc[170000:,:]
        test_seq_mat,test_y = to_seq(test)
        Confm = test_file(test_seq_mat,test_y,train,val)
        plot_fig(Confm)

    在获得最优的训练数据后,我们就可以开始预测了。我们将竞赛中提供的测试集带入模型中,加载储存好的训练集进行预测,得到预测矩阵。再将预测矩阵中每一行的最大值转化为对应的标签,储存在输出列表中即可,最后将该列表写入'test_DL.csv'文件中上传即可。(如此生成的csv文件同上一个模型一样,需手动打开删除掉第一列)

    def pred_file():
        test_df = pd.read_csv('./data/test_a.csv')
        test_seq_mat = sequence.pad_sequences([i.split(' ') for i in tqdm(test_df['text'])],maxlen=max_len)
        
        inputs = Input(name='inputs',shape=[max_len])
        ## Embedding(词汇表大小,batch大小,每个新闻的词长)
        layer = Embedding(max_words+1,128,input_length=max_len)(inputs)
        layer = LSTM(128)(layer)
        layer = Dense(128,activation="relu",name="FC1")(layer)
        layer = Dropout(0.5)(layer)
        layer = Dense(14,activation="softmax",name="FC2")(layer)
        model = Model(inputs=inputs,outputs=layer)
        model.summary()
        model.compile(loss="categorical_crossentropy",optimizer=rmsprop_v2.RMSprop(),metrics=["accuracy"])
        model = load_model('my_model.h6')
        
        test_pre = model.predict(test_seq_mat)
    
        pred_result = [i.tolist().index(max(i.tolist())) for i in test_pre]
        res=pd.DataFrame()
        res['label']=pred_result
        res.to_csv('test_DL.csv')

    整理后,我们只需要注释掉对应的指令行即可进行训练或预测。

    #如果想要训练,取消下行注释,训练之前需先删除原训练文件(.h6)
    #train()
    
    #如果想要查看模型效果,取消下行注释(训练集:检验集:测试集=15:2:3)
    # test_main()
    
    #如果想预测并生成csv文件,取消下行注释
    # pred_file()

    3. 结果分析

    最终获得的混淆矩阵如下图所示,14个标签预测的正确率均达到了80%以上,有11个标签在90%以上,有6个标签在95%以上。

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    绘制出来的预测结果如下图所示,可见预测效果相当理想,每个标签的正确率都尤为可观,预测错误的文本数相比于总量非常少。

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    最终上传网站得到结果,F1值达90%以上,效果较好。

    Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类

    以上是“Python如何通过朴素贝叶斯和LSTM分别实现新闻文本分类”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程笔记行业资讯频道!


    推荐阅读
    • 通过使用CIFAR-10数据集,本文详细介绍了如何快速掌握Mixup数据增强技术,并展示了该方法在图像分类任务中的显著效果。实验结果表明,Mixup能够有效提高模型的泛化能力和分类精度,为图像识别领域的研究提供了有价值的参考。 ... [详细]
    • 从2019年AI顶级会议最佳论文,探索深度学习的理论根基与前沿进展 ... [详细]
    • Ihavetwomethodsofgeneratingmdistinctrandomnumbersintherange[0..n-1]我有两种方法在范围[0.n-1]中生 ... [详细]
    • PHP预处理常量详解:如何定义与使用常量 ... [详细]
    • 在本地环境中部署了两个不同版本的 Flink 集群,分别为 1.9.1 和 1.9.2。近期在尝试启动 1.9.1 版本的 Flink 任务时,遇到了 TaskExecutor 启动失败的问题。尽管 TaskManager 日志显示正常,但任务仍无法成功启动。经过详细分析,发现该问题是由 Kafka 版本不兼容引起的。通过调整 Kafka 客户端配置并升级相关依赖,最终成功解决了这一故障。 ... [详细]
    • 在前文探讨了Spring如何为特定的bean选择合适的通知器后,本文将进一步深入分析Spring AOP框架中代理对象的生成机制。具体而言,我们将详细解析如何通过代理技术将通知器(Advisor)中包含的通知(Advice)应用到目标bean上,以实现切面编程的核心功能。 ... [详细]
    • Node.js 教程第五讲:深入解析 EventEmitter(事件监听与发射机制)
      本文将深入探讨 Node.js 中的 EventEmitter 模块,详细介绍其在事件监听与发射机制中的应用。内容涵盖事件驱动的基本概念、如何在 Node.js 中注册和触发自定义事件,以及 EventEmitter 的核心 API 和使用方法。通过本教程,读者将能够全面理解并熟练运用 EventEmitter 进行高效的事件处理。 ... [详细]
    • 在处理大规模并发请求时,传统的多线程或多进程模型往往无法有效解决性能瓶颈问题。尽管它们在处理小规模任务时能提升效率,但在高并发场景下,系统资源的过度消耗和上下文切换的开销会显著降低整体性能。相比之下,Python 的 `asyncio` 模块通过协程提供了一种轻量级且高效的并发解决方案。本文将深入解析 `asyncio` 模块的原理及其在实际应用中的优化技巧,帮助开发者更好地利用协程技术提升程序性能。 ... [详细]
    • 本文提供了 RabbitMQ 3.7 的快速上手指南,详细介绍了环境搭建、生产者和消费者的配置与使用。通过官方教程的指引,读者可以轻松完成初步测试和实践,快速掌握 RabbitMQ 的核心功能和基本操作。 ... [详细]
    • 解决Only fullscreen opaque activities can request orientation错误的方法
      本文介绍了在使用PictureSelectorLight第三方框架时遇到的Only fullscreen opaque activities can request orientation错误,并提供了一种有效的解决方案。 ... [详细]
    • 单片微机原理P3:80C51外部拓展系统
        外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
    • poj 3352 Road Construction ... [详细]
    • 在《Python编程基础》课程中,我们将深入探讨Python中的循环结构。通过详细解析for循环和while循环的语法与应用场景,帮助初学者掌握循环控制语句的核心概念和实际应用技巧。此外,还将介绍如何利用循环结构解决复杂问题,提高编程效率和代码可读性。 ... [详细]
    • 超分辨率技术的全球研究进展与应用现状综述
      本文综述了图像超分辨率(Super-Resolution, SR)技术在全球范围内的最新研究进展及其应用现状。超分辨率技术旨在从单幅或多幅低分辨率(Low-Resolution, LR)图像中恢复出高质量的高分辨率(High-Resolution, HR)图像。该技术在遥感、医疗成像、视频处理等多个领域展现出广泛的应用前景。文章详细分析了当前主流的超分辨率算法,包括基于传统方法和深度学习的方法,并探讨了其在实际应用中的优缺点及未来发展方向。 ... [详细]
    • 当前,众多初创企业对全栈工程师的需求日益增长,但市场中却存在大量所谓的“伪全栈工程师”,尤其是那些仅掌握了Node.js技能的前端开发人员。本文旨在深入探讨全栈工程师在现代技术生态中的真实角色与价值,澄清对这一角色的误解,并强调真正的全栈工程师应具备全面的技术栈和综合解决问题的能力。 ... [详细]
    author-avatar
    手机用户2602922511
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有