如何从文本中提取特征信息?

只愿长相守 提交于 2020-10-29 06:41:47

虽然之前也写过gensim库的word2vec的教程,但是对于文本分析的特征提取并不太理解。最近看了几篇scikit的外文教程,对机器学习中文本的特征提取有了一些了解。

首先做文本的机器学习(自然语言处理),我们要理解这几个概念:

  • 文档(document)这里是指一段单独的文本信息。这可能是一则短信、一条推特、一封邮件、一本书、或者一首歌词。一般一个文档对应于一个观测值或一行数据。

  • 语料(corpus) 文档的集合(语料大于等于1条文档)。这相当于我们要研究对象的所有文本数据

  • 单词或词语(token) 英文中对应的是单词,汉语是词语。例如“How are you”这个文档,是由how、are、you三个单词组成的。token相当于机器学习中的特征(列)。

首先让我们给出一个语料例子。

corpus = ["Hey hey hey lets go get lunch today :)",
           "Did you go home?",
           "Hey!!! I need a favor"]

CountVectorizer

首先我们要明白,计算机是不能从文本字符串中发现规律的。只有将字符串编码为计算机可以理解的数字,计算机才有可能发现文本中的规律。

最容易理解的实现思路:

  • 对文本编码,就是让词语与数字对应起来,建立基于给定文本的词典。(fit方法 )

  • 再根据词典对所有的文本数据进行转码。(transform方法)

scikit库的CountVectorize类就是这种思路。

from sklearn.feature_extraction.text import CountVectorizer

vectorize = CountVectorizer()

使用fit方法,CountVectorizer()类的会从corpus语料中学习到所有词语,进而构建出corpus词典。

#fit学会语料中的所有词语,构建词典
vectorize.fit(corpus)
CountVectorizer(analyzer='word', binary=False, decode_error='strict',
        dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
        lowercase=True, max_df=1.0, max_features=None, min_df=1,
        ngram_range=(1, 1), preprocessor=None, stop_words=None,
        strip_accents=None, token_pattern='(?u)\\b\\w\\w+\\b',
        tokenizer=None, vocabulary=None)
#这里我们查看下“词典”,也就是特征集(11个特征词)
vectorize.get_feature_names()
['did',
 'favor',
 'get',
 'go',
 'hey',
 'home',
 'lets',
 'lunch',
 'need',
 'today',
 'you']

这里,特征集(get_feature——name)返回的结果,有要注意的事情:

  • 所有的单词都是小写

  • 单词长度小于两个字母的,会被剔除掉

  • 标点符号会剔除掉

  • 不重复

  • 这个特征集是有顺序的

接下来会按照这个顺序去编码文本数据,这里会出现一个新概念文档-词频矩阵(document-term matrix),英文简写为dtm。我们让机器挖掘文本中的规律时,喂给机器的数据就是 这文档-词频矩阵(document-term matrix)

#构建 文档词频矩阵
dtm = vectorize.transform(corpus)dtm
<3x11 sparse matrix of type '<class 'numpy.int64'>'
    with 13 stored elements in Compressed Sparse Row format>

构建文档词频矩阵。结果3*11。

3指的是语料中的三个文档;11指的是corpus中11个特征词。为了方便我们理解,我用pandas库将其展现出来

import pandas as pd

pd.DataFrame(dtm.toarray(), columns = vectorize.get_feature_names())

从上面的dataframe表中,行代表一个文档,列代表特征词。比如第1行,hey列的所对应的单元格值为3,说明corpus中第一个document(Hey hey hey lets go get lunch today :) 出现了三次hey。

这里有一个我要提示的重点,在此时我们已经构件号了文档词频矩阵dtm,如果你还想加入新的文档。我们应该注意tranform和fit的区别。

new_document = ['Hey lets go get a drink tonight']
new_dtm = vectorize.transform(new_document)
pd.DataFrame(new_dtm.toarray(), columns=vectorize.get_feature_names())

即使new_document含有6个单词,但是在上面的dataframe表中只有4个特征词被有效编码,drink和tonight词未被表征。这是因为我们初识的corpus语料所构建的词典并未含有这些词。但是对文本进行特征表征时,使用的确实corpus所生产的词典。

