目录

为什么要用特征工程

特征提取(Feature Extraction)

1.目的

2.对应的工具

3.三种方法

4.对应的sklearn的API

(1)字典特征提取

(2)文本特征提取

总结


特征是从数据中抽取出来的对结果有预测有用的信息,可以是文本或者数据。

Feature Engineer。特征工程就是把原始数据转换成特征的过程。特征工程对数据进行处理,使得特征在机器学习算法上发挥更好的作用。

从数学的角度,就是人工的去设计输入变量x。

过程包括:特征选择(Feature Selection)、特征提取(Feature Extraction)、特征构建(Feature Construction)。

目的:筛选出更好的特征,获取更好的训练数据。

为什么要用特征工程

要使得预测模型性能达到最佳,不仅要选择最好的算法,更要尽可能从原始数据中获取更多的信息。而特征工程就是获取更多的训练数据。

数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限。

特征提取(Feature Extraction)

1.目的

将任意数据(如文本或图像)转换成机器学习的数学特征

2.对应的工具

sklearn:特征工程

pandas:数据清洗 数据处理

3.三种方法

字典特征提取

文本特征提取

图像特征提取(目前主要应用于深度学习)

4.对应的sklearn的API

sklearn.feature_extraction

该包下有对应的上述方法中的字典特征提取、文本特征提取等的API

(1)字典特征提取

1.目的

将字典中属于类别的非数值的特征转换成one-hot编码。也就是对字典数据进行特征值化。

one-hot编码:一位有效编码。其方法就是使用n位状态来进行编码,每个状态都有独立的位置,并且在任意的时候,只有一位有效。这样转换成数值的特征不会有数值大小的比较。

也就是为每个类别生成一个布尔列,这些列中只有一列可以为该样本取值为1.

2.对应的sklean的API

sklearn.feature_extraction.DictVectorizer(dtype=<class‘numpy.float64’>, separator=’=’, sparse=True, sort=True)

参数介绍

参数 含义
dtype 特征值的类型,默认的为float
separator 默认为‘=’。当构造one-hot编码的特征值时要使用的分割字符串。分割传入字典数据的键与值的字符串,也就是最后生成的特征矩阵的列名的键与值的分割符。
sparse 默认为true:产生一个稀疏矩阵;false:不产生稀疏矩阵,返回的是二维数组的one-hot编码方式
sort 默认为true:拟合要对feature_names(包含所有特征名称)和vocabulary_(特征名称和特征列索引映射字典)进行排序

DictVectorizer为一个转换器父类。调用该API这个是实例化一个转换器类,里面有一些迭代器,用来返回该转换器的一些信息。主要API有以下几个:

(1)DictVectorizer.fit_transform(x)

将输入的字典x转换成矩阵,返回的是稀疏矩阵sparse矩阵

(2)DictVectorizer.inverse_transform(x)

将矩阵还原成特征字典列表。传入的x必须是DictVectorizer经过transform或者fit_transform产生的x

(3)DictVectorizer.get_feature_names()

返回类别的名称

 DictVectorizer.transform(X)

将x转换为numpy.ndarray或者Scipy.sparse

3.实例

通过一个实例看下一个样本集合是怎么进行提取特征值的

# 导入DictVectorizer
from sklearn.feature_extraction import DictVectorizer#字典特征提取
def dict():#定义数据集data = [{'city':'上海','temperature':100},{'city':'北京','temperature':60},{'city':'深圳','temperature':30}]#1.实例化一个转换器类transfor =  DictVectorizer()#2.调用fit_transform,生成矩阵data_new = transfor.fit_transform(data)print(transfor.get_feature_names())print(data_new)return None

从上面的代码中可以看出:

(1)首先要从sklearn中导入DictVectorizer

(2)定义了一个数据集

(3)实例化一个DictVectorizer转换器的实例

(4)调用fit_transform,生成矩阵

我们看下最后输出的内容:

['city=上海', 'city=北京', 'city=深圳', 'temperature'](0, 0)    1.0(0, 3)   100.0(1, 1) 1.0(1, 3)   60.0(2, 2)  1.0(2, 3)   30.0

