zoukankan      html  css  js  c++  java
  • 【自然语言处理】利用朴素贝叶斯进行新闻分类(自己处理数据)

    读完这篇博文,你能够收获什么?

    • 从数据处理到利用朴素贝叶斯进行分类的整个过程
    • 本文更关注于数据处理阶段,朴素贝叶斯模型直接使用sklearn库中自带的

    先给出整个算法的流程:

     采用的是sogou语料库的部分数据,每个C开头的文件各代表一类,里面包含着若干篇txt类型的文章,具体类别如下:

    1.数据审视阶段(查看是否有不符合规范或异常的数据),由于我们这里的数据是比较规整的,就直接进行下一阶段了;

    2.要想训练一个模型,我们必须得有训练集和测试集。我们要明确训练集和测试集里面是什么。这里,我们使用的是词袋,即包含有不同单词的列表。

    首先导入相应的包:

    #用于处理文件路径
    import os
    #用于打乱数据,产生随机的训练集和测试集
    import random
    #用于分词
    import jieba
    #朴素贝叶斯模型
    from sklearn.naive_bayes import MultinomialNB

    然后是词袋模型的建立:

    def data_process():
        #获取当前文件的绝对路径
        cur_path = os.path.dirname(os.path.abspath(__file__))
        #定位包含数据的那级目录
        path = cur_path + '/Database/SogouC/Sample/'
        #测试集占总数据的百分比
        test_size = 0.2
        #Sample下的所有文件
        folder_list = os.listdir(path)
        #存储分词后的列表
        data_list =[]
        #存储标签列表
        class_list = []
        #遍历C000008等类型的文件夹
        for folder in folder_list:
            #取得该文件夹绝对路径
            new_folder_path = os.path.join(path,folder)
            #取得该文件夹下所有txt类型的数据,并返回
            files=os.listdir(new_folder_path)
            #读取txt文件
            for file in files:
                #打开txt文件
                with open(os.path.join(new_folder_path,file),'r',encoding='utf-8') as fp:
                    #读取里面的内容
                    raw = fp.read()
                    #进行结巴分词
                    word_cut=jieba.cut(raw,cut_all=False)
                    #将分词后的结果转成列表,即单词列表
                    word_list=list(word_cut)
                    #将该文件夹下的所有txt分词后添加到data_list中
                    data_list.append(word_list)
                    #获得标签列表,就是文件夹名称
                    class_list.append(folder)
        #将分词列表和标签对应并返回
        data_class_list = list(zip(data_list,class_list))
        #打乱数据以获得随机的训练集和测试集
        random.shuffle(data_class_list)
        #通过索引来切分数据
        index = int(len(data_class_list)*test_size)+1
        #训练集(包含数据和标签)
        train_list=data_class_list[index:]
        #测试集(包含数据和标签
        test_list=data_class_list[:index]
        #拆分
        train_data_list,train_class_list=zip(*train_list)
        #拆分
        test_data_list,test_class_list=zip(*test_list)
        #取得所有文章分词后构成的词袋
        all_words_dict ={}
        #取得训练集中的每一篇分词后的列表
        for word_list in  train_data_list:
            #取得每一个单词
            for word in word_list:
                #判断是否存在于词袋中,如果没有,则出现次数为1,否则+1
                if word in all_words_dict:
                    all_words_dict[word]+=1
                else:
                    all_words_dict[word]=1
        #将所有词语按出现次数由大到小排列
        all_words_tuple_dict=sorted(all_words_dict.items(),key=lambda x:x[1],reverse=True)
        #取出单词,并转为列表
        all_words_list=list(list(zip(*all_words_tuple_dict))[0])
        #返回词袋,训练集,训练集标签,测试集,测试集标签
        return all_words_list,train_data_list,train_class_list,test_data_list,test_class_list

    我们虽然得到了词袋模型,但是,我们发现里面的词并不是我们所需要的,我们还要进行下一步操作:去除一些不必要的词和一些没有意义的词,这里得用到stopwods_cn.txt:

     上图展示的是部分停用词。首先,我们必须从txt中获得停用词列表:

    def get_stopwords_cn():
        stopwords_cn_path = os.path.dirname(os.path.abspath(__file__)) + "\stopwords_cn.txt"
        with open(stopwords_cn_path,'r',encoding='utf-8') as fp:
            stopwords_cn=fp.read().split("
    ")
        return set(stopwords_cn)

    然后,我们词袋中的每一个单词,如果不在停用词中,就加入到新的列表中:

    def word_dicts(all_words_list,deleteN,stopwords_set=set()):
        #用来存储不位于停词中的单词
        features_words=[]
        #用于指定词袋的长度
        n=1
        for t in range(deleteN,len(all_words_list),1):
         #限定词袋的长度为1000
    if n>1000: break #如果不是数字且不在停词列表中且1<长度<5 if not all_words_list[t].isdigit() and all_words_list[t] not in stopwords_set and 1<len(all_words_list[t])<5: #加入到新的词袋中 features_words.append(all_words_list[t]) n+=1 return features_words

    接下来,我们得到修正过后的词袋后,还需要将原本文章的分词列表转换成One-hot编码,这才是我们真正需要的特征:

    def text_features(train_data_list,test_data_list,features_words):
        #text是每一条train_data_list中或test_data_list的数据
        #辅助函数
        def helper(text,features_words):
            #首先过滤掉重复的值
            text_words = set(text)
            #如果该词位于词袋中,则编码成1,否则为0
            features = [1 if word in text_words else 0 for word in features_words]
            return features
        #对训练集进行编码
        train_feature_list=[helper(text,features_words) for text in train_data_list]
        #对测试集进行编码
        test_feature_list = [helper(text, features_words) for text in test_data_list]
        #返回新的特征
        return train_feature_list,test_feature_list

    我们已经拥有特征了,最后需要定义朴素贝叶斯模型:

    def text_classifier(train_feature_list,train_class_list,test_feature_list,test_class_list):
        classifier = MultinomialNB().fit(train_feature_list,train_class_list)
        test_accuracy=classifier.score(test_feature_list,test_class_list)
        print(classifier.predict(test_feature_list))
        print(test_class_list)
        return test_accuracy

    最后,将所有部件组合起来,就大功告成了:

    def main():
        all_words_list, train_data_list, train_class_list, test_data_list, test_class_list = data_process()
        #去除掉停用词
        features_words = word_dicts(all_words_list,0,get_stopwords_cn())
        train_feature_list, test_feature_list=text_features(train_data_list,test_data_list,features_words)
        accuracy = text_classifier(train_feature_list,train_class_list,test_feature_list,test_class_list)
        print(accuracy)
    if __name__ == '__main__':
        main()

    我们来看下输出:

     由于只是个较为基础的实现,所以准确率并不算太高,最主要的还是掌握整个过程。虽然代码比较多,但是画了流程图和基本上都会有注释,看起来应该会简单些。

    相关代码和资料:链接: https://pan.baidu.com/s/1odwgJ8Vy_h1QyMrWpsi68Q 提取码: d74g 

  • 相关阅读:
    自我介绍
    汇编实验报告五
    汇编第二章知识总结
    汇编第一章知识总结
    汇编实验报告四
    汇编实验报告三
    汇编实验报告(二)
    汇编实验报告(一)
    实验报告(七)
    实验报告(六)
  • 原文地址:https://www.cnblogs.com/xiximayou/p/11861018.html
Copyright © 2011-2022 走看看