电影《芳华》在春节重映了一波,加上之前的热映,最终取得了14亿票房的好成绩。严歌苓的原著也因此被更多的人细细品读。用文本分析的一些技术肢解小说向来是自然语言处理领域的一大噱头,这次当然也不能放过,本篇达成的成就有: 1、提取两大主角刘峰和何小嫚(萍)的关键词并绘制好看的人物词云; 2、以章节为单位探索小说的主题分布并画图展示。

主要功能包:

jieba
lda
wordcloud
seaborn
安装命令: pip install ***
复制代码

需要的外部文件:

1、小说全文, 芳华-严歌苓.txt
2、中文停用词,stopwords.txt
3、小说人物名称,person.txt,作为jieba的用户自定义词典
4、两个人物的png图片
5、你喜欢的中文字体的ttf文件,我用的楷体
复制代码

一、文本预处理

1、分词,并过滤无意义词

文本挖掘的必备步骤,毕竟理解中文的最小单位是词汇。这里没有使用简单的jieba.cut进行分词,因为我们需要知道单词的词性,便于稍后根据词性过滤不重要的词。

采用jieba.posseg.cut分词可以输出词性。我们并不能拍脑门决定是要动词还是名词等等,词性有非常多个,我把全部分词结果按照词性分好类,看了一下每个词性对应哪些词,最后决定保留词性为["a", "v", "x", "n", "an", "vn", "nz", "nt", "nr"]的词,例如图中,m代表量词,这是对语义没有帮助的词,应该舍弃。

import jieba.posseg
jieba.load_userdict("data/person.txt")
STOP_WORDS = set([w.strip() for w in open("data/stopwords.txt").readlines()])def cut_words_with_pos(text):seg = jieba.posseg.cut(text)res = []for i in seg:if i.flag in ["a", "v", "x", "n", "an", "vn", "nz", "nt", "nr"] and is_fine_word(i.word):res.append(i.word)return list(res)# 过滤词长,过滤停用词,只保留中文
def is_fine_word(word, min_length=2):rule = re.compile(r"^[\u4e00-\u9fa5]+$")if len(word) >= min_length and word not in STOP_WORDS and re.search(rule, word):return Trueelse:return False复制代码

2、划分章节

我们按照“第*章”这样的字眼将小说的不同章节分割开来,作为独立的文档,用于之后的主题分析。定义了一个名为MyChapters的生成器,存储每章分好的词汇,是为了避免章节过多带来的一些程序运行问题。其实《芳华》仅有15章,用一个简单的列表也是可以的。

class MyChapters(object):def __init__(self, chapter_list):self.chapter_list = chapter_listdef __iter__(self):for chapter in self.chapter_list:yield cut_words_with_pos(chapter)def split_by_chapter(filepath):text = open(filepath).read()chapter_list = re.split(r'第.{1,3}章\n', text)[1:]return chapter_list
复制代码

二、人物关键词提取

要提取人物关键词,首先要解决的问题是,在不借助外部的人物描述(比如百度百科和豆瓣电影上的角色介绍)的情况下,如何确定跟这个人物相关的内容。这里采用的比较简单的策略是,对小说文件中的每一行,如果该人物的名称存在,则将该行加入到此人的相关语料中去。再以此为基础统计词频,结果大致ok,为了人物词云更精确的展示,我将词频输出到了文件,手动删除了一些词,并简单调整了一些词的词频,下图是调整过后的词和词频,左为何小嫚,右为刘峰。

import pandas as pddef person_word(name):lines = open("data/芳华-严歌苓.txt", "r").readlines()word_list = []for line in lines:if name in line:words = cut_words_with_pos(line)word_list += words# 统计词频并按照词频由大到小排序,取top500cnt = pd.Series(word_list).value_counts().head(500)# 可以把结果输出到文件,进行一些手动调整# cnt.to_csv("data/cntliu.csv")# 返回字典格式return cnt.to_dict()
复制代码

三、词云绘制

python有wordcloud包可以用于词云绘制,在使用过程中需要注意:

1、用于定义形状的外部图片必须是png格式,默认纯白色部分为非图像区域; 2、中文词云必须载入一个字体文件; 3、字的颜色可以自己定义,也可以使用图片本身的底色。本例中何小嫚的图片 底色很鲜艳明晰,可以用本身的底色(ImageColorGenerator);而刘峰的图片是单色,且色浅,我使用了自定义颜色(my_color_func); 4、绘制词云需要用到的数据格式为dict,key为词,value为词频,词频越大,在图片中的字体越大。

import matplotlib.pyplot as plt
from wordcloud import WordCloud, ImageColorGenerator
from scipy.misc import imread
from random import choice# 定义颜色,方法很多,这里用到的方法是在四个颜色中随机抽取
def my_color_func(word, font_size, position, orientation, random_state=None, **kwargs):return choice(["rgb(94,38,18)", "rgb(41,36,33)", "rgb(128,128,105)", "rgb(112,128,105)"])def draw_cloud(mask_path, word_freq, save_path):mask = imread(mask_path)  #读取图片wc = WordCloud(font_path='data/kaiti.TTF',  # 设置字体background_color="white",  # 背景颜色max_words=500,  # 词云显示的最大词数mask=mask,  # 设置背景图片max_font_size=80,  # 字体最大值random_state=42,)# generate_from_frequencies方法,从词频产生词云输入wc.generate_from_frequencies(word_freq)plt.figure()# 刘峰, 采用自定义颜色plt.imshow(wc.recolor(color_func=my_color_func), interpolation='bilinear')# 何小嫚, 采用图片底色# image_colors = ImageColorGenerator(mask)# plt.imshow(wc.recolor(color_func=image_colors), interpolation='bilinear')plt.axis("off")wc.to_file(save_path)plt.show()
复制代码
# 获取关键词及词频
input_freq = person_word("刘峰")
# 经过手动调整过的词频文件,供参考
# freq = pd.read_csv("data/cntliu.csv", header=None, index_col=0)
# input_freq = freq[1].to_dict()
draw_cloud("data/liu.png", input_freq, "output/liufeng.png")
复制代码

对人物进行抠图,背景设置为纯白,存储为png格式。 为了使形状更鲜明,对小嫚的辫子还有腰的部分做了加白处理,可以对比文章开头原图感受一下。

如果你看过这部作品,不知道印象最深的是不是像词云显示的那样?小嫚在精神病院的月下独舞,刘峰对丁丁的深深眷恋,在战争中失去手臂,与不爱的人结婚又离婚,和小嫚以朋友的姿态相伴终老... ...

四、主题分析

lda 方法的原理不做介绍了,假设你设置了这15章讲了k个主题,那么它的输出是:1、每个主题都由哪些词构成,概率几何; 2、每章内容中,k个主题各占多大比例,占比越大,该章内容与该主题越贴切。

1、首先,整理模型输入

lda要求的输入格式为文档-词汇频次矩阵,也就是各词语在个章节中出现了多少次,我们用CountVectorizer可以一步实现。 CountVectorizer要求的输入格式为:["word1 word2", "word3 word4", ...] 即一个章节作为一个完整的字符串,其中的词用空格隔开

from sklearn.feature_extraction.text import CountVectorizerdef get_lda_input(chapters):corpus = [" ".join(word_list) for word_list in chapters]vectorizer = CountVectorizer()X = vectorizer.fit_transform(corpus)return X.toarray(), vectorizer
复制代码

2、训练模型

我们设置主题个数为20个,并打印如下内容: 每个主题打印最能描述该主题的前20个词 每章打印占比最高的前3个主题

def lda_train(weight, vectorizer):model = lda.LDA(n_topics=20, n_iter=500, random_state=1)model.fit(weight)doc_num = len(weight)topic_word = model.topic_word_vocab = vectorizer.get_feature_names()titles = ["第{}章".format(i) for i in range(1, doc_num + 1)]n_top_words = 20for i, topic_dist in enumerate(topic_word):topic_words = np.array(vocab)[np.argsort(topic_dist)][:-(n_top_words + 1):-1]print('Topic {}: {}'.format(i, ' '.join(topic_words)))doc_topic = model.doc_topic_print(doc_topic, type(doc_topic))plot_topic(doc_topic)for i in range(doc_num):print("{} (top topic: {})".format(titles[i], np.argsort(doc_topic[i])[:-4:-1]))
复制代码
def main():chapter_list = split_by_chapter("data/芳华-严歌苓.txt")chapters = MyChapters(chapter_list)weight, vectorizer = get_lda_input(chapters)lda_train(weight, vectorizer)
复制代码

输出结果:

Topic 0: 小惠 郝淑雯 少俊 好人 啤酒 看着 生意 老板 刘大哥 老战友 发廊 老公 邻居 汽车 背叛 城管 出卖 眼线 惠雅玲 路灯
Topic 1: 年轻 女人 照片 眼睛 想到 生命 跟着 来到 笑笑 院子 回去 房间 好看 军区 结婚 接受 打开 听说 坐在 关系
Topic 2: 刘峰 红苕 老百姓 老太太 红楼 括弧 落后 大娘 打靶 子弹 练功 板凳 榔头 文工团 男孩儿 地板 大胜 打着 剩下 姨太太
Topic 3: 母亲 父亲 女儿 牺牲 善良 名字 前线 丈夫 看着 坏话 干事 生活 触摸 碰到 妻子 家庭 手指尖 继父 脊梁 手指
Topic 4: 丁丁 林丁丁 干事 人格 小林 出卖 恶心 报告 声乐 回答 老师 摄影 库房 对象 演员 男女 喜欢 王老师 组织 权利
Topic 5: 女人 侄子 事儿 女朋友 电话 想象 红楼 手机 回来 地方 公司 酒店 日子 轿车 叔叔 皮包 战友 电梯 化疗 客厅
Topic 6: 丁丁 丈夫 食堂 妹妹 王家 肯定 故事 文工团 条件 函授 机器 笑笑 老板 夫人 工作 老三 姐妹 考试 姨妈 虚荣
Topic 7: 父亲 标兵 女兵 爸爸 父母 茶缸 政治 包裹 招待所 看成 学雷锋 萧穗子 送来 编造 捎来 文件 放进 行李袋 友谊商店 真话
Topic 8: 看着 黑色 眼睛 红色 郝淑雯 故事 学校 怀疑 毛衣 走出 闹钟 帽子 玩儿 老兵 柔软 军帽 起床 热爱 冷水 新兵
Topic 9: 何小嫚 头发 衬衫 演出 感觉 同志 所有人 轻伤 掌上明珠 伤员 分队 小何 潜意识 表演 体温 下放 连队 温度 退回 对话
Topic 10: 小时 跟头 毯子 看着 同屋 同情 小郝 领导 危险 甜饼 自由 炊事班 中提琴手 伙食 邀请 办法 目光 女孩儿 巷子 梆子
Topic 11: 团长 驾驶员 卫生员 骑兵 战士 护士 包扎 士兵 奖品 装病 流传 红蚁 卡车 体温计 服装 舞蹈 温度计 弹药 离开 军马
Topic 12: 护士 服务员 报道 医院 首长 战友 政治部 报纸 天使 住院 只能 剪断 包扎 标语 伏击 妈妈 学习 歌声 迟到 护理员
Topic 13: 母亲 弟弟 继父 女儿 拖油瓶 厅长 毛衣 弄堂 妹妹 绒线衫 高烧 亭子间 跟着 饺子 讨厌 小时 姆妈 虫蛀 卫生 姐姐
Topic 14: 刘峰 郝淑雯 点儿 林丁丁 告诉 女儿 时间 发生 男人 老家 好像 医院 拿出 无耻 等待 所有人 世界 不错 帮忙 不知
Topic 15: 丁丁 沙发 表弟 林丁丁 秘密 萧穗子 排长 胆石 眼睛 参观 吉普 排球场 专注 肌肤 卫生带 脱下 成功 距离 合算 衬衫
Topic 16: 身体 发现 孩子 回到 找到 不知 记得 说话 意识 见到 摇摇头 所有人 漂亮 样子 机会 显得 毛巾 我会 发言 不见
Topic 17: 老师 朱克 头发 郝淑雯 身体 走廊 乳罩 承认 藤椅 卫生员 军帽 撒谎 哨兵 地板 活儿 范儿 男舞者 眼泪 衬衣 海绵
Topic 18: 女兵 男兵 首长 明白 发现 地方 排练 回来 部队 舞蹈 动作 触摸 演出 事件 秘密 军装 生病 舞台 结束 接下去
Topic 19: 刘倩 平凡 追悼会 新兵 堂叔 灵台 操场 小林 灵堂 钥匙 冬青 通知 萨其马 老头儿 烈士陵园 小徐 看望 皮肤 土黄色 成就
复制代码