默认的返回的是sparse矩阵,并不是我们之前说的字典特征就是将特征的类别转换成one-hot编码的形式。

  • sparse矩阵

这个sparse矩阵即稀疏矩阵,特点就是把非0值按位置表示出来。为什么会有这种方式呢?

字典特征提取的目的就是将不同类别的特征转换成one-hot编码的方式,但是如果我们有1000甚至更多的类别,那么在转换成one-hot编码的时候,就会有很多很多的0存在,这样就会浪费空间,而这个稀疏矩阵只需要把非0的位置表示出来,那么其他的位置就是0,从而节省内存,提供加载效率。

那么对于上述的返回值的表示的含义如下:

那么怎么得到one-hot编码的矩阵呢?这个就是在实例化DictVectorizer的一个参数sparse,如果我们把该值设置为false,输出结果

   transfor =  DictVectorizer(sparse=False)

把每一个样本转换成了一个向量 的二维数组

['city=上海', 'city=北京', 'city=深圳', 'temperature']
[[  1.   0.   0. 100.][  0.   1.   0.  60.][  0.   0.   1.  30.]]

从这个矩阵和对比上面输出的内容,可以看出这个60的确就是在第2行第3列的位置。我们将刚才的每个样本中的两个特征值转换四个特征值来表示,也就是第一个特征值为1,其他为0的就是上海,第2个特征值为1,其他为0的就是北京等等。这样就把字符串的字典特征转换成了one-hot编码的形式。

4.应用场景

(1)数据集中有很多的类别特征的时候

首先要将数据集的特征转换成字典类型,然后使用DictVectorizer进行转换

(2)本身拿到的数据就是字典类型

(2)文本特征提取

一篇文章进行分类的话,使用什么作为特征更容易分类呢?通常采用单词作为特征值更容易分类。当然句子、短语、字母都可以作为特征。

  • 1.英文的特征提取

通常取文章中出现的单词作为特征值。对应的sklearn的API为

sklearn.feature_extraction.text.CountVectorizer(input='content', encoding='utf-8',decode_error='strict', strip_accents=None, lowercase=True,preprocessor=None, tokenizer=None, analyzer='word',stop_words=None, token_pattern=r"(?u)\b\w\w+\b",ngram_range=(1, 1), max_df=1.0, min_df=1,max_features=None, vocabulary=None, binary=False,dtype=np.float64, norm='l2', use_idf=True, smooth_idf=True,sublinear_tf=False)

统计是单词出现的频率,返回的是词频矩阵

对应的参数含义

参数 含义
input 一般使用默认即可,也可以设置为filename/file
encoding 编码方式
decode_error

默认为strict,遇到不能解码的字符串则抛出UnicodeDecodeError

ignore:忽略错误

replace

strip_accents

默认为None

ascil或unicode:在预处理的去除raw document的重音符号

analyzer 一般使用默认word,可设置为string,也可以设置为callable
preprocessor 设置为None或callable
token 设置为None或callable
ngram_range 词组切分的长度范围
stop_words 设置停用词,
lowercase 将所有字符变为小写
token_pattern 过滤规则
max_df 设置范围为[0.0,1.0],作用是阀值,当某个词的document frequence>max_df,则不被作为关键词。如果设定了vacabulary,则该参数无效
min_df 当某个词的document frequence<min_df,则不被作为关键词。
max_features 默认为None,对关键词的tem_frequency进行降序排序,只取前max_features作为关键词频
vocabulary 默认为None,自动从数据集中构建关键词集
binary 默认为false,一个关键词出现次数为n词,如果为true,非0的n将全部只为1
dtype 对得到的词频矩阵,设置这个矩阵的数组类型

调用该API这个是实例化一个转换器类,里面有一些迭代器,用来返回该转换器的一些信息。主要API有以下几个:

(1)CountVectorizer.fit_transform(x)

x为数组或者sparse矩阵,返回值为sparse矩阵

(2)CountVectorizer.inverse_transform(x)

将transfor的sparse矩阵还原。x必须为transform或者fit_transform产生的x

(3)CountVectorizer.get_feature_names()

返回单词列表

  • 2.英文特征提取对应的实例
 #导入相应的包
