当前位置:   article > 正文

如何对文本提取特征_文本转特征

文本转特征

问题来源

做文本分类这样的问题,需要从大量语料中提取特征,并将这些文本特征变换为数值特征。
假设我们有下面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_#特征名
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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

方法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_#特征名
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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

这是什么情况呢?经查看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_#特征名
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

仔细想想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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

同理,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}]
  • 1
  • 2
  • 3

完整代码如下:

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

FeatureHasher特征

样本x1x2x3x4x5x6x7x8x9x10
10000000100
20101000011
30000101101

结论

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

本文例子所有源码参见Github

参考

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/371962
推荐阅读
相关标签
  

闽ICP备14008679号