贝叶斯做文本分类,代码实现数据处理

Posted 光英的记忆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贝叶斯做文本分类,代码实现数据处理相关的知识,希望对你有一定的参考价值。

import os
import time
import random
import jieba  #处理中文
import nltk # 处理英文
import sklearn
from sklearn.naive_bayes import MultinomialNB  #多项式模式贝叶斯   还有伯努利模式  混合模式
import numpy as np
import pylab as pl
import matplotlib.pyplot as plt
#划分数据集 api 
from sklearn.model_selection import train_test_split

from sklearn.externals import joblib



#粗暴的词去重

#文本处理  样本生成  读取文件 划分训练集合
"""
共9类  9个文件夹  每个文件夹有一系列文本  每个text是一个文本
C000008  C000010  C000013  C000014  C000016  C000020  C000022  C000023  C000024
每个文件夹下的是一些文本
10.txt  11.txt  12.txt  13.txt  14.txt  15.txt  16.txt  17.txt  18.txt  19.txt
传入文件夹路径  划分训练和测试集合  
"""
def text_processing(folder_path,test_size=0.2):
    foleder_list=os.listdir(folder_path)
    data_list=[]
    class_list=[]
    #print("foleder_list",len(foleder_list))
    
    #遍历文件夹
    for folder in foleder_list:
        new_folder_path=os.path.join(folder_path,folder)
        files=os.listdir(new_folder_path)
        #print("files",len(files))
        
        #遍历每个类别的文件夹
        for file in files:
            with open(os.path.join(new_folder_path,file),'r') as fp:
                raw=fp.read()
                # 对读到的文本进行Jieba分词
                jieba.enable_parallel(4)#开启结巴并行分词模式
                word_cut=jieba.cut(raw,cut_all=False)
                word_list=list(word_cut)
                jieba.disable_parallel()#关闭并行模式
                
                #将每个文本放入数据列表中
                """
                [
                []
                []
                ]
                """
                data_list.append(word_list)
                """
                C000008 财经
                C000010 IT
                C000013 健康
                C000014 体育
                C000016 旅游
                C000020 教育
                C000022 招聘
                C000023 文化
                C000024 军事
                将每个文本对应的文件夹的名称 存入类别列表  建立关联label

                """
                class_list.append(folder.encode('utf-8').decode('utf-8'))#类别 列表
                
    #划分数据集合
    train_data_list,test_data_list,train_class_list,test_class_list=train_test_split(data_list, class_list, test_size=test_size)
        
    # 统计词频数据
    """
    
    'word':1,
    
    """
    all_words_dict=
    for word_list in train_data_list:
        for word in word_list:
            if word in all_words_dict:
                all_words_dict[word]+=1
            else:
                all_words_dict[word]=1
                    
    #用Key韩式利用词频进行降序排序
    #print("all_words_dict.items():",all_words_dict.items())
    """
        all_words_dict.items(): dict_items([('\\u3000', 250), ('这是', 9), ('一次', 11), ('跨越', 1), ('世纪', 1), 
        ('的', 307), ('重逢', 1), (',', 374), ('弥补', 4), ('历史', 9), ('棋坛', 2), ('盛事', 1), ('。', 177), ('5', 6), ('月', 8), 
        ('23', 1), ('日至', 1), ('27', 1), ('日', 21), ('在', 97), ('美丽', 5), ('沈阳', 7), ('世博园', 5), ('来自', 1), ('中国', 9), 
        ('、', 30), ('日本', 3), ('和', 22), ('韩国', 6), ('三国', 4), ('九位', 2), ('当年', 2), ('叱咤', 1), ('世界', 5), ('围棋', 9), ('元老', 11), ('将', 20), ('上演', 1),
        ('对决', 2), ('昨天', 3), ('本次', 3), ('赛', 3), ('参赛者', 2), ('之一', 2), ('中国围棋协会', 3), ('主席', 2), 
        这个函数可以将字典转为元组
    """
    all_words_tuple_list=sorted(all_words_dict.items(),key=lambda f:f[1],reverse=True)#内建函数sorted参数为List
    """
        排序
    """
        #print("all_words_tuple_list:",all_words_tuple_list)
    all_words_list = list(list(zip(*all_words_tuple_list))[0])
        #print(all_words_list)
        #排序后的单词列表
    """
          ['&', 'nbsp', ';', ',', '的', '\\u3000', '。', '\\n', '在', '“', '”', ' ', '了', '我', '是', '他', '比赛', ':', '、',
          '对', '就', '说', '时', '—', '这', '3', '和', '1', '0', '阿里', '日', '我们', '纳斯', '上', '都', '也', '而', '还', 'VS', '/', '辽宁队',
    """
        
    return all_words_list,train_data_list,test_data_list,train_class_list,test_class_list
        

#加载停用词 并且去重
def make_word_set(words_file):
    word_set=set()
    with open(words_file,'r') as fp:
        for line in fp.readlines():
            word=line.strip().encode('utf-8').decode('utf-8')
            if len(word)>0 and word not in word_set:
                word_set.add(word)
                
    return word_set
                

    
#选取特征词语
def words_dict(all_words_list,deleteN,stopwords_set=set()):
    #选取特征词
    feature_words=[]
    n=1
    for t in range(deleteN,len(all_words_list),1):
        #每次选取1000个词
        if n>1000:
            break
        #Python isdigit() 方法检测字符串是否只由数字组成。
        #每次选出不是全数字  且不在停用词列表中 长度大于1小于5的1000分词  作为特征  
        if not all_words_list[t].isdigit()  and  all_words_list[t] not in stopwords_set and 1<len(all_words_list[t])<5:
            feature_words.append(all_words_list[t])
            n+=1
    return feature_words


