IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> NB朴素贝叶斯进行中文文本分类 -> 正文阅读

[人工智能]NB朴素贝叶斯进行中文文本分类

基于multinomial-nb的文本分类

一、数据处理

1. 数据获取

搜狗实验室 搜狐新闻数据 下载地址:http://www.sogou.com/labs/resource

2. 数据预处理

下载后数据为GBK格式,使用UltraEdit转码为UTF8格式,再整理为json方便处理

接着,由url前缀对应的新闻类型得到分类,共得到15类,取分布均匀的11个类,如下

img

在对每个新闻取前100字,并通过jieba分词,并去掉词性为‘x’的词(标点),得到最终数据

(1)新闻文本数据,每行 1 条新闻,每条新闻由若干个词组成,词之间以空格隔开,训练文本 17600 行,测试文本 4324 行;

(2)新闻标签数据,每行 1 个数字,对应这条新闻所属的类别编号,训练标签 17600行,测试标签 4324 行

二、离散型朴素贝叶斯——multinomial-nb算法

1. 文本识别中的NB

对于文本分类任务,其输入是一组文档,输出则是文档的类型,而朴素贝叶斯在文本分类任务中表现得很出色。NB是一个概率分类器,他告诉我们结果在类中的可能性,也就是对每一个元素,我们使用公式计算其概率,并取最高的概率所对应的类作为其分类结果。

初始公式如下:

img

先验概率P(c)被计算为训练数据在c类中的文档所占的百分比。

img公式1)

其中Nc是数据中具有c类的文档总数,而Ndoc是文档总数。

由于文档d被表示为一组特征(词语)w,所以类中每个单词的初始似然公式为:

img

即结果为类别c中给定词语的计数与类别c中所有单词的比