我们机器学习所用的数据,一般被分成训练集和测试集。训练集是为了让机器学习数据的规律,测试集是为了验证规律的有效性。训练集本质上代表的是过去及现在已知的数据,测试集本质上代表的是未来的未知数据(现在不存在的数据),我们是用已知的数据预测未来。

所以我们只能让fit方法操作于训练集,构建基于过去或已知数据的特征集。

TfidfVectorizer

scikit库除了CountVectorizer类,还有TfidfVectorizer类。TF-IDF这个定义相信大家应该已经耳熟能详了:

TF 词频出现的次数 IDF = 1/(语料中含有该词语的文档的数目)

TF简单点说有的时候词语出现越多,这个词越是特征词。但同时,有些“的它呢”等无意义词出现的多并没有什么意义,反而是像“核能”这种词,虽然不怎么出现,但是一出现往往很具有特征性。

综合TF*IDF,就能很好的刻画一个词语是否具有表征文本信息能力,作为特征是否合适。有了上面的基础知识,我们接下来继续写代码,便于理解TFIDF

from sklearn.feature_extraction.text import TfidfVectorizer

def createDTM(corpus):    """构建文档词语矩阵"""    vectorize = TfidfVectorizer()    #注意fit_transform相当于fit之后又transform。    dtm = vectorize.fit_transform(corpus)        #打印dtm    return pd.DataFrame(dtm.toarray(), columns=vectorize.get_feature_names())    
corpus = ["Hey lets get lunch :)",
           "Hey!!! I need a favor"]
createDTM(corpus)

我们看到hey这个词在所有大于0的值里面,是最小的。因为hey同时出现在两个文档中,不具有文本的表征能力,所以TFIDF小。而favor和need因为他们仅仅出现在第二个文档中,所以他们的TFIDF值更高。

现在我们改变corpus内容。将第一个文档从Hey lets get lunch改为Hey hey hey lets get lunch。我们希望第一个文档的hey词频增大,进而使得其TFIDF值变大。

corpus = ["Hey hey hey lets get lunch :)",
           "Hey!!! I need a favor"]

createDTM(corpus)

我们发现第一个文档hey的TFIDF值变大,但这里有两点要注意:

  • 第一个文档中其余特征词的TFIDF值变小了

  • 第二个文档中hey的TFIDF未发生变化

上面的例子是通过TF词频操作TFIDF值的。下面我们从IDF出发,改变TFIDF值。

corpus = ["Hey hey hey lets get lunch :)",
           "I need a favor"]

createDTM(corpus)

由于hey只存在于文档一,且其词频是最多的,所有文档一的hey的TFIDF值最大。

文本处理分析

文本数据相似度的度量

对于中文,nltk能做哪些事情

gensim:用Word2Vec进行文本分析 

PMI点互信息计算

RAKE:快速自动抽取关键词算法

基于共现发现人物关系的python实现

用pyecharts制作词云图

留在网上的每个字,都在泄露你的身份


数据采集

视频讲解】Scrapy递归抓取简书用户信息

【实战视频】使用scrapy写爬虫-爬知乎live

如何将html中的表格数据保存下来

美团商家信息采集神器

gevent:异步理论与实战  

轻盈高效的异步访问库grequests库

selenium驱动器配置详解

爬虫神器PyQuery的使用方法

简易SQLite3数据库学习

当爬虫遭遇验证码,怎么办  

js2xml:将javascript字符串转换为xml  

extruct提取结构化数据


数据结构

优雅简洁的列表推导式

Get小技巧等分列表

如何对数据进行各种排序?

数据结构:队列与堆栈 

else除了跟if很搭,你还知道其他的关键词吗?

杂文

Python通过字符串调用函数

Python圈中的符号计算库-Sympy

Python中处理日期时间库的使用方法 

三分钟掌握文件格式识别

为什么你要为2019,而不是2018做计划?

2017年度15个最好的数据科学领域Python库

迅雷不给力,我DIY了个下载器

计算运行时间-装饰器实现

花十分钟,给爱机安装个MongoDB

使用Python登录QQ邮箱发送QQ邮件

WTF Python: 开启你的懵逼模式

8行代码实现微信聊天机器人




本文分享自微信公众号 - 大邓和他的Python(DaDengAndHisPython)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!