特征工程1:特征的抽取
特征工程
· 定义:特征工程是指将原始数据转换为特征向量。(比如一片文档包含文本等类型,将这些文本类型的数据转换为数字类型的数据,这个过程是为了计算机更好的理解数据)
· 目的:特征工程的处理直接影响模型的预测结果,目的也正是为了提高模型的预测效果。
· 内容:主要有三部分:
1、特征抽取
2、特征预处理
3、数据的降维
特征抽取
· 特征提取在python scikit-learn中的API是:sklearn.feature_extraction
文本特征抽取
下面主要介绍文本特征抽取的两种方式:count 词频统计和 tf-idf 重要性统计。
1. 词频统计
1.1 词频统计的API是CountVectorizer,对于每一个训练文本,它只考虑每种词汇在该训练文本中出现的频率,注意单个字符不进行统计,因为没有分类意义。
1.2 CountVectorizer会将文本中的词语转换为词频矩阵,然后调用fit_transform函数计算各个词语出现的次数。
1.3. fit_transform计算词语次数时,以空格划分,传统上只适用于英文的计算,当然,如果手动将中文文章中的词以空格划分,也可以使用,但是太繁琐,生产环境中肯定不会这样处理,针对于中文,我们可以先使用jieba这个中文分词工具进行分词,然后再用fit_transform进行计算。
scikit-learn文本特征抽取的用法
from sklearn.feature_extraction.text import CountVectorizer # 使用 CountVectorizer 将文本中的词语转换为词频矩阵
vec = CountVectorizer()
article1 = "A bad beginning makes a bad ending"
article2 = "A faithful friend is hard to find" # 使用 fit_transform 函数计算各个词语出现的次数,返回的是scipy中压缩行格式(csr_matrix)的稀疏矩阵
result = vec.fit_transform([article1, article2])
print(result) # 使用 get_feature_names 获取全部的特征值,即所有文本的关键字
print('所有出现过的单词:')
print(vec.get_feature_names()) # 使用 toarray 转化为numpy的数组形式,可以看到词频矩阵的结果
print("numpy数组,每个词的出现次数:")
print(result.toarray())
输出:
(0, 2) 1
(0, 8) 1
(0, 1) 1
(0, 0) 2
(1, 4) 1
(1, 9) 1
(1, 6) 1
(1, 7) 1
(1, 5) 1
(1, 3) 1
所有出现过的单词: ['bad', 'beginning', 'ending', 'faithful', 'find', 'friend', 'hard', 'is', 'makes', 'to']
numpy数组,每个词的出现次数:
[[2 1 1 0 0 0 0 0 1 0]
[0 0 0 1 1 1 1 1 0 1]]
1、上面输出的numpy数组:0轴(即每列)分别对应特征值列表中相应索引单词的出现次数,1轴(即每行)表示每个文档中各词的出现频率; 即:第一篇文章中"bad"出现两次,"beginning"出现一次,"ending"出现一次,"makes"出现一次; 第二篇文章中'faithful', 'find', 'friend', 'hard', 'is', 'to'各出现一次。 2、每个文档中的词,只是整个语料库中所有词的很小的一部分,这样会造成特征向量的稀疏性(很多值为0),为了解决存储和运算速度的问题,使用 Python 的 scipy.sparse 矩阵结构保存,所以 fit_transform 返回值的类型是 scipy 的矩阵类型,想以数组方式查看,需要调用 toarray 进行转化。
中文文本特征抽取
使用pip安装jieba分词库
代码:
from sklearn.feature_extraction.text import CountVectorizer
import jieba
vec = CountVectorizer()
article1 = "生命是什么呢,生命是时时刻刻不知如何是好"
article2 = "生活是什么呢,生活是这样的,有些事情还没有做,一定要做的,另有些事做了,没有做好,明天不散步了" # jieba分词返回的是一个生成器,转化为列表并用空格连接起来
c1 = ' '.join(list(jieba.cut(article1)))
c2 = ' '.join(list(jieba.cut(article2)))
result = vec.fit_transform([c1, c2]) # 获取特征,与英文相同,单个字符不统计
print(vec.get_feature_names())
print(result.toarray())
输出:
['一定', '不知', '事情', '什么', '做好', '如何是好', '散步', '时时刻刻', '明天', '有些', '没有', '生命', '生活', '这样']
[[0 1 0 1 0 1 0 1 0 0 0 2 0 0]
[1 0 1 1 1 0 1 0 1 2 2 0 2 1]]
2. TF-IDF 重要性统计
文章分类时,用上面统计词频的方式是有缺陷的,比如两篇文章中有很多相似的中性词(我们、昨天等),根据上面词频统计的方法就会将他们划为主题相似的文章,我们需要用另一种方法解决这个问题,就是 TF-IDF 统计法。
· TF-IDF 介绍
tf-idf是一种统计方法,用以评估某个字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在文件集中出现的频率成反比下降。
· 主要思想
如果某个词在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词的重要性较高,具有很好的类别区分能力。
· API
计算tf-idf重要性的API是TfidfVectorizer,它会根据指定的公式将文档中的词转换为概率表示。
代码:
from sklearn.feature_extraction.text import TfidfVectorizer # 实例化
tf = TfidfVectorizer() # 还是使用fit_transform这个方法进行转化计算
data = tf.fit_transform([c1, c2])
print('特征值:')
print(tf.get_feature_names())
print('重要性:')
print(tf.toarray())
输出:
特征值:
['一定', '不知', '事情', '什么', '做好', '如何是好', '散步', '时时刻刻', '明天', '有些', '没有', '生命', '生活', '这样']
重要性:
[[ 0. 0.36499647 0. 0.25969799 0. 0.36499647 0. 0.36499647 0. 0. 0. 0.72999294 0. 0. ]
[ 0.23245605 0. 0.23245605 0.1653944 0.23245605 0. 0.23245605 0. 0.23245605 0.4649121 0.4649121 0. 0.4649121 0.23245605]]
以上代码可以简单的看出每个词在每篇文章中的重要性; 比如第一篇中“生命”这个词的重要性是0.72
总结:
1、主要介绍了特征工程的意义;
2、文本特征抽取的两种方式:词频统计和TF-IDF重要性统计;
3、scikit-learn中各自API的简单使用;