特征工程之特征提取
特征提取即将任意数据(如文本或图像)转换为可用于机器学习的数字特征
注:特征值化是为了计算机更好的去理解数据
- 字典特征提取(特征离散化)
- 文本特征提取
- 图像特征提取(深度学习将介绍)
特征提取API
sklearn.feature_extraction
应用DictVectorizer实现对类别特征进行数值化、离散化
sklearn.feature_extraction.DictVectorizer(sparse=True,...)
DictVectorizer.fit_transform(X)
,X
: 字典或者包含字典的迭代器,返回值:返回sparse
矩阵DictVectorizer.inverse_transform(X)
:X
:array
数组或者sparse
矩阵 返回值:转换之前数据格式DictVectorizer.get_feature_names()
返回类别名称
应用
我们对以下数据进行特征提取
data = [
{'city': '北京', 'value' : 150},
{'city': '浙江', 'value': 10},
{'city': '上海', 'value': 50}
]
流程分析
- 实例化类
DictVectorizer
- 调用
fit_transform
方法输入数据并转化 (注意返回格式)
from sklearn.feature_extraction import DictVectorizer
if __name__ == '__main__':
data = [
{'city': '北京', 'value' : 150},
{'city': '浙江', 'value': 10},
{'city': '上海', 'value': 50}
]
# 示例化一个转化器类
transfer = DictVectorizer(sparse=False)
# 调用 transfer.fit_transform
data = transfer.fit_transform(data)
print('返回结果为:', data)
# 输出特征名字
print('特征名字为:', transfer.get_feature_names())
# 输出结果为
'''
返回结果为: [[ 0. 1. 0. 150.]
[ 0. 0. 1. 10.]
[ 1. 0. 0. 50.]]
特征名字为: ['city=上海', 'city=北京', 'city=浙江', 'value']
'''
注意观察没有加上 sparse=False
参数的结果
from sklearn.feature_extraction import DictVectorizer
if __name__ == '__main__':
data = [
{'city': '北京', 'value' : 150},
{'city': '浙江', 'value': 10},
{'city': '上海', 'value': 50}
]
# 示例化一个转化器类
transfer = DictVectorizer()
# 调用 transfer.fit_transform
data = transfer.fit_transform(data)
print('返回结果为:', data)
# 输出特征名字
print('特征名字为:', transfer.get_feature_names())
# 输出结果为
'''
返回结果为: (0, 1) 1.0
(0, 3) 150.0
(1, 2) 1.0
(1, 3) 10.0
(2, 0) 1.0
(2, 3) 50.0
特征名字为: ['city=上海', 'city=北京', 'city=浙江', 'value']
'''
可以看到没有加上 sparse=False
参数的结果为 sparse
矩阵,sparse
稀疏,将非零值 按位置表示出来,可以节省内存,提高加载效果
应用CountVectorizer实现对文本特征进行数值化
sklearn.feature_extraction.text.CountVectorizer(stop_words=[])
- 返回词频矩阵
stop_words
参数表示停用的词
CountVectorizer.fit_transform(X)
X
:文本或者包含文本字符串的可迭代对象- 返回值:返回
sparse
矩阵
CountVectorizer.inverse_transform(X)
X
:array
数组或者sparse
矩阵- 返回值:转换之前数据格
CountVectorizer.get_feature_names()
- 返回值:单词列表
sklearn.feature_extraction.text.TfidfVectorizer
应用
我们对以下数据进行特征提取
data = [
'Everyone is fighting their own battle.',
'To be free from their past.',
'To live in their present.',
'And to create their future.'
]
流程分析
- 实例化类
CountVectorizer
- 调用
fit_transform
方法输入数据并转化 (注意返回格式,利用toarray()
进行sparse
矩阵转化为array
数组)
from sklearn.feature_extraction.text import CountVectorizer
if __name__ == '__main__':
data = [
'Everyone is fighting their own battle.',
'To be free from their past.',
'To live in their present.',
'And to create their future.'
]
# 示例化一个转化器类
transfer = CountVectorizer()
# 调用 transfer.fit_transform
data_new = transfer.fit_transform(data)
print('返回结果为:', data_new.toarray())
# 输出特征名字
print('特征名字为:', transfer.get_feature_names())
# 输出结果为
'''
返回结果为: [[0 1 0 0 1 1 0 0 0 0 1 0 1 0 0 1 0]
[0 0 1 0 0 0 1 1 0 0 0 0 0 1 0 1 1]
[0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 1 1]
[1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1]]
特征名字为: ['and', 'battle', 'be', 'create', 'everyone', 'fighting', 'free', 'from', 'future', 'in', 'is', 'live', 'own', 'past', 'present', 'their', 'to']
'''
然而,当文本为中文时,由于每个字之间没有空格,所以在面对中文文本的时候,我们需要先进行分词:
jieba 分词处理
jieba.cut()
- 返回词语组成的生成器
需要安装 jieba
库
pip install jieba
案例分析
我们对python
之禅 进行特征提取
data = [
'优美胜于丑陋(Python以编写优美的代码为目标)',
'明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)',
'简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)',
'复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)',
'扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)',
'间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)',
'可读性很重要(优美的代码是可读的)',
'即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)',
'不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)',
'当存在多种可能,不要尝试去猜测',
'而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)',
'做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)',
'如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)',
'命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)'
]
- 分析
- 准备句子,利用
jieba.cut
进行分词 - 实例化
CountVectorizer
- 将分词结果变成字符串当作
fit_transform
的输入值
- 准备句子,利用
import jieba
from sklearn.feature_extraction.text import CountVectorizer
def cut_word(text):
return ' '.join(list(jieba.cut(text)))
if __name__ == '__main__':
data = [
'优美胜于丑陋(Python以编写优美的代码为目标)',
'明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)',
'简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)',
'复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)',
'扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)',
'间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)',
'可读性很重要(优美的代码是可读的)',
'即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)',
'不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)',
'当存在多种可能,不要尝试去猜测',
'而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)',
'做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)',
'如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)',
'命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)'
]
data_new = [cut_word(sent) for sent in data]
# print(data_new)
# 示例化一个转化器类
transfer = CountVectorizer(stop_words=['except', 'pass', '(', ')'])
# 调用 transfer.fit_transform
data_final = transfer.fit_transform(data)
print('返回结果为:', data_final.toarray())
# 输出特征名字
print('特征名字为:', transfer.get_feature_names())
应用TfidfVectorizer实现对文本特征进行数值化
Tf-idf文本特征提取
TF-IDF
的主要思想是:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TF-IDF
作用:用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。
公式
- 词频(term frequency,tf)指的是某一个给定的词语在该文件中出现的频率
- 逆向文档频率(inverse document frequency,idf)是一个词语普遍重要性的度量。某一特定词语的idf,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取以10为底的对数得到
tfidf = tf * idf
- 最终结果可以理解为重要程度
API
sklearn.feature_extraction.text.TfidfVectorizer(stop_words=None,...)
- 返回词的权重矩阵
TfidfVectorizer.fit_transform(X)
X
:文本或者包含文本字符串的可迭代对象- 返回值:返回
sparse
矩阵
TfidfVectorizer.inverse_transform(X)
X
:array
数组或者sparse
矩阵- 返回值:转换之前数据格式
TfidfVectorizer.get_feature_names()
- 返回值:单词列表
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
def cut_word(text):
return ' '.join(list(jieba.cut(text)))
if __name__ == '__main__':
data = [
'优美胜于丑陋(Python以编写优美的代码为目标)',
'明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)',
'简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)',
'复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)',
'扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)',
'间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)',
'可读性很重要(优美的代码是可读的)',
'即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)',
'不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)',
'当存在多种可能,不要尝试去猜测',
'而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)',
'做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)',
'如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)',
'命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)'
]
data_new = [cut_word(sent) for sent in data]
# print(data_new)
# 示例化一个转化器类
transfer = TfidfVectorizer(stop_words=['except', 'pass', '(', ')'])
# 调用 transfer.fit_transform
data_final = transfer.fit_transform(data)
print('返回结果为:', data_final.toarray())
# 输出特征名字
print('特征名字为:', transfer.get_feature_names())
Tf-idf 的重要性
分类机器学习算法进行文章分类中前期数据处理方式