朴素贝叶斯--新浪新闻分类实例

对于英文的语句可以通过非字母和非数字进行切分,但是汉语中的一句话该如何进行切分呢?我们可以直接使用第三方分词组件,即jieba来实现分词。

安装

pip install jieba

在这里插入图片描述

切分中文语句

import os
import jieba

def TextProcessing(folder_path):
    folder_list = os.listdir(folder_path)                        #查看folder_path下的文件
    data_list = []                                                #训练集
    class_list = []

    #遍历每个子文件夹
    for folder in folder_list:
        new_folder_path = os.path.join(folder_path, folder)        #根据子文件夹,生成新的路径
        files = os.listdir(new_folder_path)                        #存放子文件夹下的txt文件的列表

        j = 1
        #遍历每个txt文件
        for file in files:
            if j > 100:                                            #每类txt样本数最多100个
                break
            with open(os.path.join(new_folder_path, file), 'r', encoding = 'utf-8') as f:    #打开txt文件
                raw = f.read()

            word_cut = jieba.cut(raw, cut_all = False)            #精简模式,返回一个可迭代的generator
            word_list = list(word_cut)                            #generator转换为list

            data_list.append(word_list)
            class_list.append(folder)
            j += 1
        print(data_list)
        print(class_list)
if __name__ == '__main__':
    #文本预处理
    folder_path = './SogouC/Sample'                #训练集存放地址
    TextProcessing(folder_path)

运行结果:

