说到《红楼梦》后四十回的真伪 文学界各位大佬争论了两百多年,有共识,却没有定论 小智也想班门弄斧一下 试试从理科的角度破解这个纠缠两个多世纪的悬案 一般来说,每一段语言、文字都或多或少带着对应人物形象的烙印 比如听到“我想死你们了”,大概知道是冯巩来了 “抽烟喝酒烫头”那是于谦老师的标配 甚至有时候,一个群体也会有着固定的口头禅或者说话习惯 (ಥ_ಥ) 图文无关 (ಥ_ಥ) 基于这个理由,我们相信,如果红楼梦前八十回与后四十回 由同一个作者书写 那么,他的用词习惯,行文风格必然是统一的 反之,如果用词存在明显差异,就证明后四十回存在伪造嫌疑 小智的大致思路是将红楼梦120回通过统计方法转换为向量,并打上是否为前八十回的标签,之后从中抽取一小部分作为训练集,剩下大部分为测试集。训练集送入分类算法进行学习,然后用此算法放在测试集上检验,看效果如何,如果精度较高则表明前八十回和后四十回的写作风格的确有所不同。 那么,选择什么样的特征来将红楼梦文本转化为向量? 常用的词频统计、χ方统计、互信息等方法肯定是不行的,因为前八十回和后四十回本来情节上就不同,涉及情节的词词频肯定有所不同,例如,七十八回之前和之后相比,晴雯这个词的出现频率肯定有天壤之别。如果用这些方法选出来的词作为特征,即使能将前八十回分出来也说明不了这是两个不同人写出来的。 因此,本文选择了“之”、“其”、“亦”等五十多个文言虚词,加上红楼梦中在所有120回中均有出现的部分词语共同组成特征值,这样算下来一共有一百余个词,采用这些词的出现频率来作为特征,最大程度地排除了情节的影响,某种程度上体现了写作者的写作风格。 接下来是分类算法的选择,小智选择了常用的SVM算法。闲话不多说,特征值选择和算法确定了之后,接下来就是写个小程序验证一下这个想法。在这里,小智用的语言是Python 3.5。 具体操作分成四步进行: 一、引入模块 开头部分没什么过多可以说的,就是引入需要的模块,以scikit-learn的内容为主。HC这个模块里面是小智自己写的一些常用函数。 二、向量化 首先是读取红楼梦的文本,这个文本是在网上抓取的一个无脂批的红楼梦120回版本,经过了一定预处理然后保存下来的文件。 之后调用了张华平博士开发的NLPIR汉语分词系统,将所有文本进行分词,然后收集成一个词典。 下一步,将每一回均出现的词加上五十余个文言虚词合并起来,作为特征值。程序运行结果显示最后作为特征值的词有138个。 将文本向量化的时候使用了最简单粗暴的词频统计方法,一开始也试过tf-idf等方法将文本向量化,但是运行之后发现在本次应用里其结果还没有简单的词频方法好。 三、分类算法 将120回随机分成了两部分,比例是0.8,也就是训练集占20%,24回,剩下的96回作为测试集。由于是文本分类任务,就直接把SVM的核定为线性核,然后用gridsearch搜索一下参数C,得到一个最优化的参数。最后在测试集上验证算法。 四、可视化 为了有个直观一些的印象,将138维的文本向量压缩成2维并画出来,降维过程采用的是PCA的方法。 运行程序后,在测试集上得到了如下的验证结果:
在验证集上得到了0.95的平均f1值,效果还是不错的。这也可以表明,前八十回和后四十回至少在写作用词习惯上是有所区别的,使用算法可以很清楚地区分开。光看f1值有些抽象,可以考虑将高维的文本向量降维,然后画出来,虽然会损失很多信息,但是也可能有一些直观的东西呈现出来。 将138维向量压缩到2维之后得到的图像如下:
依照如上方式,如果将红楼梦分为三部分画出来,可以得到:
本文用机器学习的方法选取了一个很小的方面来对红楼梦前八十回和后四十回的区别做了些探究,算法并不复杂,结果还是比较明显。由于用词风格上存在明显差异,我们有理由相信,《红楼梦》后四十回,极有可能是他人假托曹雪芹之名的伪作! |
|