Python自然语言处理分析倚天屠龙记

2024-03-24 10:20

本文主要是介绍Python自然语言处理分析倚天屠龙记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Python中文社区
全球Python中文开发者的精神部落


最近在了解到,在机器学习中,自然语言处理是较大的一个分支。存在许多挑战。例如: 如何分词,识别实体关系,实体间关系,关系网络展示等。

我用Jieba + Word2vec + NetworkX 结合在一起,做了一次自然语言分析。语料是 倚天屠龙记。 之前也有很多人用金庸的武侠小说做分析和处理,希望带来一些不同的地方。截几张图来看看:

所有人物的相似图连接。

关系同上。展示形式为多中心结构

以张无忌的不同身份为中心的网络关系图。 

这次分析的不一样之处主要是:

1、Word2Vec的相似度结果 - 作为后期社交网络权重

2、NetworkX中分析和展示

上面两个方法结合起来,可以大幅减少日常工作中阅读文章的时间。 采用机器学习,可以从头到尾半自动抽取文章中的实体信息,节约大量时间和成本。 在各种工作中都有利用的场景, 如果感兴趣的朋友,可以联系合作。

先来看看,用Word2Vec+NetworkX 可以发现什么。

一、分析结果

实体的不同属性(张无忌的总多马甲)

张无忌,无忌,张教主,无忌哥哥,张公子。同一个张无忌有多个身份,不同身份又和不同的人联系,有不一样的相似度。

先来看看图:

无忌哥哥是过于亲密的名字,一般不喊。好似和这个词相似度高的都是比较奇怪的角色。

无忌是关系熟了以后,平辈或者长辈可以称呼的名字。还有周姑娘,殷姑娘等

张无忌是通用的名字,人人可以称呼 和马甲联系密切。

张公子是礼貌尊称。 例如,黄衫女子,汝阳王等

张教主是头衔。既要尊重,也表示其实不太熟,有时还有些敌意。 例如: 朱元璋

注:

1、图是Networkx 基于Word2vex画出来了,上面的描述是我的人工分析。 

2、赵敏不在上面的网络关系图中。Word2Vec计算出来 张无忌和赵敏 相似度不太高。有些出乎我的意料。 仔细回忆一下,当年看此书时,突然就发现二人在一起了,显得比较突兀。推想起来,书中世界二人成婚了,如果变成现实世界,二人关系比较悬。

二、实现过程

主要步骤:

准备语料

  1. 倚天屠龙记 小说的文本文件

  2. 自定义分词词典 (小说中的人物名,网上有现成的,约180个)

  3. 停用词表

