重做红楼梦的数据分析-判断前80回后40回是否一个人写的

红楼梦的数据分析已经有许多人做过,结论也各不相同。
我在知乎上看到两篇帖子:
1. 通过数据挖掘能分析《红楼梦》各回的真伪吗?
2. 用机器学习判定红楼梦后40回是否曹雪芹所写
觉得很有意思,于是用自己的方法重做了一次

环境配置:

我主要使用的编程环境是Jupyter Notebook 4.2.1,因为可以调整每一个代码块,方便
纠错什么的。
然后我们得用到一个中文分词工具 - Jieba, 是由百度工程师Sun Junyi开发的
之后我们还得用到一些做机器学习/数据挖掘的标准包:numpy, matplotlib 和 sklearn

数据准备:

用爬虫思想,我去这个网站扒下来红楼梦全集,然后剪掉中间所有的换行符,使得每一回只
占文档中的一行。这样的话,方便接下来读取。

直接上代码:
一、导入各种需要的包

# -*-coding:utf-8 -*-import urllib
import urllib2
import re
from bs4 import BeautifulSoup as bsbook = []
for i in range(120):print("处理第{}回...".format(i+1))if i+1<10:url = "http://www.purepen.com/hlm/00{}.htm".format(i+1)elif i+1 < 100:url = "http://www.purepen.com/hlm/0{}.htm".format(i+1)else:url = "http://www.purepen.com/hlm/{}.htm".format(i+1)request = urllib2.Request(url)response = urllib2.urlopen(request)bsObj = bs(response.read().decode('gb18030')) #注意原网页的codec是哪一种chapter = bsObj.table.font.contents[0]book.append(chapter)

下面是结果:

之后把全文存进一个txt文件:

with open('红楼梦.txt', 'w') as f:  f.write(codecs.BOM_UTF8)  for chap in book:s = chap.encode('utf-8').strip()f.write("".join(s.split()))f.write('\n')

数据ready,可以开始进行处理了

处理:

直接上代码:
一、导入各种需要的包

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # 因为后面会用到3d作图
import operator
# 下面是机器学习包
from sklearn.cross_validation import train_test_split
from sklearn.grid_search import GridSearchCV
from sklearn.svm import SVC
from sklearn.metrics import classification_report
from sklearn.decomposition import PCA
# Jieba
import jieba

二、读取文件并分词

with open('红楼梦.txt') as f:all_chaps = [chap.decode('utf8') for chap in f.readlines()]# 给整本书分词
dictionary = []
for i in range(120):print "处理第{}回".format(i+1)words = list(jieba.cut(all_chaps[i]))dictionary.append(words)

三、Flatten数组 (中文是’摊平’? 哈哈)

tmp = [item for sublist in dictionary for item in sublist] # 摊平
dictionary = tmp

四、 给每一回贴上标签

# 给每一回贴上标签
for i in range(120):if i < 80:all_chaps[i] = [all_chaps[i],'1']else:all_chaps[i] = [all_chaps[i],'0']content = [row[0] for row in all_chaps]
label = [row[1] for row in all_chaps]

五、找出每一回均出现的词
之所以要这么做,是因为有一些很常出现的角色名在后四十回因为剧情原因不再出现了。在整个分析中我们注重对于文言虚词和其他连接词的分析,因为这样更能体现出写作者的个人风格。另外,这也是为什么我们没有在Jieba里加入角色名称的字典,因为没有这个必要。

# 找出每一回均有出现的词
from progressbar import ProgressBar # 显示进度
pbar =ProgressBar()wordineverychap = []
length = len(dictionary)
print "共有{}个词".format(length)
for word in pbar(dictionary):n = 0for text in content:if word in text:n+=1if n==120:wordineverychap.append(word)

六、合并虚词,以防虚词被过滤掉
这里用的虚词是直接从维基百科上抄下来的,一共20个左右,所以也并不麻烦。

with open('xuci.txt') as f:xuci = [word.decode('utf8').strip() for word in f.readlines()]for word in xuci:if word not in wordineverychap:wordineverychap.append(word)

七、过滤重复的词语,并去掉标点符号

selected_words = list(set(wordineverychap))
# 人工处理, 删除标点符号
for w in selected_words:print w

计算结果是一共有125个词语

八、给每个词语计数 并 排序

wordT = []
countT = []
table = {}chapNo = 1
for chap in content:sub_table = {}for word in uw:sub_table[word.decode('utf8')] = chap.count(word.decode('utf8'))table[chapNo] = sub_tablechapNo+=1import operator
table_sorted = []for idx in table:sub_table_sorted = sorted(table[idx].items(),key=operator.itemgetter(1),reverse=True)table_sorted.append(sub_table_sorted)

九、把数据存在csv里,以免不小心关掉程序后不用重新计算

# 任务:把数据存到csv里
import unicodecsv as csv# 写入第一行和第一列
f1 = open('cipin.csv', 'w+')
writer = csv.writer(f1, encoding='utf8', delimiter=',')
first_row = ['']  # A1留空
for i in range(120):first_row.append('第{}回'.format(i+1))
writer.writerow(first_row)   for word in selected_words:row = [word]for i in range(120):row.append(table[i+1][word.decode('utf8')])writer.writerow(row)f1.close()

十、把数据向量化

# 任务:把数据向量化 all_vectors = []for i in range(120):chap_vector = []for word in selected_words:chap_vector.append(table[i+1][word.decode('utf8')])all_vectors.append(chap_vector)

十一、把高维向量压缩为3维向量,方便作图
这里我们使用PCA(Principal Component Analysis),就是一种把高维度向量变成低维度向量的算法。比如我们现在每一回就有125维,无法作图。这个算法,像它的名字一样,会采集最重要的向量,然后压缩成到我们所需要的维数(3维)

#设置PCA的目标维数并创建一个model
pca = PCA(n_components=3)
#Feed我们的向量,进行训练
pca.fit(all_vectors)
#取得目标向量
z = pca.fit_transform(all_vectors)
#取得前八十回的向量
xs_a = [row[0] for row in z[:80]]
ys_a = [row[1] for row in z[:80]]
zs_a = [row[2] for row in z[:80]]
#取得后四十回的向量
xs_b = [row[0] for row in z[-40:]]
ys_b = [row[1] for row in z[-40:]]
zs_b = [row[2] for row in z[-40:]]#创建一个新的图表
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
#绘图
ax.scatter(xs_a, ys_a, zs_a, c='r', marker='o')
ax.scatter(xs_b, ys_b, zs_b, c='b', marker='^')
plt.show()

这就是绘制出来的图表:

每一个点表示一回,红色的点表示的是前八十回,蓝色的点表示的是后四十回。从该图我们可以发现,前八十回和后四十回的写作者用词习惯有可观察到的不同,所以由此我们可以大胆的说,前后的写作者是不同的!

为了准确,我们还可以做一组对比试验,这次我们分别画出前四十回 ,中间四十回 和 后四十回:

#前四十回
xs_a = [row[0] for row in z[:40]]
ys_a = [row[1] for row in z[:40]]
zs_a = [row[2] for row in z[:40]]
#中间四十回
xs_b = [row[0] for row in z[40:80]]
ys_b = [row[1] for row in z[40:80]]
zs_b = [row[2] for row in z[40:80]]
#最后四十回
xs_c = [row[0] for row in z[-40:]]
ys_c = [row[1] for row in z[-40:]]
zs_c = [row[2] for row in z[-40:]]ax.scatter(xs_a, ys_a, zs_a, c='b', marker='o')
ax.scatter(xs_b, ys_b, zs_b, c='y', marker='^')
ax.scatter(xs_c, ys_c, zs_c, c='r', marker='o')
plt.show()

画出的图表是这样:

蓝色的是前四十回,绿色的是中间四十回,红色的是后四十回。在这个图里我们也能看到前四十回和中间四十回重合了很多,而后四十回相对独立。

十三、用机器学习的思路处理
简单的说,就是我们把前八十回和后四十回分别做标注,用‘1’表示属于前八十回,‘0’表示属于后四十回。接着我们从前八十回中抽16回,后四十回中抽8回用作训练样本,剩下的用作测试样本。如果训练出来的模型成功从预测样本中预测出是否属于前八十回,就代表我们的想法是对的—–前八十回和后四十回的用词习惯的确不同。

上代码:

label = []
for i in range(120):if i<80:label.append(1)else:label.append(0)
# 分出训练和测试样本
x_train, x_test, y_train, y_test = train_test_split(all_vectors, label, test_size=0.8)
# 使用GridSearch找到合适的参数
params = [{'C':[1,5,10,50,100,250,500]}]
grid = GridSearchCV(SVC(kernel='linear'),params,cv=10)
# 训练!
grid.fit(x_train,y_train)
# 预测
y_pred = grid.predict(x_test)
# 显示预测结果
print(classification_report(y_test, y_pred))

最后我们的预测结果是这样的:

prediction precision recall f1-score support
0 0.85 0.97 0.90 29
1 0.98 0.93 0.95 67
avg/total 0.94 0.94 0.94 96

就结果而言,我们的模型比较准确的预测了测试样本属于哪个分类,说明我们的直观判断,可能是对的。

撒花~

欢迎转载