下面展示的章节所包括的主题,对照上面相应主题序号的词语,是否能大致判断每章在讲些什么呢。

第1章 (top topic: [ 2 18 16])
第2章 (top topic: [ 7 14 18])
第3章 (top topic: [10 14  7])
第4章 (top topic: [ 4 18 14])
第5章 (top topic: [15 14  1])
第6章 (top topic: [ 4 14 15])
第7章 (top topic: [ 3 14 16])
第8章 (top topic: [13 16  1])
第9章 (top topic: [ 8 13 18])
第10章 (top topic: [17  9 18])
第11章 (top topic: [11  9 18])
第12章 (top topic: [12  1  3])
第13章 (top topic: [ 6 14 18])
第14章 (top topic: [ 0 14  5])
第15章 (top topic: [19 14  1])
复制代码

3、画图

对于各章节的不同主题的分布,我们可以画个图来展示一下。 利用lda输出的doc_topic画热力图,doc_topic是一个二维数组,值为某主题在某章节的占比,刚刚打印的内容只可以看到每章包括的前三个主题,从下图中则可以看到全部主题在各章的分布情况,参考图例,颜色越深代表占比越大。

def plot_topic(doc_topic):f, ax = plt.subplots(figsize=(10, 4))cmap = sns.cubehelix_palette(start=1, rot=3, gamma=0.8, as_cmap=True)sns.heatmap(doc_topic, cmap=cmap, linewidths=0.05, ax=ax)ax.set_title('proportion per topic in every chapter')ax.set_xlabel('topic')ax.set_ylabel('chapter')plt.show()f.savefig('output/topic_heatmap.jpg', bbox_inches='tight')
复制代码

五、结语

中文的自然语言处理技术是一项特别繁杂的工作,需要注意非常多的细节,在分析的过程中,我也花了足够的精力做数据可视化,好看的图不仅可以吸引人的眼球,更可以加深我们对数据的理解。此外,探索一本小说,除了关键词和主题,还有很多别的思路,比如利用pagerank算法自动提取文本摘要,以及利用深度学习的模型自动续写情节... ...期待看到更多相关的作品,enjoy。 完整代码和数据:https://github.com/scarlettgin/novel_analysis