from sklearn.feature_extraction.text import CountVectorizerdef count():#文本特征抽取data=["life is short , i like like python","lift is too long , i dislike "," i am a IT "]#实例化一个转换器类transfor = CountVectorizer()#调用fit_transform()data_new = transfor.fit_transform(data)print(transfor.get_feature_names())print(data_new)return None

跟字典特征的提取的过程一样,导入相应的包、实例化转换器、调用迭代器输出矩阵,我们看下输出的内容:

['am', 'dislike', 'is', 'it', 'life', 'lift', 'like', 'long', 'python', 'short', 'too'](0, 4)  1(0, 2) 1(0, 9) 1(0, 6) 2(0, 8) 1(1, 2) 1(1, 5) 1(1, 10)    1(1, 7) 1(1, 1) 1(2, 0) 1(2, 3) 1

同字典特征提取一样,返回的是稀疏矩阵,即非0值的位置。

我们发现CountVectorizer并没有一个sparse的参数,但是可以调用sparse矩阵的toarray()转换成对应的样本数量的n维数组的形式。

    print(data_new.toarray())

输出的结果如下

['am', 'dislike', 'is', 'it', 'life', 'lift', 'like', 'long', 'python', 'short', 'too']
[[0 0 1 0 1 0 2 0 1 1 0][0 1 1 0 0 1 0 1 0 0 1][1 0 0 1 0 0 0 0 0 0 0]]

代表的含义就是上面的特征词在每个样本中出现的次数 。

在看下在实例化转换器 CountVectorizer的stop_words参数的含义,指的是停用词,即这些词不会出现在特征词中。网上也有好多停用词表供使用。

    #实例化一个转换器类transfor = CountVectorizer(stop_words=['is','too','am'])

从运行结果可以看到,‘is’,‘too’,‘am’已经不在特征词中。

['dislike', 'it', 'life', 'lift', 'like', 'long', 'python', 'short'](0, 2)   1(0, 7) 1(0, 4) 2(0, 6) 1(1, 3) 1(1, 5) 1(1, 0) 1(2, 1) 1
[[0 0 1 0 2 0 1 1][1 0 0 1 0 1 0 0][0 1 0 0 0 0 0 0]]

我们刚才的例子中提到的是英文文章的特征提取,那么如果我们把数据集换成中文呢?结果是不是也是一样呢?我们在刚才的例子中换下数据集

def count_ch():#文本特征抽取data = ["今天的天气很晴朗", "心情也跟着好起来", "学习机器学习真有意思"]#实例化一个转换器类transfor = CountVectorizer()#调用fit_transform()data_new = transfor.fit_transform(data)print(transfor.get_feature_names())print(data_new)print("转换成n维数组:")print(data_new.toarray())return None

我们看下输出的结果如下:

['今天的天气很晴朗', '学习机器学习真有意思', '心情也跟着好起来'](0, 0)   1(1, 2) 1(2, 1) 1
转换成n维数组:
[[1 0 0][0 0 1][0 1 0]]

我们可以看到每个样本都作为了特征词,这个主要由于英文自动有空格进行分割单词,但是中文没有分割,所以每个短语都成了单独的一个特征词,那么中文的特征提取怎么做呢?

  • 3.中文的特征提取

当然第一种比较笨的方法,就是通过自动给文本中的内容按照词组进行加空格进行分组,但是这种方式显然无法利用实际应用中。那么就有了另外一种方式通过结巴分词的方式来将原文本进行分词。当然还有其他的一些分词方式,如盘古分词、Yaha分词、清华YHULAC等

结巴分词就是将文本中的词语进行分开。有三种模式:

(1)精确模式:试图将句子最精确的切开,适合文本分析

(2)全模式:把句子中所有的可以成词的词语都扫描出来

(3)搜索引擎模式:在精确模式的基础上,对长词在进行切分,适合用于搜索引擎分词

默认的为精确模式。我们看下同样一个文本在不同的模式下的输出的区别