重做红楼梦的数据分析-判断前80回后40回是否一个人写的相关推荐

  1. [机器学习]---如何用机器学习来判定红楼梦后40回是否曹雪芹所写

    前言 看到用机器学习方法分析红楼梦的文章不少,也有好几种方法,大观是因为纯文字的分析成本低吧,比较适合初学者练手,先转载一两篇文章过来学习.所谓机器学习也是一些数学统计的方法,通过习惯用词来做判断, ...

  2. 用人工智能判断红楼梦后40回是否是曹雪芹写的

    本博文主要是用机器学习的方法判断红楼梦后四十回是不是曹雪芹写的 开发语言: Python3.6 开发工具: numpy,matplatlib,sklearn 相关算法: SVM 先放上预测结果,再慢慢 ...

  3. [机器学习]如何用机器学习来判定红楼梦后40回是否曹雪芹所写

    前言 今天在涉机器学习相关知识时,看到黎晨这篇文章,觉得蛮有意思的,拿来这里介绍大家.这里判定的维度越多越精准,下面判定仅供参考,仅供娱乐学习! #判定整体思路 主要从以下几个方面可以进行粗略进行判定 ...

  4. 数学建模训练 — 红楼梦作者解析

    摘要 <红楼梦>不同章回之间作者的异同,历来被学术界争论不休.当新的计算工具出现之后,我们就可以用数学的知识统计分析<红楼梦>不同章回作者异同的问题. 针对问题一,问题一要求根 ...

  5. 统计虚词使用不同聚类方法判别红楼梦作者

    采用了K-means聚类和层次聚类.密度聚类效果不太好就舍弃了 用到的库 import numpy as np from sklearn.cluster import KMeans from skle ...

  6. 机器学习之红楼梦作者判断(贝叶斯分类)

    上篇文章不带假设的使用聚类算法去判断红楼梦的作者,这一篇打算使用监督学习方法的贝叶斯分类,假设后四十回不是曹雪芹所写, 去做个验证. 关于我读过比较好的贝叶斯讲解:A simple explanati ...

  7. 【Python】统计《红楼梦》中出场次数前十的人物

    [Python]统计<红楼梦>中出场次数前十的人物 代码 截图 代码 import jiebaexcludes = {'什么', "一个", "我们" ...

  8. python红楼梦人物词频统计_用 Python 分析《红楼梦》

    1 前言 两个月以来,我通过互联网自学了一些文本处理的知识,用自然语言处理和机器学习算法对<红楼梦>进行了一些分析.这个过程中我找到了一些有趣的发现,所以我想写一篇文章,既㲌与大家分享和讨 ...

  9. 红楼梦人物出场统计python_用Python分析《红楼梦》:见证贾府的兴衰

    没读过<红楼梦>也能知道前后四十回是不是一个作者写的?很久以前,数据侠黎晨,用机器学习的算法分析了<红楼梦>,认为后四十回和前八十回内容上有明显差距.不过,数据侠楼宇却不这么认 ...

最新文章

  1. 基于canoe 新建一个lin工程_CANoe教程 | 高级编程 - C Library API
  2. vi编辑器基本使用方法
  3. jooq中record_在Spring中使用jOOQ:CRUD
  4. 网络管理的任务包括linux,网络管理员的任务是阻止的10.152.8.0/21 一个基于Linux的防火墙的网络子网的默认端口上的所有出站SSH 连接。以下哪项规则集将完成这项任务?(单选题)...
  5. Android的HTTP方式网络通信---HttpURLConnection
  6. Hadoop笔记整理(三):Zookeeper
  7. n皇后问题c语言_九章算法 | N皇后问题
  8. delphi 异步 调用 带参数_Dubbo 关于同步/异步调用的几种方式
  9. MSBuild 命令参数
  10. Elsevier旗下期刊利用latex模板撰写论文记录
  11. 教你快速高效接入SDK——总体思路和架构
  12. qq代理服务器传输文件失败,qq接收文件时显示传输文件失败?
  13. Ruby语言介绍(二)——Ruby基本语法(语言基础)
  14. 马克飞象(markdown)的快捷键
  15. php 模拟鼠标点击,Python全局模拟鼠标点击操作(以至善网无聊评价点击作为案例)...
  16. 深信服EDR任意用户登录漏洞复现
  17. kettle读取hbase
  18. 干货 | Reactive模式在Trip.com消息推送平台上的实践
  19. 岭回归原理简单分析与理解
  20. http、https和数字证书的相关知识

热门文章

  1. 终极USB示波器PicoScope 6000系列
  2. python curses_python curses 使用
  3. 联想TS540服务器主板型号,【ThinkServer TS540参数】ThinkServer TS540系列服务器参数-ZOL中关村在线...
  4. 三代笔记本CPU 正式版代号(升级联想K29笔记本)
  5. 基于Linux系统的C语言多关卡推箱子设计
  6. 意派epub360 html 代码,意派Epub360丨不用代码,不用定制,你也可以自己制作DIY类H5啦!...
  7. 人工智能洗衣机教程_什么是“智能洗衣机”,我需要一个吗?
  8. eclipse2022-06的web brower内部浏览器
  9. 利用cheese在Ubuntu(20.04)配置摄像头(VMware虚拟机)
  10. java计算机毕业设计社区流浪猫狗救助网站源码+系统+数据库+lw文档+mybatis+运行部署