用Python进行一些简单的自然语言处理的教程


Posted in Python onMarch 31, 2015

本月的每月挑战会主题是NLP,我们会在本文帮你开启一种可能:使用pandas和python的自然语言工具包分析你Gmail邮箱中的内容。

NLP-风格的项目充满无限可能:

  •     情感分析是对诸如在线评论、社交媒体等情感内容的测度。举例来说,关于某个话题的tweets趋向于正面还是负面的意见?一个新闻网站涵盖的主题,是使用了更正面/负面的词语,还是经常与某些情绪相关的词语?这个“正面”的Yelp点评不是很讽刺么?(祝最后去的那位好运!)
  •     分析语言在文学中的使用,进而衡量词汇或者写作风格随时间/地区/作者的变化趋势.
  •     通过识别所使用的语言的关键特征,标记是否为垃圾内容。
  •     基于评论所覆盖的主题,使用主题抽取进行相似类别的划分。
  •     通过NLTK's的语料库,应用Elastisearch和WordNet的组合来衡量Twitter流API上的词语相似度,进而创建一个更好的实时Twitter搜索。
  •     加入NaNoGenMo项目,用代码生成自己的小说,你可以从这里大量的创意和资源入手。

将Gmail收件箱加载到pandas

让我们从项目实例开始!首先我们需要一些数据。准备你的Gmail的数据存档(包括你最近的垃圾邮件和垃圾文件夹)。

https://www.google.com/settings/takeout

现在去散步吧,对于5.1G大小的信箱,我2.8G的存档需要发送一个多小时。

当你得到数据并为工程配置好本地环境之后好,使用下面的脚本将数据读入到pandas(强烈建议使用IPython进行数据分析)
 

from mailbox import mbox
import pandas as pd
 
def store_content(message, body=None):
 if not body:
  body = message.get_payload(decode=True)
 if len(message):
  contents = {
   "subject": message['subject'] or "",
   "body": body,
   "from": message['from'],
   "to": message['to'],
   "date": message['date'],
   "labels": message['X-Gmail-Labels'],
   "epilogue": message.epilogue,
  }
  return df.append(contents, ignore_index=True)
 
# Create an empty DataFrame with the relevant columns
df = pd.DataFrame(
 columns=("subject", "body", "from", "to", "date", "labels", "epilogue"))
 
# Import your downloaded mbox file
box = mbox('All mail Including Spam and Trash.mbox')
 
fails = []
for message in box:
 try:
  if message.get_content_type() == 'text/plain':
   df = store_content(message)
  elif message.is_multipart():
   # Grab any plaintext from multipart messages
   for part in message.get_payload():
    if part.get_content_type() == 'text/plain':
     df = store_content(message, part.get_payload(decode=True))
     break
 except:
  fails.append(message)

上面使用Python的mailbox模块读取并解析mbox格式的邮件。当然还可以使用更加优雅的方法来完成(比如,邮件中包含大量冗余、重复的数据,像回复中嵌入的“>>>”符号)。另外一个问题是无法处理一些特殊的字符,简单起见,我们进行丢弃处理;确认你在这一步没有忽略信箱中重要的部分。

需要注意的是,除了主题行,我们实际上并不打算利用其它内容。但是你可以对时间戳、邮件正文进行各种各样有趣的分析,通过标签进行分类等等。鉴于这只是帮助你入门的文章(碰巧会显示来自我自己信箱中的结果),我不想去考虑太多细节。

查找常用词语

现在我们已经得到了一些数据,那么来找出所有标题行中最常用的10个词语:
 

# Top 10 most common subject words
from collections import Counter
 
subject_word_bag = df.subject.apply(lambda t: t.lower() + " ").sum()
 
Counter(subject_word_bag.split()).most_common()[:10]
 
[('re:', 8508), ('-', 1188), ('the', 819), ('fwd:', 666), ('to', 572), ('new', 530), ('your', 528), ('for', 498), ('a', 463), ('course', 452)]

嗯,那些太常见了,下面尝试对常用词语做些限制:
 

