您的位置:首页 > 其它

如何对文本提取特征

2017-05-22 21:56 204 查看

问题来源

做文本分类这样的问题,需要从大量语料中提取特征,并将这些文本特征变换为数值特征。

假设我们有下面3个样本,怎么将他们转换为数值特征呢?

样本文本
1God is love
2OpenGL on the GPU is fast
3Doctor David is PHD

方法1:Bags of words

这种所谓
Bags of words
的特征,是将训练集中所有出现过的单词做成一个字典,统计每个单词出现的次数,作为特征。本文例子中有3个样本,共出现了13个单词,出去3个is是重复出现的,可获得一个由11个单词组成的字典。统计这11个单词在每个样本中的出现次数,可得:

Bags of words特征


样本daviddoctorfastgodgpuisloveonopenglphdthe
100010110000
200101101101
311000100010
我们也可以用
sklearn
中的
sklearn.feature_extraction.text.CountVectorizer
来获取
Bags of words特征


基于sklearn获取
Bags of words特征
的python代码


# 原始语料,3个文本
strs_train =[
'God is love',
'OpenGL on the GPU is fast',
'Doctor David is PHD']
# 提取特征
from sklearn.feature_extraction.text import CountVectorizer
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(strs_train)
X_train_counts.shape
# 查看数值特征
X_train_counts.todense()#转换成数值特征Bags of words
# 查看特征名
count_vect.vocabulary_#特征名


用代码计算得到的特征与理论统计得到的特征完全相同

方法2:TF

TF
词频
(Term Frequency)。
Bags of words特征
统计的是单词的出现次数,这样在长文本中,单词的出现次数会大于短文本,可能造成不公平问题。所以
TF特征
就被提出,用于统计词频。

TF=(某个单词在文本中的出现次数)/(文本中的总单词数)。

根据
TF
的计算公式,可得
TF特征
如下。

TF特征


样本daviddoctorfastgodgpuisloveonopenglphdthe
10000.3300.330.330000
2000.1700.170.1700.170.1700.17
30.250.250000.250000.250
我们也可以用
sklearn
中的
sklearn.feature_extraction.text.TfidfTransformer
来获取
TF特征


from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
# 先提取 Bags of words特征
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(strs_train)
# 再基于Bags of words特征,变换为TF特征
tf_transformer = TfidfTransformer(use_idf=False).fit(X_train_counts)
X_train_tf = tf_transformer.transform(X_train_counts)
X_train_tf.shape
# 查看数值特征
X_train_tf.todense()#转换成数值特征Bags of words
# 查看特征名
count_vect.vocabulary_#特征名


经计算,我们发现,代码算得到的特征与理论公式计算得到的特征数值不相同!!

这是什么情况呢?经查看
sklearn
源码。发现
sklearn
计算TF的方式与理论公式不一致,它只对
Bags of words特征
矩阵做了
Normalization
,就将结果作为
TF特征
。如果在计算
TF特征
时,去掉
Normalization
(代码
TfidfTransformer(norm=None, use_idf=False).fit(X_train_counts)
),如下,就得到了与
Bags of words特征
完全相同的结果。

from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
# 先提取 Bags of words特征
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(strs_train)
# 再基于Bags of words特征,变换为TF特征
tf_transformer = TfidfTransformer(norm=None, use_idf=False).fit(X_train_counts)
X_train_tf = tf_transformer.transform(X_train_counts)
X_train_tf.shape
# 查看数值特征
X_train_tf.todense()#转换成数值特征Bags of words
# 查看特征名
count_vect.vocabulary_#特征名


仔细想想
sklearn
的做法也没有问题,
TF特征
的提出,不就是为了去除文档大小对结果的影响吗。
Normalization
不也能达到同样效果么。

并且我们这里也要明白,TF的是可以有不同的定义的,本文给出的是理论上用的最多的计算公式。但
sklearn
计算TF就用了其他的方法。一些常用的TF定义见这里

方法3:TF-IDF

IDF
逆文档频率
。逆文档频率 = log(语料中的文档总数/含有该词的文档数加1)。得到
逆文档频率
后,TF-IDF = TF*IDF。

TF-IDF特征


样本daviddoctorfastgodgpuisloveonopenglphdthe
10000.33*log(1.5)00.33*log(0.75)0.33*log(1.5)0000
2000.17*log(1.5)00.17*log(1.5)0.17*log(1.5)00.17*log(1.5)0.17*log(0.75)00.17*log(1.5)
30.25*log(1.5)0.25*log(1.5)0000.25*log(0.75)0000.25*log(1.5)0
我们也可以用
sklearn
中的
sklearn.feature_extraction.text.TfidfTransformer
来获取
TF-IDF特征


from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
# 先提取 Bags of words特征
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(strs_train)
# 再基于Bags of words特征,变换为TF-IDF特征
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
X_train_tfidf.todense()


同理,
sklearn
计算
TF-IDF特征
的方法也和本文的理论公式有所区别,并且最终还对计算结果做了
Normalization
。具体细节见源码注释

方法4:FeatureHasher

FeatureHasher
能将string通过Hash算法
Murmurhash3
,变为数值化的矩阵。

在使用
FeatureHasher
前,需要将原始语料的字符格式变为如下格式。

[{'God': 1, 'is': 1, 'love': 1},
{'GPU': 1, 'OpenGL': 1, 'fast': 1, 'is': 1, 'on': 1, 'the': 1},
{'David': 1, 'Doctor': 1, 'PHD': 1, 'is': 1}]


完整代码如下:

from sklearn.feature_extraction import FeatureHasher

# 将原始数据Hash到10维Feature
h = FeatureHasher(n_features=10, non_negative=True)

# 将数据组成D格式
D=[]
for s in strs_train:
tmp = {}
for w in s.split(' '):
tmp[w] = 1
D.append(tmp)

f = h.transform(D)
f.toarray()


FeatureHasher
特征


样本x1x2x3x4x5x6x7x8x9x10
10000000100
20101000011
30000101101

结论

对于文本、字符串数据,我们有4种常用方法(
Bags of words
TF
TF-IDF
FeatureHasher
),将原始数据变为数值型数据。

本文例子所有源码参见Github

参考

(1)http://scikit-learn.org/stable/tutorial/text_analytics/working_with_text_data.html

(2)http://www.ruanyifeng.com/blog/2013/03/tf-idf.html

(3)http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.FeatureHasher.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: