赞
踩
要知道,原始文本是不能直接被机器学习到的,因为机器通常需要以数值型的、定长的数据作为输入。
原始文本是字符串或字符串集合。
数值型、定长的数据是浮点型或整型的向量。
为了让原始为本转化成数值型地、定长的向量,sklearn提供了三种常用的工具:
以上三种工具存在一种递进关系。
单独使用方法1的向量化方法有:one-hot编码、hash编码
使用方法1 + 方法2的向量化方法有:基于词袋的向量化
使用方法1 + 方法2 + 方法3的向量化方法有:TF-IDF
词袋的原名为Bag of Word,又称BOW,详细信息可以参考NLP之词袋模型一。
使用BOW进行文本向量化时,由于词袋特别大,会产生特别长的词向量。另一方面,一条文本通常只包含词袋中的一部分词,也就是说,向量化后的词向量中有特别多的0值,非常稀疏。
稀疏编码可以通过索引=>词频的键值对表示词向量,减少不必要的存储空间和数值计算。
sklearn中使用scipy.sparse
中的方法进行稀疏编码。
from sklearn.feature_extraction.text import CountVectorizer
CountVectorizer
类可以执行令牌化和词频统计操作,可以对文本进行基于词袋的向量化。下面使用一个例子演示该类的使用,首先是初始化和训练。
vectorizer = CountVectorizer()
corpus = [
'This is the first document.',
'This is the second document.',
'And the third one.',
'Is this the first document?'
]
X = vectorizer.fit_transform(corpus)
print X
'''输出
<4x9 sparse matrix of type '<... 'numpy.int64'>' with 19 stored elements in Compressed Sparse ... format>
'''
完成训练后,查看一下提取到词袋中的字符串,再查看一下向量化后的文本集合。
print vectorizer.get_feature_names()
'''输出
'and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this'
'''
print X.toarray()
'''输出
[[0, 1, 1, 1, 0, 0, 1, 0, 1],
[0, 1, 0, 1, 0, 2, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 1, 1, 0],
[0, 1, 1, 1, 0, 0, 1, 0, 1]]
'''
对向量化结果的解释:
输出一个2D数组。4行对应4条文本,9列对应词袋的大小。
原始文本中的标点符号,如’.‘和’?'都被自动过滤了。
词袋中的第一个单词’and‘,对应第一列;第二个单词’document‘对应第二列,以此类推。
预测新的文本。
print vectorizer.transform(['Something completely new.']).toarray()
'''输出
[[0, 0, 0, 0, 0, 0, 0, 0, 0]]
'''
新文本中的词都不存在于词袋中,因此向量化的结果全是0.
通过上面的例子,可以发现CountVectorizer
自带分词功能,可以将文本按空格分开,并且过滤标点符号。这个功能是由analye
完成的。
在之前的例子中,analyze默默地发挥作用。现在,我们看看它独立工作的效果,如下所示。
analyze = vectorizer.build_analyzer()
print analyze("This is a text document to analyze.")
'''输出
'this', 'is', 'text', 'document', 'to', 'analyze'
'''
我们可以使用默认的analyze,也可以根据需求重写analyze。
基于词袋的向量化用词频值代替原始文本,很容易丢失文本中的位置关系。比如 ‘This is the first document.’ 和 ‘Is this the first document?’ 有相同的词向量表示,但它们的意思其实不同。
Q:怎么办?
A:使用N-gram。
这里我们使用2-gram。
bigram_vectorizer = CountVectorizer(ngram_range=(1, 2), token_patter=r'\b\w+\b', min_df=1) analyze = bigram_vectorizer.build_analyzer() assert analyze('Bi-grams are cool!') == (['bi', 'grams', 'are', 'cool', 'bi grams', 'grams are', 'are cool']) X_2 = bigram_vectorizer.fit_transform(corpus).toarray() print bigram_vectorizer.get_feature_names() '''输出 u'and', u'and the', u'document', u'first', u'first document', u'is', u'is the', u'is this', u'one', u'second', u'second document', u'the', u'the first', u'the second', u'the third', u'third', u'third one', u'this', u'this is', u'this the' ''' print X_2 '''输出 [[0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0], [0, 0, 1, 0, 0, 1, 1, 0, 0, 2, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0], [1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0], [0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1]] '''
参数解析:
ngram_range
: tuple (min_n, max_n)
表示ngram中n的取之范围,min_n<=n<=max_n。当ngram_range=(1,2)时,n取1和2。
token_pattern
: string
用于传入正则表达式,正则表达式界定一个token。在自然语言处理中,token表示一个word或者一个字。
min_df
: float in range [0.0, 1.0] or int, default=1
如果是float,当token在文本中出现的比例小于min_df时,过滤该token。
如果是int,当token在文本中出现的频次小于min_df时,过滤该token。
默认为int,值为1。
停用词指没有意义的词,如:“and”, “the”, "him"或者中文中的“的”,“了”,“这”。
CountVectorizer
提供了一个参数,用来传入停用词。
参数stop_words
: string {‘english’}, list, or None (default)
不了解TF-IDF的朋友可以戳这里:TF-IDF与余弦相似性的应用。不过,sklearn中TF-IDF的计算方式有些不同。
TF,即term-frequency,是一个token在文本中出现的频次。
IDF,即inverse document-frequency,是逆文档频率,用作权重。
idf ( t ) = log 1 +
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。