Naive的贝叶斯说红楼梦后40回不是曹雪芹写的

1,088 阅读6分钟

最近刚刚开始看《机器学习实战》,有讲到用朴素贝叶斯方法分辨普通邮件和垃圾邮件。

朴素贝叶斯算法的理论基础来自于贝叶斯公式:
v2-be9e650b10b56abb06bf3c0cbf4a90b2_b-1

知道B条件下A发生的概率、B发生的概率、A发生的概率,就可以求出A条件下是B的概率。
以分辨垃圾邮件为例,知道垃圾邮件中出现垃圾词的概率p(A|B),收到垃圾邮件的概率p(B),收到的邮件中有垃圾词的概率p(A),就可以求出收到的有垃圾词的邮件属于垃圾邮件的概率p(B|A)。
不得不说原来我大二学的概率论还有点用。

准备数据:从文本中构建词向量。我手头正好有刘慈欣、韩松、马伯庸、迟卉的中短篇小说集,利用jieba模块分词处理后创建词向量。
测试算法:按理说结果应该分成 True positive/ False Postive/ True
Negative/ False Negative 四类情况,也就相当于机械互换性中说的误收、误废这样的概念。然而我目前无论哪种出错都直接errorCount += 1 了事。
测试程序中有个循环,每次循环都会打乱收录文章的顺序,做到随机取得测试集和训练集。错误数累计求平均值。

先放入刘慈欣和韩松的小说,训练集各20篇,测试集各5篇,循环5次,分类结果如下。

manyTimes(20,5,'刘慈欣','韩松',5)
第1次训练
……
第2次训练
……
第3次训练
……
第4次训练
……
第5次训练
……
我猜测 月夜 的作者是:刘慈欣
我猜测 杂草 的作者是:韩松
我猜测 非典幸存者联谊会 的作者是:韩松
我猜测 赡养上帝 的作者是:刘慈欣
耗时100秒
总耗时7分33秒
平均错误率:4.00%

再放入韩松和马伯庸的小说,参数同上。

manyTimes(20,5,'马伯庸','韩松',5)
第1次训练
……
第5次训练
……
我猜测 写给马小烦的信 的作者是:马伯庸
我猜测 我的祖国不做梦 的作者是:韩松
我猜测 钢铁之圆舞曲 的作者是:马伯庸
我猜测 杂草 的作者是:韩松
我猜测 三峡之旅 的作者是:韩松
耗时94秒
总耗时8分7秒
平均错误率:4.00%

刘慈欣和马伯庸的小说,参数同上。

manyTimes(20,5,'马伯庸','刘慈欣',5)
第1次训练
……
第5次训练
……
我猜测 吞食者 的作者是:刘慈欣
我猜测 耶稣之死 的作者是:马伯庸
我猜测 盗贼的委托人 的作者是:马伯庸
我猜测 北京九侠 的作者是:马伯庸
耗时78秒
总耗时6分58秒
平均错误率:0.00%

程序的错误率基本上在5%以下了。
大刘的小说多有科技名词,韩松小说文风怪诞,亲王的文章多有历史气息。这三个人的风格其实都还挺分明的。
然后我放进去迟卉的小说,与刘慈欣的进行对比。

manyTimes(20,5,'马伯庸','刘慈欣',5)
第1次训练
……
第5次训练
……
我猜测 命运 的作者是:刘慈欣
我猜测 思想者 的作者是:迟卉
我猜测 艾兹尼达传说 的作者是:迟卉
我猜测 最远的距离 的作者是:迟卉
耗时21秒
总耗时1分55秒
平均错误率:16.00%

这就属于比较gg了,把迟卉分别与韩松、亲王对比一下,结果也很糟糕。

manyTimes(19,5,'迟卉','刘慈欣',5)
……
平均错误率:50.00%
manyTimes(19,5,'迟卉','韩松',5)
……
平均错误率:34.00%

关于原因,我分析可能是迟卉小说的字数明显比前三者的要少,导致迟卉小说词语在词向量中占比不够高。或者其他什么我不懂但是大家毕竟是老司机了所以可以一眼看出来的错误和原因~还希望大家告知~

然后我又想到了红楼梦,相传红楼梦的后四十回执笔者乃高鹗。我感觉也可以用这个方法判断一下前八十回和后四十回究竟是不是一个人写的。
两个文件夹分别保存了前八十回和后四十回,进行分析。训练集各30篇,测试集各10篇,循环5次,分类结果如下。

manyTimes(30,10,'曹','高',5)
第1次训练
……
第5次训练
……
我猜测 072 的作者是:曹
我猜测 076 的作者是:曹
我猜测 116 的作者是:高
耗时61秒
总耗时5分16秒
平均错误率:4.00%
数字即为章数

我把前四十回和四十至八十回放到两个文件夹,判断这两部分是否是一个人写的。

manyTimes(30,10,'曹','高',5)
第1次训练
……
第5次训练
……
我猜测 069 的作者是:高
我猜测 032 的作者是:曹
我猜测 077 的作者是:高
14 应该是曹
21 应该是曹
耗时72秒
总耗时6分13秒
平均错误率:21.00%
数字即为章数

结果似乎已经很明显了。在区分前八十回和后四十回的时候,程序的错误率为4%,说明前后风格差距比较大,容易辨识出来。而区分前四十回和第四十回到第八十回的时候,程序的错误率为21%,说明前后两者风格更加接近,不容易分辨清楚。
这样比较之下,前八十回像是一个人写的,而后四十回像是另一个人写的。

不得不感慨朴素贝叶斯真是强大,我明明就是随便找了几篇文章,随随便便拿jieba切了一下词汇,没有词频统计,也没有去除无意义词语,都是直接加进词向量里面,计算概率。就这样弄出来的分类器的错误率都在5%以下。。。。

所谓朴素(naive),指的是各个词特征之间相互独立、每个特征重要程度相同等等的假设。比如cake出现在delicious和nausea附近的概率相同云云。实际情况肯定不是这样的,但是有了这种简单原始的假设,运算速度会大大加快,而且分类准确率也不低。

当然了,要是不naive了说不定会更厉害。

就酱。

初次接触机器学习,以及初次写这种类似于博客的文章,请各位多指教!