from nltk.corpus import stopwords
stops = [unicode(word) for word in stopwords.words('english')] + ['re:', 'fwd:', '-']
subject_words = [word for word in subject_word_bag.split() if word.lower() not in stops]
Counter(subject_words).most_common()[:10]
 
[('new', 530), ('course', 452), ('trackmaven', 334), ('question', 334), ('post', 286), ('content', 245), ('payment', 244), ('blog', 241), ('forum', 236), ('update', 220)]

除了人工移除几个最没价值的词语,我们也使用了NLTK的停用词语料库,使用前需要进行傻瓜式安装。现在可以看到我收件箱中的一些典型词语,但通常来讲在英文文本中并不一定同样是典型的。

二元词组和搭配词

NLTK可以进行另外一个有趣的测量是搭配原则。首先,我们来看下常用的“二元词组”,即经常一起成对出现的两个单词的集合:
 

from nltk import collocations
bigram_measures = collocations.BigramAssocMeasures()
bigram_finder = collocations.BigramCollocationFinder.from_words(subject_words)
 
# Filter to top 20 results; otherwise this will take a LONG time to analyze
bigram_finder.apply_freq_filter(20)
for bigram in bigram_finder.score_ngrams(bigram_measures.raw_freq)[:10]:
 print bigram
 
(('forum', 'content'), 0.005839453284373725)
(('new', 'forum'), 0.005839453284373725)
(('blog', 'post'), 0.00538045695634435)
(('domain', 'names'), 0.004870461036311709)
(('alpha', 'release'), 0.0028304773561811506)
(('default', 'widget.'), 0.0026519787841697267)
(('purechat:', 'question'), 0.0026519787841697267)
(('using', 'default'), 0.0026519787841697267)
(('release', 'third'), 0.002575479396164831)
(('trackmaven', 'application'), 0.002524479804161567)

我们可以对三元词组(或n元词组)重复相同的步骤来查找更长的短语。这个例子中,“new forum content”是出现次数最多的三元词组,但是在上面例子的列表中,它却被分割成两部分并位居二元词组列表的前列。

另外一个稍微不同类型的搭配词的度量是基于点间互信息(pointwise mutual information)的。本质上,它所度量的是给定一个我们在指定文本中看到的单词,相对于他们通常在全部文档中单独出现的频率,另外一个单词出现的可能性。举例来说,通常,如果我的邮件主题使用单词“blog”与/或“post”很多,那么二元组“blog post”并不是一个有趣的信号,因为一个单词仍然可能不和另一个单词同时出现。根据这条准则,我们得到一个不同的二元组的集合。
 

for bigram in bigram_finder.nbest(bigram_measures.pmi, 5):
 print bigram
 
('4:30pm', '5pm')
('motley', 'fool')
('60,', '900,')
('population', 'cap')
('simple', 'goods')

因此,我没有收到很多提到单词“motley”或者“fool”的邮件主题,但是当我看到其中任意一个,那么“Motley Fool”可能是相关联的。

情感分析

最后,让我们尝试一些情感分析。为了快速入门,我们可以使用以NLTK为基础的TextBlob库,它提供了对于大量的常用NLP任务的简单访问。我们可以使用它内建的情感分析(基于模式)来计算主题的“极性(polarity)”。从,表示高度负面情绪的-1到表示正面情绪的1,其中0为中性(缺乏一个明确的信号)

接下来:分析一段时间内的你的收件箱;看看是否能够通过邮件分类,确定正文的发送者/标签/垃圾这些基本属性。使用潜在语义索引去揭示所涵盖的最常用的常规主题。将你的发件文件夹输入到马尔科夫模型(Markov model)中,结合词性标注生成看起来连贯的自动回复

请让我们知道你是否使用NLP尝试了有趣的项目分支,包含一份开源库将作为加分点。你可以在challenge.hackpad.com看下前面的展示,以找到更多的灵感!

Python 相关文章推荐
如何处理Python3.4 使用pymssql 乱码问题
Jan 08 Python
Python WXPY实现微信监控报警功能的代码
Oct 20 Python
python爬取足球直播吧五大联赛积分榜
Jun 13 Python
linux安装Python3.4.2的操作方法
Sep 28 Python
python_opencv用线段画封闭矩形的实例
Dec 05 Python
Python 函数返回值的示例代码
Mar 11 Python
解决Django生产环境无法加载静态文件问题的解决
Apr 23 Python
django url到views参数传递的实例
Jul 19 Python
Pycharm+django2.2+python3.6+MySQL实现简单的考试报名系统
Sep 05 Python
python如何查看安装了的模块
Jun 23 Python
用Python 执行cmd命令
Dec 18 Python
python简单验证码识别的实现过程
Jun 20 Python
用Python制作在地图上模拟瘟疫扩散的Gif图
Mar 31 #Python
以一段代码为实例快速入门Python2.7
Mar 31 #Python
11个并不被常用但对开发非常有帮助的Python库
Mar 31 #Python
Python的Flask框架中@app.route的用法教程
Mar 31 #Python
使用Python的Flask框架实现视频的流媒体传输
Mar 31 #Python
在Python3中初学者应会的一些基本的提升效率的小技巧
Mar 31 #Python
使用IronPython把Python脚本集成到.NET程序中的教程
Mar 31 #Python
You might like
使用NetBeans + Xdebug调试PHP程序的方法
2011/04/12 PHP
Jquery 获取表单text,areatext,radio,checkbox,select值的代码
2009/11/12 Javascript
jquery tab标签页的制作
2010/05/10 Javascript
js 纯数字不重复排列的另类方法
2010/07/17 Javascript
html dom节点操作(获取/修改/添加或删除)
2014/01/23 Javascript
JavaScript Promise启示录
2014/08/12 Javascript
jQuery获取对象简单实现方法小结
2014/10/30 Javascript
有效提高JavaScript执行效率的几点知识
2015/01/31 Javascript
javascript实现下班倒计时效果的方法(可桌面通知)
2015/07/10 Javascript
Javascript的表单验证-初识正则表达式
2016/03/18 Javascript
js时间控件只显示年月
2017/01/08 Javascript
手机注册发送验证码倒计时的简单实例
2017/11/15 Javascript
JavaScript动态添加数据到表单并提交的几种方式
2019/06/26 Javascript
微信小程序 组件的外部样式externalClasses使用详解
2019/09/06 Javascript
[01:02]2014 DOTA2国际邀请赛中国区预选赛 现场抢先看
2014/05/22 DOTA
[00:15]TI9观赛名额抽取
2019/07/10 DOTA
Python中你应该知道的一些内置函数
2017/03/31 Python
详解Python里使用正则表达式的ASCII模式
2017/11/02 Python
完美解决安装完tensorflow后pip无法使用的问题
2018/06/11 Python
win10系统下Anaconda3安装配置方法图文教程
2018/09/19 Python
Python按钮的响应事件详解
2019/03/04 Python
Python实现带下标索引的遍历操作示例
2019/05/30 Python
python障碍式期权定价公式
2019/07/19 Python
pyftplib中文乱码问题解决方案
2020/01/11 Python
利用Python制作动态排名图的实现代码
2020/04/09 Python
Python自动化测试中yaml文件读取操作
2020/08/20 Python
介绍一下linux文件系统分配策略
2012/11/17 面试题
迟到检讨书400字
2014/01/13 职场文书
导游个人求职信
2014/04/25 职场文书
县委常委班子专题民主生活会查摆问题及整改措施
2014/09/27 职场文书
大学生党员自我评价
2015/03/04 职场文书
幼儿园感恩节活动总结
2015/03/24 职场文书
感谢信的技巧及范例
2019/05/15 职场文书
个人工作总结(管理人员)范文
2019/08/13 职场文书
Python3接口性能测试实例代码
2021/06/20 Python
一篇文章带你学习Mybatis-Plus(新手入门)
2021/08/02 Java/Android