#导入相应的包
import jieba
def cut_word_test(text):#传入一个词组然后进行自动分词#用空格来连接结巴分词之后的列表result = " ".join(list(jieba.cut(text, cut_all=True)))print("<全模式>结巴分词的结果为:")print(result)result = " ".join(list(jieba.cut(text, cut_all=False)))print("<精确模式>结巴分词的结果为:")print(result)result = " ".join(list(jieba.cut(text)))print("<默认>结巴分词的结果为:")print(result)result = " ".join(list(jieba.cut_for_search(text)))print("<搜索引擎模式>结巴分词的结果为:")print(result)return result

输出的结果如下:

<全模式>结巴分词的结果为:
我 在 南京 南京理工 理工 理工大 理工大学 工大 大学 读研 研究 研究生
<精确模式>结巴分词的结果为:
我 在 南京 理工大学 读 研究生
<默认>结巴分词的结果为:
我 在 南京 理工大学 读 研究生
<搜索引擎模式>结巴分词的结果为:
我 在 南京 理工 工大 大学 理工大 理工大学 读 研究 研究生
  • 4.中文的特征提取实例

还是通过一个实例看下中文的特征提取,区别于英文的特征提取,在进行调用转换器进行转换成矩阵之前,首先要对数据集进行分词。

def cut_word(text):#传入一个词组然后进行自动分词print("中文输入的内容为:" + text)#用空格来连接结巴分词之后的列表result = " ".join(list(jieba.cut(text)))print("默认的结巴分词的结果为:")print(result)return resultdef count_ch1():#中文特征提取,自动分词data = ["今天的天气很晴朗", "心情也跟着好起来", "学习机器学习真有意思"]#进行分词data_cut=[]for text in data:data_cut.append(cut_word(text))#实例化一个转换器类transfor = CountVectorizer()#调用fit_transform()data_new = transfor.fit_transform(data_cut)print(transfor.get_feature_names())print(data_new)print("转换成n维数组:")print(data_new.toarray())

从上面的代码中可以看出我们在使用CountVectorizer进行转换的数据集,是通过结巴分词进行分词的数据集,其他的就和英文特征提取的步骤一样:实例化转换器,调用转换器的迭代器进行转换,最后输出的结果如下:

['今天', '天气', '学习', '心情', '晴朗', '有意思', '机器', '起来', '跟着'](0, 0)  1(0, 1) 1(0, 4) 1(1, 3) 1(1, 8) 1(1, 7) 1(2, 2) 2(2, 6) 1(2, 5) 1
转换成n维数组:
[[1 1 0 0 1 0 0 0 0][0 0 0 1 0 0 0 1 1][0 0 2 0 0 1 1 0 0]]

同样我们可以在实例化CountVectorizer的时候,通过stop_words来过滤某些词组。

上面介绍的是统计所有特征词出现的词频,那么怎么去衡量一个特征词的重要程度呢?另外对一个文章进行分类的时候,怎么去确定这个文章的关键词呢?

所谓的关键词就是在某一个类别的文章中出现的次数很多,在其他文章中出现的次数很少或几乎不出现。

上面统计了两篇文章中对应的词组出现的一个比例关系,我们发现第一篇文章中出现了大量的“车”、“共享 ”,我们就猜测可能是在讲共享单车的一篇互联网科技文章,而另外一篇出现了大量的“经济”、“银行”、“证券”,那就可能是一篇财经类的文章,并且两篇词组在一篇文章中的基本上不会出现在另外一篇文章中,那我们就可以通过这些词组来区分是哪类文章了。

其中sklearn中有专门的API来实现挑选这种关键词:文本特征提取TfidfVectorizer

  • 5.TfidfVectorizer

用来表示在某个词或者短语在多篇文章中出现的次数的情况,可以看出哪个词语更为重要。

TF-IDF的主要思想:如果某个词语或者短语在一篇文章中出现的概率高,并且在其他文章中很少出现,那么则认为该词语或者短语具有很好的类别区分能力,适合用来分类。

作用:主要用来衡量一个字词对于一个文章集或者语料库中的一份文章的重要程度。

(1)TF:词频Term Frequency,指定某一个给定的词语在该文章中出现的频率。

(2)IDF:逆向文档频率Inverse Document Frequent,指的是一个词语普遍重要性的度量。某一个词语的IDF,

(3)TF-IDF:就是TF和IDF的乘积