准备工具

  1. Python Pandas, Numpy,Scipy(标准库)

  2. Jieba(中文分词)

  3. Word2vec (单词向量化工具,可以计算单词之间的详细度)

  4. Networks(网络图工具,用于展示复杂的网络关系

数据预处理

  1. 文本文件转发成utf8(pandas)

  2. 文本文件分句,分词(Jieba)

  3. 文本文件分句,分词, 分析词性,主要是人名(Jieba)

  4. 更新自定义词典,重新分词(整个过程需要几遍,直至满意)

  5. 手工少量删除(分词出来的人名误判率不高,但是还是存在一些。例如:赵敏笑道,可以被识别的 一个叫 赵敏笑的人。 这部分工作还需要手工做。 除非有更好的分词工具,或者可以训练的分词工具,才能解决这一问题。

Word2Vec 训练模型。这个模型可以计算两个人之间的相似度

  1. 采用300个维度

  2. 过滤词频小于20次

  3. 滑动窗口 为20

  4. 下采样:0.001

生成实体关系矩阵。

  1. 网上没找找到现成库,我就自己写了一个。

  2. N*N 维度。 N是人名数量。

  3. 用上面WordVec的模型来,填充实体关系矩阵

NetworkX 生成网络图

  1. 节点是人名

  2. 边是两个节点之间的线条。也就是两个人之间的关系。

三、部分代码实现(因篇幅有限,获取完整代码请关注公众号编程狗回复0321获取)

初始化

  
  1. import numpy as np

  2. import pandas as pd

  3. import jieba

  4. import jieba.posseg as posseg

  5. %matplotlib inline

数据分词,清洗

  
  1. renming_file = "yttlj_renming.csv"

  2. jieba.load_userdict(renming_file)

  3. stop_words_file = "stopwordshagongdakuozhan.txt"

  4. stop_words = pd.read_csv(stop_words_file,header=None,quoting=3,sep="\t")[0].values

  5. corpus = "yttlj.txt"

  6. yttlj = pd.read_csv(corpus,encoding="gb18030",header=None,names=["sentence"])

  7. def cut_join(s):

  8.    new_s=list(jieba.cut(s,cut_all=False)) #分词

  9.    #print(list(new_s))

  10.    stop_words_extra =set([""])

  11.    for seg in new_s:

  12.        if len(seg)==1:

  13.            #print("aa",seg)

  14.            stop_words_extra.add(seg)

  15.    #print(stop_words_extra)

  16.    #print(len(set(stop_words)| stop_words_extra))

  17.    new_s =set(new_s) -set(stop_words)-stop_words_extra

  18.    #过滤标点符号

  19.    #过滤停用词

  20.    result = ",".join(new_s)

  21.    return  result

  22. def extract_name(s):

  23.    new_s=posseg.cut(s) #取词性

  24.    words=[]

  25.    flags=[]

  26.    for k,v in new_s:

  27.        if len(k)>1:

  28.            words.append(k)

  29.            flags.append(v)

  30.    full_wf["word"].extend(words)

  31.    full_wf["flag"].extend(flags)

  32.    return len(words)

  33. def check_nshow(x):

  34.    nshow = yttlj["sentence"].str.count(x).sum()

  35.    #print(x, nshow)

  36.    return nshow

  37. # extract name & filter times

  38. full_wf={"word":[],"flag":[]}

  39. possible_name = yttlj["sentence"].apply(extract_name)

  40. #tmp_w,tmp_f

  41. df_wf = pd.DataFrame(full_wf)

  42. df_wf_renming = df_wf[(df_wf.flag=="nr")].drop_duplicates()

  43. df_wf_renming.to_csv("tmp_renming.csv",index=False)

  44. df_wf_renming = pd.read_csv("tmp_renming.csv")

  45. df_wf_renming.head()

  46. df_wf_renming["nshow"] = df_wf_renming.word.apply(check_nshow)

  47. df_wf_renming[df_wf_renming.nshow>20].to_csv("tmp_filtered_renming.csv",index=False)

  48. df_wf_renming[df_wf_renming.nshow>20].shape

  49. #手工编辑,删除少量非人名,分词错的人名

  50. df_wf_renming=pd.read_csv("tmp_filtered_renming.csv")

  51. my_renming = df_wf_renming.word.tolist()

  52. external_renming = pd.read_csv(renming_file,header=None)[0].tolist()

  53. combined_renming = set(my_renming) |set(external_renming)

  54. pd.DataFrame(list(combined_renming)).to_csv("combined_renming.csv",header=None,index=False)

  55. combined_renming_file ="combined_renming.csv"

  56. jieba.load_userdict(combined_renming_file)

  57. # tokening

  58. yttlj["token"]=yttlj["sentence"].apply(cut_join)

  59. yttlj["token"].to_csv("tmp_yttlj.csv",header=False,index=False)

  60. sentences = yttlj["token"].str.split(",").tolist()

Word2Vec 向量化训练

  
  1. # Set values for various parameters

  2. num_features = 300    # Word vector dimensionality                      

  3. min_word_count = 20   # Minimum word count                        

  4. num_workers = 4       # Number of threads to run in parallel

  5. context = 20          # Context window size                                                                                    

  6. downsampling = 1e-3   # Downsample setting for frequent words

  7. # Initialize and train the model (this will take some time)

  8. from gensim.models import word2vec

  9. model_file_name = 'yttlj_model.txt'

  10. #sentences = w2v.LineSentence('cut_jttlj.csv')

  11. model = word2vec.Word2Vec(sentences, workers=num_workers, \

  12.            size=num_features, min_count = min_word_count, \

  13.            window = context, \

  14.            sample = downsampling

  15.            )

  16. model.save(model_file_name)  

建立实体关系矩阵

  
  1. entity = pd.read_csv(combined_renming_file,header=None,index_col=None)

  2. entity = entity.rename(columns={0:"Name"})

  3. entity = entity.set_index(["Name"],drop=False)

  4. ER = pd.DataFrame(np.zeros((entity.shape[0],entity.shape[0]),dtype=np.float32),index=entity["Name"],columns=entity["Name"])

  5. ER["tmp"] = entity.Name

  6. def check_nshow(x):

  7.    nshow = yttlj["sentence"].str.count(x).sum()

  8.    #print(x, nshow)

  9.    return nshow

  10. ER["nshow"]=ER["tmp"].apply(check_nshow)

  11. ER = ER.drop(["tmp"],axis=1)

  12. count = 0

  13. for i in entity["Name"].tolist():

  14.    count +=1

  15.    if count % round(entity.shape[0]/10) ==0:

  16.        print("{0:.1f}% relationship has been checked".format(100*count/entity.shape[0]))

  17.    elif count == entity.shape[0]:

  18.        print("{0:.1f}% relationship has been checked".format(100*count/entity.shape[0]))

  19.    for j in entity["Name"]:

  20.        relation =0

  21.        try:

  22.            relation = model.wv.similarity(i,j)

  23.            ER.loc[i,j] = relation

  24.            if i!=j:

  25.                ER.loc[j,i] = relation

  26.        except:

  27.            relation = 0

  28. ER.to_hdf("ER.h5","ER")

NetworkX 展示人物关系图

  
  1. import networkx as nx

  2. import matplotlib.pyplot as plt

  3. import pandas as pd

  4. import numpy as np

  5. import pygraphviz

  6. from networkx.drawing.nx_agraph import graphviz_layout


本文作者

王勇,Python中文社区专栏作者,雪球ID:快乐_爸,目前感兴趣项目商业分析、Python、机器学习、Kaggle。17年项目管理,通信业干了11年项目经理管合同交付,制造业干了6年项目管理:PMO,变革,生产转移,清算和资产处理。MBA, PMI-PBA, PMP。


因篇幅有限,获取完整代码请关注公众号编程狗回复0321获取

点击下方阅读原文免费成为Python中文社区会员

这篇关于Python自然语言处理分析倚天屠龙记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/841306

相关文章

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

PHP应用中处理限流和API节流的最佳实践

《PHP应用中处理限流和API节流的最佳实践》限流和API节流对于确保Web应用程序的可靠性、安全性和可扩展性至关重要,本文将详细介绍PHP应用中处理限流和API节流的最佳实践,下面就来和小编一起学习... 目录限流的重要性在 php 中实施限流的最佳实践使用集中式存储进行状态管理(如 Redis)采用滑动

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

Python实现精确小数计算的完全指南

《Python实现精确小数计算的完全指南》在金融计算、科学实验和工程领域,浮点数精度问题一直是开发者面临的重大挑战,本文将深入解析Python精确小数计算技术体系,感兴趣的小伙伴可以了解一下... 目录引言:小数精度问题的核心挑战一、浮点数精度问题分析1.1 浮点数精度陷阱1.2 浮点数误差来源二、基础解决

使用Python实现Word文档的自动化对比方案

《使用Python实现Word文档的自动化对比方案》我们经常需要比较两个Word文档的版本差异,无论是合同修订、论文修改还是代码文档更新,人工比对不仅效率低下,还容易遗漏关键改动,下面通过一个实际案例... 目录引言一、使用python-docx库解析文档结构二、使用difflib进行差异比对三、高级对比方

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本