然而,如果类别c中没有给定的词语,那么该概率将等于0,而最后我们要将所有的特征似然相乘,就会导致整个类别的概率也为0。因此,采用拉普拉斯平滑技术,公式如下:(公式2

img

其中V是我们所有词语的集合,由于每个概率值很小(比如0.0001)若干个很小的概率值直接相乘,得到的结果会越来越小。为了避免计算过程出现下溢(underflower),引入对数函数Log,在 log space中进行计算。然后使用词袋模型的每个单词wi 出现频率作为特征,得到如下公式(公式3

img

2. 训练朴素贝叶斯分类器

训练朴素贝叶斯的过程其实就是计算先验概率和似然函数的过程。

2.1 先验概率P?的计算

P?的意思是:在所有的文档中,类别为c的文档出现的概率有多大?假设训练数据中一共有Ndoc篇文档,只要数一下类别c的文档有多少个就能计算p?了,类别c的文档共有Nc篇,先验概率的计算公式如下:

img

关于先验信息理解,可参考:这篇文章

2.2 似然函数P(wi|c)的计算

由于是用词袋模型表示一篇文档d,对于文档d中的每个单词wi,找到训练数据集中所有类别为c的文档,数一数 单词wi在这些文档(类别为c)中出现的次数:count(wi,c)

然后,再数一数训练数据集中类别为c的文档一共有多少个单词img.计算 二者之间的比值,就是似然函数的值。似然函数计算公式如下:

img

其中V,就是词库。(有些单词在词库中,但是不属于类别C,那么 count(w,c)=0)

注意,实际训练还需要使用拉普拉斯平滑。

3. 代码实现

下面,我将从代码运行顺序进行代码实现。

3.1 执行函数

class Implementation():
    '''
    执行函数
    accuary:计算正确率
    main:主函数
    readfile:读取数据集
    '''
    def __init__(self):
        self.labels = dict()

    @staticmethod
    def accuracy(prediction, test):
        acc = 0
        test_list = list(test)
        for idx, result in enumerate(prediction):
            if result == test_list[idx]:
                acc += 1

        return acc / len(test)

    def main(self):
        x_train, y_train, x_test, y_test = self.readFile()
        nb = MultinominalNB()

        """ 
        save:保存训练模型
        cached:读取训练模型
        """
        nb.fit(x_train, y_train, save=True)
        predictions = nb.predict(x_test, cached=False)

        print('Accuracy: ', self.accuracy(predictions, y_test))

    def readFile(self):
        x_train = open('mydata/train_contents.txt', encoding="utf-8").read().split('\n')
        y_train = open('mydata/train_labels.txt', encoding="utf-8").read().split('\n')
        x_test = open('mydata/test_contents.txt', encoding="utf-8").read().split('\n')
        y_test = open('mydata/test_labels.txt', encoding="utf-8").read().split('\n')

        print('Train data: ', len(x_train), 'Testing data: ', len(x_test), 'Total: ', len(x_train)+len(x_test))

        return x_train, y_train, x_test, y_test

该函数作为执行函数,包含计算正确率,读取数据集,训练模型等方法。

在 main()方法中,MultinominalNB()为已经搭建好的类,在后文论述,其中nb.fit()对模型进行训练,参数save控制其是否保存训练模型,nb.predict()对测试集进行分类,并返回分类结果predictions,其中参数cached控制是否读取训练模型进行分类。predictions传入方法accuracy()中

accuracy()将accuracy()与测试集标签进行对比,并返还正确率比值。

3.2 fit()训练

fit()方法实现了模型的训练。

    def fit(self, x, y, save=False):
        self.docs = x
        self.classes = y
        num_doc = len(self.docs)  # 训练集数量
        uniq_cls = np.unique(self.classes)  # 标签种类数量
        self.vocab = self.buildGlobalVocab()  # 建立所有词的词库
        vocab_cnt = len(self.vocab)  # 词库中词的数量

        t = time()

        for _cls in uniq_cls:
            cls_docs_num = self.countCls(_cls)  # 当前标签种类数量
            self.logprior[_cls] = np.log(cls_docs_num / num_doc)
            self.buildClassVocab(_cls)  # 建立当前种类的词库
            class_vocab_counter = Counter(self.class_vocab[_cls])  # 记录当前类,词库中每个词的数量
            class_vocab_cnt = len(self.class_vocab[_cls])  # 当前类特征词库长度

            for word in self.vocab:
                w_cnt = class_vocab_counter[word]
                self.loglikelihood[word, _cls] = np.log((w_cnt + 1) / (class_vocab_cnt + vocab_cnt))

        if save:
            self.saveModel()
        print('Training finished at {} mins.'.format(round((time() - t) / 60, 2)))

在main中有

nb = MultinominalNB()
nb.fit(x_train, y_train, save=True)

首先读入数据集x_train, y_train, 并在第一次训练时令save=True,

        self.docs = x
        self.classes = y

fit中先把x_train保存在docs中,y_train保存在classes中

        num_doc = len(self.docs)  # 训练集数量
        uniq_cls = np.unique(self.classes)  # 标签种类数量

计算训练集中文档的数目、标签种类,输出如下

17600
['1' '10' '11' '2' '3' '4' '5' '6' '7' '8' '9']
        self.vocab = self.buildGlobalVocab()  # 建立所有词的词库
        vocab_cnt = len(self.vocab)  # 词库中词的数量

利用方法**buildGlobalVocab()**建立所有词的词库,该方法将在下面论述。返回词库保存在vocab中,并计算词库中所有词语的数量
部分输出如下:

['下' '中式' '乔氏' '了' '亨德利' '以' '以上' '以及' '佛' '佛山' '佛山市' '全天' '全家福' '全封闭'
 '全球' '八球' '冠军' '决战' '出炉' '初步' '后' '吨' '含' '周一' '周三' '回暖' '国际' '图文' '在'
 '复苏' '外汇' '大师' '大桥' '大通' '实施' '巩义' '已经' '年' '幸福' '广佛' '开始' '张广豪' '总体'
 '执行' '挑战赛' '摩根' '数据' '施工' '旅游' '日' '日报' '日讯' '时刻' '显现' '暨首届' '月' '来自' '杯'
 '梁宝忠' '汽车' '河南' '照片' '环球' '球杆' '疲软' '的' '站' '第二季度' '第二阶段' '第四站' '管制' '米'
 '经历' '经济' '维修' '翠' '花山' '英伦' '表现' '表示' '讯' '货车' '起' '车辆通行' '进行' '迹象' '选手'
 '邀请赛' '都市网' '销售量' '长沙' '陈' '限制' '陕西' '陕西省' '零售' '颁奖仪式' '预选赛' '高度' '鲨鱼']
 58513
        for _cls in uniq_cls:
            cls_docs_num = self.countCls(_cls)  # 当前标签种类数量
            self.logprior[_cls] = np.log(cls_docs_num / num_doc)
            self.buildClassVocab(_cls)  # 建立当前种类的词库
            class_vocab_counter = Counter(self.class_vocab[_cls])  # 记录当前类,词库中每个词的数量
            class_vocab_cnt = len(self.class_vocab[_cls])  # 当前类特征词库词语数量

对于每一类文档,首先利用方法**countCls()计算当前标签种类的数量,并计算先验概率(公式1),保存在logprior[_cls]**中,*self.buildClassVocab(_cls)*方法建立当前种类的词库,并将其保存在class_vacab中,下面计数,在类cls中每个词语的数量保存在class_vocab_counter中,计算当前类词库词语总数保存至class_vocab_cnt。

            for word in self.vocab:
                w_cnt = class_vocab_counter[word]
                self.loglikelihood[word, _cls] = np.log((w_cnt + 1) / (class_vocab_cnt + vocab_cnt))

利用公式2计算似然函数

        if save:
            self.saveModel()
        print('Training finished at {} mins.'.format(round((time() - t) / 60, 2)))

最后,判断是否保存,并计算训练所用时间

3.3 buildGlobalVocab(self) 建立全部词库

    def buildGlobalVocab(self):
        # 建立词库
        vocab = []
        for doc in self.docs:
            vocab.extend(self.cleanDoc(doc))

        return np.unique(vocab)

对训练集中每个文档doc,先将doc中词语分离出来,这里用到了方法cleanDoc,并将重复的词去掉,最终返回。

3.4 cleanDoc() 分离文档中的词语

    def cleanDoc(doc):
        # 分词
        return re.split(' ', doc)
    
# 例程
vocab_cnt = cleanDoc(x_train_test[1])
print(x_train_test[1])
print(vocab_cnt)

输出如下:

幸福 时刻 全家福 旅游 照片 年 月 日 陕西省 翠 花山 全家福 旅游 照片 年 月 日 陕西省 翠 花山 全家福 旅游 照片 年 月 日 陕西省 翠 花山 全家福 旅游 照片 年 月 日 陕西
['幸福', '时刻', '全家福', '旅游', '照片', '年', '月', '日', '陕西省', '翠', '花山', '全家福', '旅游', '照片', '年', '月', '日', '陕西省', '翠', '花山', '全家福', '旅游', '照片', '年', '月', '日', '陕西省', '翠', '花山', '全家福', '旅游', '照片', '年', '月', '日', '陕西']

3.5 countCls() 计算数据集中,某个种类的数量

    def countCls(self, cls):
        # 计算docs中有多少cls这个种类
        cnt = 0
        for idx, _docs in enumerate(self.docs):
            if (self.classes[idx] == cls):
                cnt += 1
        return cnt

遍历数据集,如果种类符合计数加一

3.6 buildClassVocab(self, _cls) 计算某一类的词库

    def buildClassVocab(self, _cls):
        # 建立特征词库,将训练集中所有cls类的词建立词库
        curr_word_list = []
        for idx, doc in enumerate(self.docs):
            if self.classes[idx] == str(_cls):
                curr_word_list.extend(self.cleanDoc(doc))
        # 保存词库,如果没有则新建,有则添加
        if _cls not in self.class_vocab:
            self.class_vocab[_cls] = curr_word_list
        else:
            self.class_vocab[_cls].append(curr_word_list)

先遍历整个数据集,找出所有的该类的词库,最后将词库中词语剥离出来放进class_vocab[_cls]中。

3.7 saveModel(self)与readModel(),模型保存与读取

    def saveModel(self):
        try:
            f = open("classifier.txt", "wb")
            pickle.dump([self.logprior, self.vocab, self.loglikelihood, self.classes], f)
            f.close()
        except:
            print('Error saving the model')

    @staticmethod
    def readModel():
        try:
            f = open("classifier.txt", "rb")
            model = pickle.load(f)
            f.close()
            return model
        except:
            print('Error reading the model')

3.8 predict(self, test_docs, cached=False) 对测试集进行分类

    def predict(self, test_docs, cached=False):
        '''
        对测试集进行分类
        :param test_docs: 测试数据集
        :param cached: 是否读取的训练模型
        :return: 测试集对应的分类结果
        '''
        output = []

        if not cached:
            logprior = self.logprior
            vocab = self.vocab
            loglikelihood = self.loglikelihood
            classes = self.classes
        else:
            logprior, vocab, loglikelihood, classes = self.readModel()

        for doc in test_docs:
            uniq_cls = np.unique(classes)
            sum = dict()  # 创建sum字典

            for _cls in uniq_cls:
                sum[_cls] = logprior[_cls]

                for word in self.cleanDoc(doc):
                    if word in vocab:
                        try:
                            sum[_cls] += loglikelihood[word, _cls]
                        except:
                            print(sum, _cls)

            result = np.argmax(list(sum.values()))
            output.append(uniq_cls[result])

        return output

首先通过标志cached判断是否读取模型

接着,对测试集中每个文档,按照公式3进行计算,并得到最终分类结果,加入output中

其中 np.argmax用法

import numpy as np
a = np.array([3, 1, 2, 4, 6, 1])
b=np.argmax(a)#取出a中元素最大值所对应的索引,此时最大值位6,其对应的位置索引值为4,(索引值默认从0开始)
print(b)#4

4. 执行结果

C:\Users\BC_PC\AppData\Local\Programs\Python\Python39\python.exe C:/Users/BC_PC/Desktop/multinomial-nb-master/mynb.py
Train data:  17600 Testing data:  4324 Total:  21924
Training finished at 0.12 mins.
Accuracy:  0.8533765032377428

Process finished with exit code 0
  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-10-03 17:04:52  更:2021-10-03 17:08:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 12:40:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码