用WordCloud词云+LDA主题模型,带你读一读《芳华》(python实现)相关推荐

  1. Python实现的《芳华》WordCloud词云+LDA主题模型

    WordCloud 词云 + LDA 主题模型 何小嫚&刘峰原图.jpg 人物词云效果.jpg 电影<芳华>在春节重映了一波,加上之前的热映,最终取得了 14 亿票房的好成绩.严歌 ...

  2. lda主题模型困惑度_r语言lda主题模型代码 lda主题模型 案例分析

    r语言做灰色预测模型代码为什么会出错? 我正在MATLAB下编写一个Grey system的函数库, 我想其他的网友也做过类似的工作吧. 灰色模型的MATLAB求解代码应该很容易找到吧.如果不想用MA ...

  3. 贝叶斯算法(3)新闻分类任务实战:jieba中文分词、tfidf特征词提取、wordcloud词云展示、LDA主题建模、朴素贝叶斯算法分析预测

    1 加载数据 import pandas as pd import jieba # 数据源:http://www.sogou.com/labs/resource/ca.phpval_path = '/ ...

  4. [Pyhon疫情大数据分析] 三.新闻信息抓取及词云可视化、文本聚类和LDA主题模型文本挖掘

    思来想去,虽然很忙,但还是挤时间针对这次肺炎疫情写个Python大数据分析系列博客,包括网络爬虫.可视化分析.GIS地图显示.情感分析.舆情分析.主题挖掘.威胁情报溯源.知识图谱.预测预警及AI和NL ...

  5. 【带你玩转主题模型Topic Model】—— 之 利用sklearn 实现Latetnt Dirichlet Allocation(LDA)主题模型

    写在前面的话 9月份的第一篇blog, 正好是开学季,作为一个学生,hahahha, 我还是正正经经的贡献一篇认为比较干货的文章给大家吧. 我自己是花了很多时间去看懂LDA的算法了,当然了这篇文章不涉 ...

  6. 【项目实战】Python实现基于LDA主题模型进行电商产品评论数据情感分析

    说明:这是一个机器学习.数据挖掘实战项目(附带数据+代码+文档+视频讲解),如需数据+代码+文档+视频讲解可以直接到文章最后获取. 视频: Python实现基于LDA模型进行电商产品评论数据情感分析 ...

  7. lda主题模型的可视化_Gensim LDA主题模型实验

    本文利用gensim进行LDA主题模型实验,第一部分是基于前文的wiki语料,第二部分是基于Sogou新闻语料. 1. 基于wiki语料的LDA实验 上一文得到了wiki纯文本已分词语料 wiki.z ...

  8. LDA主题模型1——数学基础

    相信很多人第一次看到LDA算法都会头大,不管是看论文还是看博客,都少不了各种各样的公式和理论,概率分布.共轭分布.贝叶斯公式.Gibbs采样等等,一大堆耳熟又陌生的词,经常带着一大堆问号去学习,又带着 ...

  9. R语言实现LDA主题模型分析知乎话题

     这是一篇关于文本主题分析的应用实践,主要尝试聚焦几个问题,什么是LDA主题模型?如何使用LDA主题模型进行文本?我们将知乎上面的转基因话题精华帖下面的提问分成六大主题进行实践. 转基因" ...

最新文章

  1. 混合mixin函数_Less 混合
  2. Python风格规范
  3. 图像灰度图,直方图,像素通道问题
  4. 【Cef编译】 CefSharp编译失败,检测到“RuntimeLibrary”的不匹配项: 值“MT_StaticRelease”不匹配值“MD_DynamicRelease”...
  5. C#设计模式之9-装饰者模式
  6. 快速失败(fail-fast)和安全失败(fail-safe)的区别是什么?
  7. 又一次摔MFC坑里了
  8. java怎样将日期本土化_Java中的日期操作
  9. struts 标签导入
  10. 如何使用ELK来监控性能
  11. php104.tmp,首页-kaka窝论坛-综合管理-细说PHP-kaka窝 - Powered by Discuz!
  12. 将重复数据删除技术应用于数据复制过程 分享修改删除
  13. 笔记本电脑运行卡顿的真正原因和解决方案
  14. 爬取百度贴吧发帖信息并保存到scv文件中
  15. 问题:无法打开Workstation服务,错误代码2250
  16. pyecharts(9)-动态可视化-树形图-思维导图
  17. CAD转KML乱码处理
  18. 【Net Core系列】(前言).net core学习笔记
  19. ubuntu系统Firefox浏览器B站视频无法播放
  20. java代码:双色球号随机生成(极其简洁!)

热门文章

  1. 最新JAVA编程题全集(50题及答案)
  2. office各版本协同工作
  3. tp3.x和tp5.0的区别
  4. html 换行字体,div字体换行
  5. 寺冈labelnet使用说明_寺冈DI-162技术手册
  6. 课堂结对作业:二维数组(4)
  7. Java4班题库-传智专修学院Java面试题库四
  8. 计算机教师帮带情况,教师帮带工作总结
  9. 黑马程序员_面试题(一)交通灯管理系统
  10. 小程序毕设答辩问题【论坛/校园墙小程序】