用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 相关文章推荐
在漏洞利用Python代码真的很爽
Aug 26 Python
Python递归遍历列表及输出的实现方法
May 19 Python
Python采用Django制作简易的知乎日报API
Aug 03 Python
总结python爬虫抓站的实用技巧
Aug 09 Python
简单实现python画圆功能
Jan 25 Python
Python中pandas dataframe删除一行或一列:drop函数详解
Jul 03 Python
Python切片操作深入详解
Jul 27 Python
浅谈Python中的bs4基础
Oct 21 Python
python tkinter实现彩球碰撞屏保
Jul 30 Python
Django-Scrapy生成后端json接口的方法示例
Oct 06 Python
python opencv常用图形绘制方法(线段、矩形、圆形、椭圆、文本)
Apr 12 Python
pycharm无法安装cv2模块问题
May 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
PHP下escape解码函数的实现方法
2010/08/08 PHP
php中使用in_array() foreach array_search() 查找数组是否包含时的性能对比
2015/04/14 PHP
php 从一个数组中随机的取出若干个不同的数实例
2016/12/31 PHP
laravel实现上传图片,并且制作缩略图,按照日期存放的代码
2019/10/16 PHP
FormValid0.5版本发布,带ajax自定义验证例子
2007/08/17 Javascript
基于Jquery的温度计动画效果
2010/06/18 Javascript
cookie中的path与domain属性详解
2013/12/18 Javascript
javascript 自定义回调函数示例代码
2014/09/26 Javascript
javacript使用break内层跳出外层循环分析
2015/01/12 Javascript
javascript制作sql转换为stringBuffer的小工具
2015/04/03 Javascript
jQuery实用技巧必备(上)
2015/11/02 Javascript
js实现图片无缝滚动特效
2020/03/19 Javascript
jQuery实现每隔几条元素增加1条线的方法
2016/06/27 Javascript
js实现简单数字变动效果
2017/11/06 Javascript
Bootstrap table中toolbar新增条件查询及refresh参数使用方法
2018/05/18 Javascript
vue动画效果实现方法示例
2019/03/18 Javascript
详解Vue项目引入CreateJS的方法(亲测可用)
2019/05/30 Javascript
jquery选择器和属性对象的操作实例分析
2020/01/10 jQuery
python操作xml文件示例
2014/04/07 Python
在Python编程过程中用单元测试法调试代码的介绍
2015/04/02 Python
python中xrange用法分析
2015/04/15 Python
以一个投票程序的实例来讲解Python的Django框架使用
2016/02/18 Python
Python的Flask框架及Nginx实现静态文件访问限制功能
2016/06/27 Python
Python连接数据库学习之DB-API详解
2017/02/07 Python
Python批量查询域名是否被注册过
2017/06/21 Python
使用python在本地电脑上快速处理数据
2017/06/22 Python
python 字符串只保留汉字的方法
2018/11/16 Python
Python编写打字训练小程序
2019/09/26 Python
Python中pass的作用与使用教程
2020/11/13 Python
高校自主招生自荐信
2013/12/09 职场文书
公司同意接收函
2014/01/13 职场文书
人事主管岗位职责说明书
2014/07/30 职场文书
写给老师的感谢信
2015/01/20 职场文书
收银员岗位职责
2015/02/03 职场文书
2015年司机年终工作总结
2015/05/14 职场文书
python tqdm用法及实例详解
2021/06/16 Python