#文本特征
def text_features(train_data_list,test_data_list,feature_words,flag='nltk'):
    def text_features(text,feature_words):
        text_words=set(text)
        if flag=='nltk':
            ##nltk 特征dict
            features=word:1 if word in text_words else 0 for word in feature_words
        elif flag == 'sklearn':
            #sklearn 特征list
            features=[1 if word in text_words else 0 for word in feature_words]
        else:
              features = []
            
        return features
    
    train_feature_list=[text_features(text,feature_words) for text in train_data_list]
    test_feature_list=[text_features(text,feature_words) for text in test_data_list]
    return train_feature_list,test_feature_list

#根据特征进行分类 并返回测试准确率
def text_classifier(train_feature_list,test_feature_list,train_class_list,test_class_list,flag='nltk'):
    if flag=='nltk':
        ##使用Nltk分类器
        train_flist=zip(train_feature_list,train_class_list)
        test_flist=zip(test_feature_list,test_class_list)
        classifier=nltk.classify.NaiveBayesClassifier.train(train_flist)
        test_accuracy=nltk.classify.accuracy(classifier,test_flist)
    elif flag=='sklearn':
        #sklearn 分类器
        classifier=MultinomialNB().fit(train_feature_list,train_class_list)
        test_accuracy=classifier.score(test_feature_list,test_class_list)
        # 保存模型
        joblib.dump(classifier,  "./贝叶斯文本分类.pkl")   # lr是训练好的模型, "./ML/test.pkl"是模型要保存的路径及保存模型的文件名,其中,'pkl' 是sklearn中默认的保存格式gai
    else:
        test_accuracy=[]
    return test_accuracy



print("start")
##开始文本处理
print("Start prosscess  loading file!!!")
folder_path="./Database/SogouC/Sample"
#111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
all_words_list,train_data_list,test_data_list,train_class_list,test_class_list=text_processing(folder_path,test_size=0.2)
print("all_words_list.length:",len(all_words_list))
print("train_data_list.length:",len(train_data_list))
print("test_data_list.length:",len(test_data_list))
"""
all_words_list.length: 10066
train_data_list.length: 72
test_data_list.length: 18
"""

#生成停用词语
#22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
stopwords_file='./stopwords_cn.txt'
stopwords_set=make_word_set(stopwords_file)

#文本特征提取和分类
#33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333
flag='sklearn'
deleteNs=range(0,1000,20)
test_accuracy_list=[]
#循环50次  每次
for deleteN in deleteNs:
    #444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
    #每次选出1000个不全是数字 去停用词的长度在1-5之间的1000个词作为特征词
    feature_words=words_dict(all_words_list,deleteN,stopwords_set)
    #555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555
    #根据所有词选出的1000个特征词  然后在训练集合中 将训练集合 和测试集合转为1000维度的特征   变量每个文本
    # 每个文本用1000维度的特征表示    出现则为1  没出现则为0  并且转为向量 
    
    train_feature_list,test_feature_list=text_features(train_data_list,test_data_list,feature_words,flag)
    #print(train_feature_list)
    #print(len(train_feature_list))
    #72个训练样本  18个测试样本
    #66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
    #开始训练 分类 并返回测试准确率
    test_accuracy = text_classifier(train_feature_list, test_feature_list, train_class_list, test_class_list, flag)
    #循环训练测试50次 
    test_accuracy_list.append(test_accuracy)
    
    
    """
    [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
    0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    """


print(test_accuracy_list)

# 从文件中加载模型进行预测   
lr = joblib.load("./贝叶斯文本分类.pkl")
# 进行模型的预测
import torch
y_pred = lr.predict([test_feature_list[0]])  # 加载出来的模型跟我们训练出来的模型一样,有相同的参数

#print(y_pred)
#['C000024']

"""
start
Start prosscess  loading file!!!
all_words_list.length: 9960
train_data_list.length: 72
test_data_list.length: 18
[0.7777777777777778, 0.7222222222222222, 0.7222222222222222, 0.6666666666666666,
0.6111111111111112, 0.6111111111111112, 0.6111111111111112, 0.6666666666666666, 
0.6666666666666666, 0.6666666666666666, 0.6666666666666666, 0.7222222222222222, 
0.7222222222222222, 0.7222222222222222, 0.7222222222222222, 0.7222222222222222, 
0.7222222222222222, 0.7222222222222222, 0.7222222222222222, 0.7222222222222222, 
0.7222222222222222, 0.6666666666666666, 0.6666666666666666, 0.6666666666666666, 
0.6666666666666666, 0.6111111111111112, 0.6111111111111112, 0.6666666666666666, 
0.6111111111111112, 0.6666666666666666, 0.6111111111111112, 0.6111111111111112, 
0.5555555555555556, 0.5555555555555556, 0.5, 0.4444444444444444, 0.4444444444444444, 
0.4444444444444444, 0.4444444444444444, 0.5, 0.5, 0.5, 0.4444444444444444, 0.4444444444444444,
0.4444444444444444, 0.4444444444444444, 0.4444444444444444, 0.4444444444444444, 0.4444444444444444, 0.4444444444444444]
['C000024']

为啥准确率一直在下降    

可能因为特征工程 选取特征词语的词频  是不断下降的  一开始的准确率有77 这个准确率还是可以的
"""

 

以上是关于贝叶斯做文本分类,代码实现数据处理的主要内容,如果未能解决你的问题,请参考以下文章

使用朴素贝叶斯做多分类

朴素贝叶斯实现文本分类

21丨朴素贝叶斯分类(下):如何对文档进行分类?

基于朴素贝叶斯分类器的情感分析

贝叶斯分类

贝叶斯分类小结