我们通过一个实例来看下上面三个概念。

假设我们有一个10000篇文件的语料库,其中1000篇文章中都含有“房贷”,100篇文章中含有“彩妆”

现在有A文章,出现了10个“房贷”,B文章出现了10个“彩妆”,A和B的文章总的词组量都是100个,那么对于“房贷”和“彩妆”的TF-IDF是多少呢?

文章A:TF= 10/100 = 0.1

文章B:TF=1 0/100 = 0.1

我们但从TF中看不出这两个词的重要性

文章A:IDF = lg(10000/1000) = 1

文章B:IDF = lg(10000/100) = 2

那么A和B的TF-IDF为

文章A:TF-IDF = 0.1x1 = 0.1

文章B:TF-IDF = 0.1x2 = 0.2

那么可以很明显的看出文章B的“彩妆”的重要程度用数值进行表示出来。

(4)sklearn的TF-IDF的API -TfidfVectorizer

sklearn.feature_extraction.text.TfidfVectorizer(input='content', encoding='utf-8',decode_error='strict', strip_accents=None, lowercase=True,preprocessor=None, tokenizer=None, analyzer='word',stop_words=None, token_pattern=r"(?u)\b\w\w+\b",ngram_range=(1, 1), max_df=1.0, min_df=1,max_features=None, vocabulary=None, binary=False,dtype=np.float64, norm='l2', use_idf=True, smooth_idf=True,sublinear_tf=False)

参数含义可以参见CountVectorizer,不在多余介绍。其里面的迭代器和CountVectorizer也是类似的,也不再多余介绍。通过一个实例看下这个API的使用

from sklearn.feature_extraction.text import CountVectorizer,TfidfVectorizer
def tfidf():#使用TF-idf进行文本特征提取data = ["今天的天气很晴朗", "心情也跟着好起来", "学习机器学习真有意思"]#进行分词data_cut=[]for text in data:data_cut.append(cut_word(text))#实例化一个转换器类transfor = TfidfVectorizer()#调用fit_transform()data_new = transfor.fit_transform(data_cut)print(transfor.get_feature_names())print(data_new)print("转换成n维数组:")print(data_new.toarray())return None

看下输出的结果

默认的结巴分词的结果为:
学习 机器 学习 真 有意思
['今天', '天气', '学习', '心情', '晴朗', '有意思', '机器', '起来', '跟着'](0, 4) 0.5773502691896257(0, 1)    0.5773502691896257(0, 0)    0.5773502691896257(1, 7)    0.5773502691896257(1, 8)    0.5773502691896257(1, 3)    0.5773502691896257(2, 5)    0.40824829046386296(2, 6)   0.40824829046386296(2, 2)   0.8164965809277259
转换成n维数组:
[[0.57735027 0.57735027 0.         0.         0.57735027 0.0.         0.         0.        ][0.         0.         0.         0.57735027 0.         0.0.         0.57735027 0.57735027][0.         0.         0.81649658 0.         0.         0.408248290.40824829 0.         0.        ]]

我们可以看到不同的词组的TF-IDF的大小不一样,有的值比较大,有的值会比较小,值比较大的就体现这个词的重要性,具有分类意义。

总结

所谓的特征提取就是将原始数据进行特征化,将不是数值的数据进行转换成数值。

字典特征抽取DictVectorizer就是将类别转换成one-hot编码;

文本特征提取CountVectorizer用来统计词组的个数,统计的是词频;

TfidfVectorizer用来统计词组的重要性程度,对文章分类的前期数据处理。

