如何对文本提取特征
2017-05-22 21:56
204 查看
问题来源
做文本分类这样的问题,需要从大量语料中提取特征,并将这些文本特征变换为数值特征。假设我们有下面3个样本,怎么将他们转换为数值特征呢?
样本 | 文本 |
---|---|
1 | God is love |
2 | OpenGL on the GPU is fast |
3 | Doctor David is PHD |
方法1:Bags of words
这种所谓Bags of words的特征,是将训练集中所有出现过的单词做成一个字典,统计每个单词出现的次数,作为特征。本文例子中有3个样本,共出现了13个单词,出去3个is是重复出现的,可获得一个由11个单词组成的字典。统计这11个单词在每个样本中的出现次数,可得:
Bags of words特征
样本 | david | doctor | fast | god | gpu | is | love | on | opengl | phd | the |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
3 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 |
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特征
样本 | david | doctor | fast | god | gpu | is | love | on | opengl | phd | the |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0.33 | 0 | 0.33 | 0.33 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0.17 | 0 | 0.17 | 0.17 | 0 | 0.17 | 0.17 | 0 | 0.17 |
3 | 0.25 | 0.25 | 0 | 0 | 0 | 0.25 | 0 | 0 | 0 | 0.25 | 0 |
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特征
样本 | david | doctor | fast | god | gpu | is | love | on | opengl | phd | the |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0.33*log(1.5) | 0 | 0.33*log(0.75) | 0.33*log(1.5) | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0.17*log(1.5) | 0 | 0.17*log(1.5) | 0.17*log(1.5) | 0 | 0.17*log(1.5) | 0.17*log(0.75) | 0 | 0.17*log(1.5) |
3 | 0.25*log(1.5) | 0.25*log(1.5) | 0 | 0 | 0 | 0.25*log(0.75) | 0 | 0 | 0 | 0.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特征
样本 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | x10 |
---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
2 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 |
3 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 |
结论
对于文本、字符串数据,我们有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
相关文章推荐
- 如何从doc文件里提取纯文本
- 文本特征提取方法研究
- 文本特征提取方法研究
- 文本特征提取方法研究
- 文本特征提取方法研究
- 文本特征提取方法研究
- 如何使用GIST+LIBLINEAR分类器提取CIFAR-10 dataset数据集中图像特征,并用测试数据进行实验
- 如何用Linux命令提取表格文本中的某列
- 如何用C#提取Word、Excel等文件的文本(无需安装Office)
- 网络挖掘技术——微博文本特征提取
- 文本特征提取方法研究
- 文本特征提取方法研究
- 文本特征提取方法研究
- .net 下如何将文档文件(Word, Pdf等) 中的文本提取出来
- .net 下如何将文档文件(Word, Pdf等) 中的文本提取出来
- 文本特征提取方法研究
- 从文本分类问题中的特征词选择算法追踪如何将数学知识,数学理论迁移到实际工程中去
- 文本特征提取方法研究
- 文本特征提取方法研究
- 数据挖掘:网络挖掘技术——微博文本特征提取