Building prefix dict from the default dictionary ...
Dumping model to file cache C:\Users\mlj\AppData\Local\Temp\jieba.cache
Loading model cost 0.824 seconds.
Prefix dict has been built succesfully.
[['\u3000', '\u3000', '本报记者', '陈雪频', '实习', '记者', '唐翔', '发自', '上海', '\n', '\u3000', '\u3000', '一家', '刚刚', '成立', '两年', '的', '网络', '支付', '公司', 
',', '它', '的', '目标', '是', '成为', '市值', '100', '亿美元', '的', '上市公司', '。', '\n', '\u3000', '\u3000', '这家', '公司', '叫做', '快', '钱', ',', '说', '这句', '话', '的', 
'是', '快', '钱', '的', 'CEO', '关国光', '。', '他', '之前', '曾任', '网易', '的', '高级', '副总裁', ',', '负责', '过', '网易', '的', '上市', '工作', '。', '对于', '为什么', '选择', 
'第三方', '支付', '作为', '创业', '方向', ',', '他', '曾经', '对', '媒体', '这样', '说', ':', '“', '我能', '看到', '这个', '胡同', '对面', '是', '什么', ',', '别人', '只能', '看到', 
'这个', '胡同', '。', '”', '自信', '与', '狂妄', '只有', '一步之遥', '—', '—', '这', '几乎', '是', '所有', '创业者', '的', '共同', '特征', ',', '是', '自信', '还是', '狂妄', '也许', 
'需要', '留待', '时间', '来', '考证', '。', '\n', '\u3000', '\u3000', '对于', '市值', '100', '亿美元', '的', '上市公司', ',', '他', '是', '这样', '算', '这笔', '账', '的', ',', '“', 
'百度', '上市', '时', '广告', '客户', '数量', '只有', '4', '万', ',', '而且', '它', '所', '做', '的', '只是', '把', '客户', '吸引', '过来', ',', '就', '可以', '支撑', '起', '现有', '的', 
'庞大', '市值', ';', '而', '我们', '几年', '后', '的', '客户', '数量', '是', '几千万', ',', '而且', '这些', '客户', '都', '是', '能', '直接', '带来', '利润', '的', ',', '说', '市值', '100', '亿美元', '一点', '都', '不', '夸张', '。', '”', '\n', '\u3000', '\u3000', '这家', '公司', '2005', '年', '年底', '注册', '用户', '达到', '400', '万', ',', '计划', '今年', '注
册', '用户', '突破', '1000', '万', ',', '号称', '是', '国内', '最大', '的', '第三方', '网络', '支付', '平台', '。', '“', '在', '美国', '跟', '支付', '相关', '的', '收入', '已经', '超
过', '了', '所有', '商业银行', '本身', '利差', '收入', '的', '总和', ',', '我', '所查', '到', '的', '数据', '是', '3000', '亿美元', ',', '其中', '超过', '70', '%', '是', '个人', 
...
...
...
...
'获得', '军队', '指挥官', '的', '同情', ',', '他们', '认为', ',', '低腰裤', '严重威胁', '着', '以军', '的', '纪律', '基础', '。', '\n', '\u3000', '\u3000', '以军', '要求', '女
兵', '们', '把', '那些', '改过', '的', '低腰裤', '交到', '军需', '商店', ',', '以', '换回', '符合规定', '的', '军裤', '。', '此外', ',', '目前', '已经', '约', '有', '120', '名', '女
兵', '因', '穿着', '违规', '低腰裤', '而', '被', '关禁闭', '。', '\u3000']]
['C000008', 'C000008', 'C000008', 'C000008', 'C000008', 'C000008', 'C000008', 'C000008', 'C000008', 'C000008', 'C000010', 'C000010', 'C000010', 
'C000010', 'C000010', 'C000010', 'C000010', 'C000010', 'C000010', 'C000010', 'C000013', 'C000013', 'C000013', 'C000013', 'C000013', 'C000013', 
'C000013', 'C000013', 'C000013', 'C000013', 'C000014', 'C000014', 'C000014', 'C000014', 'C000014', 'C000014', 'C000014', 'C000014', 'C000014', 
'C000014', 'C000016', 'C000016', 'C000016', 'C000016', 'C000016', 'C000016', 'C000016', 'C000016', 'C000016', 'C000016', 'C000020', 'C000020', 
'C000020', 'C000020', 'C000020', 'C000020', 'C000020', 'C000020', 'C000020', 'C000020', 'C000022', 'C000022', 'C000022', 'C000022', 'C000022', 
'C000022', 'C000022', 'C000022', 'C000022', 'C000022', 'C000023', 'C000023', 'C000023', 'C000023', 'C000023', 'C000023', 'C000023', 'C000023', 
'C000023', 'C000023', 'C000024', 'C000024', 'C000024', 'C000024', 'C000024', 'C000024', 'C000024', 'C000024', 'C000024', 'C000024']

文本特征选择

将所有文本分成训练集和测试集,并对训练集中的所有单词进行词频统计,并按降序排序。也就是将出现次数多的词语在前,出现次数少的词语在后进行排序。

import os
import random
import jieba

"""
函数说明:中文文本处理

Parameters:
    folder_path - 文本存放的路径
    test_size - 测试集占比,默认占所有数据集的百分之20
Returns:
    all_words_list - 按词频降序排序的训练集列表
    train_data_list - 训练集列表
    test_data_list - 测试集列表
    train_class_list - 训练集标签列表
    test_class_list - 测试集标签列表
"""
def TextProcessing(folder_path, test_size = 0.2):
    folder_list = os.listdir(folder_path)                        #查看folder_path下的文件
    data_list = []                                                #数据集数据
    class_list = []                                                #数据集类别

    #遍历每个子文件夹
    for folder in folder_list:
        new_folder_path = os.path.join(folder_path, folder)        #根据子文件夹,生成新的路径
        files = os.listdir(new_folder_path)                        #存放子文件夹下的txt文件的列表

        j = 1
        #遍历每个txt文件
        for file in files:
            if j > 100:                                            #每类txt样本数最多100个
                break
            with open(os.path.join(new_folder_path, file), 'r', encoding = 'utf-8') as f:    #打开txt文件
                raw = f.read()

            word_cut = jieba.cut(raw, cut_all = False)            #精简模式,返回一个可迭代的generator
            word_list = list(word_cut)                            #generator转换为list

            data_list.append(word_list)                            #添加数据集数据
            class_list.append(folder)                            #添加数据集类别
            j += 1

    data_class_list = list(zip(data_list, class_list))            #zip压缩合并,将数据与标签对应压缩
    random.shuffle(data_class_list)                                #将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:
            if word in all_words_dict.keys():
                all_words_dict[word] += 1
            else:
                all_words_dict[word] = 1

    #根据键的值倒序排序
    all_words_tuple_list = sorted(all_words_dict.items(), key = lambda f:f[1], reverse = True)
    all_words_list, all_words_nums = zip(*all_words_tuple_list)    #解压缩
    all_words_list = list(all_words_list)                        #转换成列表
    return all_words_list, train_data_list, test_data_list, train_class_list, test_class_list

if __name__ == '__main__':
    #文本预处理
    folder_path = './SogouC/Sample'                #训练集存放地址
    all_words_list, train_data_list, test_data_list, train_class_list, test_class_list = TextProcessing(folder_path, test_size=0.2)
    print(all_words_list)

运行结果:

Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\mlj\AppData\Local\Temp\jieba.cache
Loading model cost 0.746 seconds.
Prefix dict has been built succesfully.
[',', '的', '\u3000', '。', '\n', ';', '&', 'nbsp', ' ', '、', '在', '了', '是', '“', '”', '和', ':', '也', '我', '有', '就', '对', '上', '为', '这', '将', '—', '他', '公司', '中', '而', '月', '不', 、'要', '都', '年', '你', '与', '一个', '(', ')', '中国', '自己', '可以', '考生', '日', ';', '从', '导弹', '等', '大陆', '到', '人', '3', '.', '(', ')', '火炮', '台军', '个', '时', '进行', 
'会', '时间', '多', '认为', '北京', '1', '但', '5', '市场', '以', '志愿', '一种', '0', '说', '让', '新', '各种', '解放军', '没有', '旅游', '能', '企业', '后', '已经', '游客', '美国', 
'大', '[', ']', '把', '并', '被', '%', '来', '还', '更', '作战', '地', '用', '《', '》', '2', '做', '成为', '药', '复习', '很', '仿制', ',', '这样', '下', '4', '学校', '大家', '9', '很多', '选择', 
'-', '主要', '如果', '最', '分析', '目前', '小', '工作', '问题', '一定', '10', '6', '前', '可', '远程', '又', '我们', '品牌', '这些', '射程', '可能', '去', '给', '通过', '时候', '看', '考
试', '基础', '使', '亿美元', '上海', '?', '2', '词汇', '辅导班', '家', '该', '专业', '完全', '文章', '部分', '部署', '需要', '就是', '能力', '因为', '快', '0', '他们', '黄金周', 
'好', '毕业生', '五一', '增长', '钱', '填报', '16', '着', '8', '一', '一些', '2005', '技术', '学习', '支付', '.', '/', 'VS', '袁', '比', '其中', '重要', '专家', '由', '那些', '但是', 
'过', '她', '7', '由于', '接待', '这个', '计划', '表示', '它', '其', '所以', '银行', '阵地', '期间', '比较', '万人次', '收入', '向', '资料', '60', '影响', '分', '用户', '坦克', '设
计', '为了', '出', '电话', '于', '只有', '其他', '2006', '管理', '得', '产品', '所', '要求', '销售', '1', '根据', '训练', '拥有', '今年', '表现', '相对', '老师', '必须', '对于', 
'或', '新浪', '当', '开始', '同时', '作为', '提高', '则', '阅读', '讲', '使用', '00', '网络', '军事', '发现', '不是', '据', '来源', '却', '发展', '30', '项目', '重点', '写作', '一旦', 
...
...
...
'成就', '由衷', '地替', '感到高兴', '焦点', '个股', '002024', '该股', '开盘', '其后', '获利盘', '压下', '买盘', '下该', '股', '封于', '可见', '拉升', '盘面', '层面', '小幅', 
'探低', '回升', '上扬', '翻红', '之强', '瞠目结舌', '繁荣', '需谨慎', '必竟', '上攻', '消耗', '动能', '退温', '外扩散', '活跌', '有色金属', '地产股', '向外', '军工', '航天
航空', '规避', '技术性', '回调', '追高']

一个简单的规则可以这样制定:首先去掉高频词,至于去掉多少个高频词,我们可以通过观察去掉高频词个数和最终检测准确率的关系来确定。除此之外,去除数字,不把数字作为分类特征。同时,去除一些特定的词语,比如:”的”,”一”,”在”,”不”,”当然”,”怎么”这类的对新闻分类无影响的介词、代词、连词。怎么去除这些词呢?可以使用已经整理好的stopwords_cn.txt文本。下
载地址:https://github.com/Jack-Cherish/Machine-Learning/blob/master/Naive%20Bayes/stopwords_cn.txt

我们可以根据这个文档,将这些单词去除,不作为分类的特征。我们先去除前100个高频词汇,然后编写代码如下:

import os
import random
import jieba

"""
函数说明:中文文本处理

Parameters:
    folder_path - 文本存放的路径
    test_size - 测试集占比,默认占所有数据集的百分之20
Returns:
    all_words_list - 按词频降序排序的训练集列表
    train_data_list - 训练集列表
    test_data_list - 测试集列表
    train_class_list - 训练集标签列表
    test_class_list - 测试集标签列表
"""
def TextProcessing(folder_path, test_size = 0.2):
    folder_list = os.listdir(folder_path)                        #查看folder_path下的文件
    data_list = []                                                #数据集数据
    class_list = []                                                #数据集类别

    #遍历每个子文件夹
    for folder in folder_list:
        new_folder_path = os.path.join(folder_path, folder)        #根据子文件夹,生成新的路径
        files = os.listdir(new_folder_path)                        #存放子文件夹下的txt文件的列表

        j = 1
        #遍历每个txt文件
        for file in files:
            if j > 100:                                            #每类txt样本数最多100个
                break
            with open(os.path.join(new_folder_path, file), 'r', encoding = 'utf-8') as f:    #打开txt文件
                raw = f.read()

            word_cut = jieba.cut(raw, cut_all = False)            #精简模式,返回一个可迭代的generator
            word_list = list(word_cut)                            #generator转换为list

            data_list.append(word_list)                            #添加数据集数据
            class_list.append(folder)                            #添加数据集类别
            j += 1

    data_class_list = list(zip(data_list, class_list))            #zip压缩合并,将数据与标签对应压缩
    random.shuffle(data_class_list)                                #将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:
            if word in all_words_dict.keys():
                all_words_dict[word] += 1
            else:
                all_words_dict[word] = 1

    #根据键的值倒序排序
    all_words_tuple_list = sorted(all_words_dict.items(), key = lambda f:f[1], reverse = True)
    all_words_list, all_words_nums = zip(*all_words_tuple_list)    #解压缩
    all_words_list = list(all_words_list)                        #转换成列表
    return all_words_list, train_data_list, test_data_list, train_class_list, test_class_list

"""
函数说明:读取文件里的内容,并去重

Parameters:
    words_file - 文件路径
Returns:
    words_set - 读取的内容的set集合
"""
def MakeWordsSet(words_file):
    words_set = set()                                            #创建set集合
    with open(words_file, 'r', encoding = 'utf-8') as f:        #打开文件
        for line in f.readlines():                                #一行一行读取
            word = line.strip()                                    #去回车
            if len(word) > 0:                                    #有文本,则添加到words_set中
                words_set.add(word)                               
    return words_set                                             #返回处理结果

"""
函数说明:文本特征选取

Parameters:
    all_words_list - 训练集所有文本列表
    deleteN - 删除词频最高的deleteN个词
    stopwords_set - 指定的结束语
Returns:
    feature_words - 特征集
"""
def words_dict(all_words_list, deleteN, stopwords_set = set()):
    feature_words = []                            #特征列表
    n = 1
    for t in range(deleteN, len(all_words_list), 1):
        if n > 1000:                            #feature_words的维度为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:
            feature_words.append(all_words_list[t])
        n += 1
    return feature_words

if __name__ == '__main__':
    #文本预处理
    folder_path = './SogouC/Sample'                #训练集存放地址
    all_words_list, train_data_list, test_data_list, train_class_list, test_class_list = TextProcessing(folder_path, test_size=0.2)

    #生成stopwords_set
    stopwords_file = './stopwords_cn.txt'
    stopwords_set = MakeWordsSet(stopwords_file)

    feature_words = words_dict(all_words_list, 100, stopwords_set)
    print(feature_words)

运行结果:

['黄金周', '目前', '企业', '支付', '增长', '仿制', '复习', '主要', '成为', '五一', '工作', '发展', '学校', '比赛', '远程', '可能', '很多', '分析', '通过', '射程', '接待', '技
术', '完全', '作战', '万人次', '记者', '时候', '基础', '亿美元', '建设', '选择', '部署', '辅导班', '期间', '电话', '问题', '表示', '上海', '专业', '能力', '毕业生', '今年', 
'重要', '收入', '比较', '填报', '达到', '训练', '使用', '一定', '部队', 'VS', '开始', '拥有', '表现', '情况', '几乎', '现在', '军事', '销售', '用户', '项目', '人数', '发现', '需
要', '资料', '相对', '服务', '科学', '提高', '希望', '坦克', '最大', '阵地', '文章', '管理', '影响', '专家', '学习', '参加', '活动', '日本', '提供', '网络', '这是', '来源', '实
验室', '重点', '东莞', '英语', '印度', '考古', '一次', '装备', '专利', '一直', '人才', 'MBA', '考试', '计划', '招聘', '大批', '公里', '一家', '要求', '数字', '阿里', '耿大勇', 
'岛屿', '词汇', '最后', '去年', '相关', '孩子', '不用', '协议', '不同', '彻底', '不能', '机会', '压制', '游戏', '睡眠', '沿海', '角度', '摧毁', '显示', '产品', '不会', '台湾', 
'设计', '知道', '新型', '非常', '行业', '出现', '准备', '系统', '一批', '全军', '数学', '阅读', '全国', '国家', '了解', '大学生', '方式', '数独', '置于', '距离', '挑衅', '两个', 
'告诉', '看到', '左右', '进入', '考虑', '必须', '注意', '作用', '历史', '大学', '国内', '排名', '医院', '纳斯', '我国', '自寻死路', '世界领先', '型号', '开战', '金贵', '海量', 
'之内', '费多', '力气', '廉价', '发展观', '景区', '全面', '目标', '部分', '完成', '药厂', '预期', '经济', '战场', '平台', '地方', '老师', '沈阳市', '介绍', '广东', '这种', '牛
奶', '包括', '决定', '手机', '此前', '是否', '知识', '连续', '增加', '方面', '我军', '录取', '止痛药', '东引岛', '军队', '明显', '特别', '景点', '最佳', '大量', '第一次', '获
得', '应该', '基本', '网上', '不断', '知识点', '建议', '旅行社', '南京', '这家', '越来越', '复试', '分期付款', '考研', '语法', '香港', '数量', '推出', '成功', '概念', '理由', 
'事情', '正在', '结果', '交易', '代表', '未来', '药物', '之后', '价值', '愿意', '容易', '条件', '理解', '吸引', '超过', '世界', '对手', '设立', '消息', '营养', '镇痛药', '武器', 
'辽宁队', '本场', '同比', '消费', '特点', '图库', '第一', '帮助', '领导', '上市', '研究', '组织', '得到', '掌握', '全球', '社会', '支持', '学员', '实现', '利用', '文化', '万元', 
'业务', '著名', '知名', '詹姆斯', '能够', '利苑', '埃及', '院校', '王治郅', '回家', '亿元', '休闲', '思路', '不要', '根本', '整个', '上午', '一年', '发布', '稳定', '最近', '数
据', '内容', '指挥', '信息化', '功能', '电子', '各型', '水平', '过程', '其实', '应用', '报道', '更加', '不少', '喜欢', '客场', '简历', '教育', '患者', '电脑', '免息', '句子', 
'昨天', '市民', '有限公司', '一位', '这次', '感觉', '再次', '一下', '过年', '感到', '发生', '当时', '具有', '国际', '一场', '指出', '调查', '赔偿', '之间', '制药', '领域', '原
因', '医疗', '职业', '银行', '关注', '参与', '往往', '平时', '每个', '经验', '我省', '关国光', '之前', '结束', '伯德', '姚明', '过去', '提前', '补充', '今天', '分公司', '面试', 
'治疗', '公布', '疼痛', '备考', '方向', '振保', '三个', '取得', '努力', '一起', '预计', '加强', '信息', '实施', '传统', '找到', '解题', '公式', '一般', '形成', '韩国', '元老', 
'运动', '生活', '工程', '口技', '主场', '最好', '酒家', '食物', '标题', '翻译', '下载', '网站', '女士', '去年同期', '泰国', '失眠', '密码', '批次', '本科', '火力', '评选', '遗
址', '晋升', '开通', '起来', '小时', '同事', '同学', '集团', '每股', '价格', '战争', '欧洲', '环境', '培训', '文物', '医药', '统计', '主动', '发出', '压力', '这一', '状态', '战
斗', '官兵', '综合', '进攻', '中心', '培养', '促进', '题型', '关系', '以下', '每天', '求职', '标准', '跨国公司', '第三方', '客户', '面对', '保证', '合作', '三分', '胜利', '第
二', '教材', '坚持', '很快', '很大', '十分', '法国', '规则', '总部', '俄罗斯', '广播', '吸收', '家长', '补报', '升旗', '新浪', '听课', '写作', '关键字', '美国在线', '东部', 
'内容摘要', '电视', '负责人', '时代', '乡村', '出游', '出境游', '下降', '回到', '实力', '意味着', '变得', '一样', '充足', '城市', '发挥', '优势', '基地', '模拟', '销售额', 
'共同', '先后', '平均', '力量', '敏华', '留下', '充分', '联系', '突出', '方法', '参看', '矩阵', '同期', '提升', '旅游者', '负责', '沈阳', '围棋', '首次', '产生', '职位', '上年', 
'规模', '学生', '第三', '刚刚', '网上支付', '因素', '效果', '创造', '米勒', '罚球', '采取', 'NBA', '困难', '月份', '巨大', '埃弗顿', '俱乐部', '研究所', '骗局', '有点', '举
办', '旅游业', '万人', '人体', '可选报', '阿片类', '吸烟', '戒烟', 'gt', '国防', '辽足', '马林', '唐尧东', '初盘', '场位', '需求', '各地', '地区', '相比', '集中', '联想', '最
高', '提出', '一页', '相当', '迅速', '几天', '简单', '年前', '机票', '感受', '避免', '真正', '签订', '年度', '双方', '高级', '生产', '竞争', '练习', '主题', '展开', '经常', '开
展', '商业', '购买', '空间', '更是', '泰华', '快速', '几年', '阶段', '有望', '收益', '经理', '年代', '战略', '增强', '正式', '经营', '直接', '宣布', '这部分', '比例', '尤其', 
'相互', '关键', '固定', '几个', '概率', '性质', '考题', '有效', '投诉', '进一步', '团队', '两年', '之一', '举行', '迎来', '经典', '不足', '从事', '优秀', '突破', '工具', '安全
性', '运用', '预测', '攻击', '连队', '荷兰', '足彩', '联赛', '佛罗伦萨', '切沃', '表明', '广州', '单位', '必要', '半导体', '搜索', '身高', '生长', '国旗', '短程', '战术导弹', 
'点穴', '改革', '海上', '业绩', '安妮', '呼叫', '汪力', '费用', '女兵', '家教', '精读', '本书', '高清晰', '成立', '红玫瑰', '白玫瑰', '指导', '语言', '重新', '变成', '积极', 
'操作', '持续', '春节', 'www', '真的', '汽车', '下来', '七天', '表演', '兄弟', '批准', '战术', '报告', '程度', '一半', '继续', '类似', '导致', '生物制药', '生物', '制剂', '增
幅', '市营率', '分钟', '地位', '推荐', '担任', '本报', '来到', '学院', '各级', '精神', '结合', '理论', '学科', '资源', '注重', '查询', '责任', '总结', '每年', '相当于', '说明', 
'线性代数', '自然', '事件', '好好', '函数', '考前', '辅导书', '最终', '机制', '门票', '带来', '商机', '陈祖德', '即将', '本报记者']

我们已经滤除了那些没有用的词组,这个feature_words就是我们最终选出的用于新闻分类的特征。随后,我们就可以根据feature_words,将文本向量化,然后用于训练朴素贝叶斯分类器。

分类器的测试

# -*- coding: UTF-8 -*-
from sklearn.naive_bayes import MultinomialNB
import matplotlib.pyplot as plt
import os
import random
import jieba

"""
函数说明:中文文本处理

Parameters:
	folder_path - 文本存放的路径
	test_size - 测试集占比,默认占所有数据集的百分之20
Returns:
	all_words_list - 按词频降序排序的训练集列表
	train_data_list - 训练集列表
	test_data_list - 测试集列表
	train_class_list - 训练集标签列表
	test_class_list - 测试集标签列表
Author:
	Jack Cui
Blog:
	http://blog.csdn.net/c406495762
Modify:
	2017-08-22
"""
def TextProcessing(folder_path, test_size = 0.2):
	folder_list = os.listdir(folder_path)						#查看folder_path下的文件
	data_list = []												#数据集数据
	class_list = []												#数据集类别

	#遍历每个子文件夹
	for folder in folder_list:
		new_folder_path = os.path.join(folder_path, folder)		#根据子文件夹,生成新的路径
		files = os.listdir(new_folder_path)						#存放子文件夹下的txt文件的列表
		
		j = 1
		#遍历每个txt文件
		for file in files:
			if j > 100:											#每类txt样本数最多100个
				break
			with open(os.path.join(new_folder_path, file), 'r', encoding = 'utf-8') as f:	#打开txt文件
				raw = f.read()
			
			word_cut = jieba.cut(raw, cut_all = False)			#精简模式,返回一个可迭代的generator
			word_list = list(word_cut)							#generator转换为list
			
			data_list.append(word_list)							#添加数据集数据
			class_list.append(folder)							#添加数据集类别
			j += 1

	data_class_list = list(zip(data_list, class_list))			#zip压缩合并,将数据与标签对应压缩
	random.shuffle(data_class_list)								#将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:
			if word in all_words_dict.keys():
				all_words_dict[word] += 1
			else:
				all_words_dict[word] = 1
	
	#根据键的值倒序排序
	all_words_tuple_list = sorted(all_words_dict.items(), key = lambda f:f[1], reverse = True)
	all_words_list, all_words_nums = zip(*all_words_tuple_list)	#解压缩
	all_words_list = list(all_words_list)						#转换成列表
	return all_words_list, train_data_list, test_data_list, train_class_list, test_class_list

"""
函数说明:读取文件里的内容,并去重

Parameters:
	words_file - 文件路径
Returns:
	words_set - 读取的内容的set集合
Author:
	Jack Cui
Blog:
	http://blog.csdn.net/c406495762
Modify:
	2017-08-22
"""
def MakeWordsSet(words_file):
	words_set = set()											#创建set集合
	with open(words_file, 'r', encoding = 'utf-8') as f:		#打开文件
		for line in f.readlines():								#一行一行读取
			word = line.strip()									#去回车
			if len(word) > 0:									#有文本,则添加到words_set中
				words_set.add(word)								
	return words_set 											#返回处理结果

"""
函数说明:根据feature_words将文本向量化

Parameters:
	train_data_list - 训练集
	test_data_list - 测试集
	feature_words - 特征集
Returns:
	train_feature_list - 训练集向量化列表
	test_feature_list - 测试集向量化列表
Author:
	Jack Cui
Blog:
	http://blog.csdn.net/c406495762
Modify:
	2017-08-22
"""
def TextFeatures(train_data_list, test_data_list, feature_words):
	def text_features(text, feature_words):						#出现在特征集中,则置1												
		text_words = set(text)
		features = [1 if word in text_words else 0 for word in feature_words]
		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				#返回结果


"""
函数说明:文本特征选取

Parameters:
	all_words_list - 训练集所有文本列表
	deleteN - 删除词频最高的deleteN个词
	stopwords_set - 指定的结束语
Returns:
	feature_words - 特征集
Author:
	Jack Cui
Blog:
	http://blog.csdn.net/c406495762
Modify:
	2017-08-22
"""
def words_dict(all_words_list, deleteN, stopwords_set = set()):
	feature_words = []							#特征列表
	n = 1
	for t in range(deleteN, len(all_words_list), 1):
		if n > 1000:							#feature_words的维度为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:
			feature_words.append(all_words_list[t])
		n += 1
	return feature_words

"""
函数说明:新闻分类器

Parameters:
	train_feature_list - 训练集向量化的特征文本
	test_feature_list - 测试集向量化的特征文本
	train_class_list - 训练集分类标签
	test_class_list - 测试集分类标签
Returns:
	test_accuracy - 分类器精度
Author:
	Jack Cui
Blog:
	http://blog.csdn.net/c406495762
Modify:
	2017-08-22
"""
def TextClassifier(train_feature_list, test_feature_list, train_class_list, test_class_list):
	classifier = MultinomialNB().fit(train_feature_list, train_class_list)
	test_accuracy = classifier.score(test_feature_list, test_class_list)
	return test_accuracy

if __name__ == '__main__':
	#文本预处理
	folder_path = './SogouC/Sample'				#训练集存放地址
	all_words_list, train_data_list, test_data_list, train_class_list, test_class_list = TextProcessing(folder_path, test_size=0.2)

	# 生成stopwords_set
	stopwords_file = './stopwords_cn.txt'
	stopwords_set = MakeWordsSet(stopwords_file)
	test_accuracy_list = []
	deleteNs = range(0, 1000, 20)				#0 20 40 60 ... 980
	for deleteN in deleteNs:
		feature_words = words_dict(all_words_list, deleteN, stopwords_set)
		train_feature_list, test_feature_list = TextFeatures(train_data_list, test_data_list, feature_words)
		test_accuracy = TextClassifier(train_feature_list, test_feature_list, train_class_list, test_class_list)
		test_accuracy_list.append(test_accuracy)

	# ave = lambda c: sum(c) / len(c)
	# print(ave(test_accuracy_list))

	plt.figure()
	plt.plot(deleteNs, test_accuracy_list)
	plt.title('Relationship of deleteNs and test_accuracy')
	plt.xlabel('deleteNs')
	plt.ylabel('test_accuracy')
	plt.show()

运行结果:

在这里插入图片描述

更多学习资讯,学习源码,请在耶宇星球领取

更多学习资讯,学习源码,请在耶宇星球领取
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北顾丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值