机器学习入门研究(五)-特征工程之特征提取相关推荐

  1. 【机器学习入门】(10) 特征工程:特征抽取,字典特征抽取、文本特征抽取,附完整python代码

    各位同学好,今天和大家介绍一下python机器学习中的特征工程.在将数据放入模型之前,需要对数据的一些特征进行特征抽取,方法有: (1) 字典特征抽取 DictVectorizer(),(2) 文本特 ...

  2. 机器学习系列(5)_特征工程02特征提取

    文章目录 一.Filter过滤法 1.方差过滤 (1)使用KNN进行考察 (2)使用随机森林(RFC)进行考察 2.相关性过滤 (1)卡方过滤 (2) 用随机森林进行比较特征选择 (3)选取超参数 ( ...

  3. 【机器学习入门】(12) 特征工程:特征选择、数据降维、PCA

    各位同学好,今天我和大家分享一下python机器学习中的特征选择和数据降维.内容有: (1)过滤选择:(2)数据降维PCA:(3)sklearn实现 那我们开始吧. 一个数据集中可能会有以下问题: ( ...

  4. 【零基础入门数据挖掘】-特征工程

    Datawhale 作者:吴忠强,Datawhale优秀学习者 摘要:对于数据挖掘项目,本文将学习应该从哪些角度做特征工程?从哪些角度做数据清洗,如何对特征进行增删,如何使用PCA降维技术等. 特征工 ...

  5. 零基础入门数据挖掘-Task3 特征工程

    Datawhale 零基础入门数据挖掘-Task3 特征工程 前言 内容介绍 数据清洗 缺失值 异常值 箱型图 3∂原则 Box-Cox 变换 特征缩放 特征编码 特征工程 特征提取 特征选择 特征构 ...

  6. 机器学习处理流程、特征工程,模型设计实例

    作者:大树 更新时间:01.14 email:59888745@qq.com 数据处理,机器学习 回主目录:2017 年学习记录和总结 阿里天池 大航杯"智造扬中"电力AI大赛 的 ...

  7. 零基础数据挖掘入门系列(四) - 特征工程

    思维导图:零基础入门数据挖掘的学习路径 1. 写在前面 零基础入门数据挖掘是记录自己在Datawhale举办的数据挖掘专题学习中的所学和所想, 该系列笔记使用理论结合实践的方式,整理数据挖掘相关知识, ...

  8. 机器学习基础之《特征工程(2)—特征工程介绍、特征抽取》

    一.什么是特征工程 机器学习领域的大神Andrew Ng(吴恩达)老师说"Coming up with features is difficult, time-consuming, requ ...

  9. 机器学习系列(3)_特征工程01数据预处理

    参考链接: 1.scikit-learn官网 2.sklearn提供的自带的数据集 3.Kaggle官网 4.数据挖掘--无量纲化 文章目录 一.数据中台 二.sklearn中的数据预处理与特征工程 ...

最新文章

  1. iOS网络缓存扫盲篇--使用两行代码就能完成80%的缓存需求
  2. mysql duplicate jpa_SpringBoot Jpa 双数据源mysql + oracle + liquibase+参考源码
  3. TypeError: __init__() takes 1 positional argument but 4 were given
  4. 数组方法深入扩展(遍历forEach,filter,reduce等)
  5. 【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 EventChannel 通信 )
  6. C++ 学习路线推荐
  7. ajax,php文件读取
  8. spark-jar冲突解决方案
  9. Android之android.os.DeadObjectException原因
  10. 非静态方法可以访问Java中的静态变量/方法吗?
  11. linux用命令行进行无线连接,linux以命令行下配置连接wlan无线网卡
  12. for语句中声明变量
  13. C语言:用单链表实现输入排序
  14. Linux Mint外接显示器分辨率调节
  15. 豆瓣上关于一万小时天才理论一书的一个评论
  16. 独立事件、笛卡尔积与矩阵向量乘法
  17. 堆中的路径(MOOC)
  18. 大麦盒子DM1004线刷降级填坑记录
  19. java+webrtc+回声消除,WebRTC回声消除(2)
  20. 货币单位PHP,PHP实现货币换算的方法_PHP

热门文章

  1. 关于网页右下角总出广告解决办法
  2. ubuntu13.10安装minidwep-gtk(PJ无线密码)
  3. 如何用python生成雷达图
  4. 小白入门——Python标准库和第三方库简介
  5. 如何把pdf文件转换成图片?
  6. U盘连接时显示位置不可用无法访问请问怎样才能修复
  7. 模拟电路——电源电路
  8. Linux驱动开发(十)---树莓派输入子系统学习(红外接收)
  9. Linux 下五个最佳的 FPS 游戏发布啦!
  10. 为什么快手不能左右滑了_为什么快手作品上下滑动不能切换 | 手游网游页游攻略大全...