python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)
一、数据预处理基础知识点
通过特征提取,我们能得到未经处理的特征,这时的特征可能有以下问题:
- 不属于同一量纲:即特征的规格不一样,不能够放在一起比较。无量纲化可以解决这一问题。
- 信息冗余:对于某些定量特征,其包含的有效信息为区间划分,例如学习成绩,假若只关心“及格”或不“及格”,那么需要将定量的考分,转换成“1”和“0”表示及格和未及格。二值化可以解决这一问题。
- 定性特征不能直接使用:某些机器学习算法和模型只能接受定量特征的输入,那么需要将定性特征转换为定量特征。最简单的方式是为每一种定性值指定一个定量值,但是这种方式过于灵活,增加了调参的工作。通常使用哑编码的方式将定性特征转换为定量特征:假设有N种定性值,则将这一个特征扩展为N种特征,当原始特征值为第i种定性值时,第i个扩展特征赋值为1,其他扩展特征赋值为0。哑编码的方式相比直接指定的方式,不用增加调参的工作,对于线性模型来说,使用哑编码后的特征可达到非线性的效果。
- 存在缺失值:缺失值需要补充。
- 信息利用率低:不同的机器学习算法和模型对数据中信息的利用是不同的,之前提到在线性模型中,使用对定性特征哑编码可以达到非线性的效果。类似地,对定量变量多项式化,或者进行其他的转换,都能达到非线性的效果。
我们使用sklearn中的preproccessing库来进行数据预处理,可以覆盖以上问题的解决方案。
二、无量钢化——数据标准化
无量纲化使不同规格的数据转换到同一规格。常见的无量纲化方法有标准化和区间缩放法。
标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。
区间缩放法利用了边界值信息,将特征的取值区间缩放到某个特点的范围,例如[0, 1]等。
Standardization即标准化,尽量将数据转化为均值为零,方差为一的数据,形如标准正态分布(高斯分布)。
关于高斯分布,文章链接为:http://blog.csdn.net/u010182633/article/details/45694437
实际中我们会忽略数据的分布情况,仅仅是通过改变均值来集中数据,然后将非连续特征除以他们的标准差。
sklearn中 scale函数提供了简单快速的singlearray-like数据集操作。
Standardization, or mean removal and variance scaling:标准化,均值去除和按方差比例缩放。
数据集的标准化:当个体特征太过或明显不遵从高斯正态分布时,标准化表现的效果较差。
实际操作中,经常忽略特征数据的分布形状,移除每个特征均值,划分离散特征的标准差,从而等级化,进而实现数据中心化。scale函数可实现数据的均值为0,方差为1,代码如下:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
from sklearn import preprocessing
import numpy as np
X = np.array([[1.,-1.,2.],[2.,0.,0.],[0.,1.,-1.]])
X_scaled = preprocessing.scale(X)
print("========X==========")
print(X)
print("========X_scaled==========")
print(X_scaled)
print("========mean==========")
#scale函数可实现数据的均值为0,方差为1
print(X_scaled.mean(axis=0)) #按列计算均值
print("========var==========")
print(X_scaled.var(axis=0)) #按列计算方差
#运行结果:
========X==========
[[ 1. -1. 2.]
[ 2. 0. 0.]
[ 0. 1. -1.]]
========X_scaled==========
[[ 0. -1.22474487 1.33630621]
[ 1.22474487 0. -0.26726124]
[-1.22474487 1.22474487 -1.06904497]]
========mean==========
[ 0. 0. 0.]
========var==========
[ 1. 1. 1.]
1、StandardScaler
标准化需要计算特征的均值和标准差,公式表达为:,使用preproccessing库的
StandardScaler类对数据进行标准化。
Python: sklearn库中数据预处理函数fit_transform()和transform()的区别详见博客链接:
http://blog.csdn.net/quiet_girl/article/details/72517053
#2.StandardScaler
from sklearn.preprocessing import StandardScaler
X1 = [[1,2,3,2],
[4,5,7,9],
[8,7,4,3],
[5,9,4,2],
[1,4,7,8]]
ss = StandardScaler() #引入标准化的方法,要有数据的均值和方差
ss.fit(X1) #用标准化的方法进行训练数据集X1(fit),得到标准化方法中的参数
#ss = StandardScaler.fit(X1) 等价于上面两句
print(ss)
print("========mean_==========")
print(ss.mean_)
print("========var_==========")
print(ss.var_)
print("===transform实现标准化转换===")
print(ss.transform(X1))
#fit与transform结合成一句
print("===fit_transform训练并标准化转换===")
X1_train = ss.fit_transform(X1)
print(X1_train)
#运行结果:
StandardScaler(copy=True, with_mean=True, with_std=True)
========mean_==========
[ 3.8 5.4 5. 4.8]
========var_==========
[ 6.96 5.84 2.8 9.36]
===transform实现标准化转换===
[[-1.06133726 -1.40693001 -1.19522861 -0.91520863]
[ 0.0758098 -0.16552118 1.19522861 1.37281295]
[ 1.59200589 0.66208471 -0.5976143 -0.58834841]
[ 0.45485883 1.4896906 -0.5976143 -0.91520863]
[-1.06133726 -0.57932412 1.19522861 1.04595272]]
===fit_transform训练并标准化转换===
[[-1.06133726 -1.40693001 -1.19522861 -0.91520863]
[ 0.0758098 -0.16552118 1.19522861 1.37281295]
[ 1.59200589 0.66208471 -0.5976143 -0.58834841]
[ 0.45485883 1.4896906 -0.5976143 -0.91520863]
[-1.06133726 -0.57932412 1.19522861 1.04595272]]
注:1)若设置with_mean=False 或者 with_std=False,则不做centering 或者scaling处理。
2)scale和StandardScaler可以用于回归模型中的目标值处理。
将数据特征缩放至某一范围(scalingfeatures to a range),被称为“区间缩放法”,常见的一种为利用两个最值进行缩放。即:另一种标准化方法是将数据缩放至给定的最小值与最大值之间,通常是0与1之间,可用MinMaxScaler实现或者将最大的绝对值缩放至单位大小,可用MaxAbsScaler实现。公式表达为:
使用这种标准化方法的原因是,有时数据集的标准差非常非常小,有时数据中有很多很多零(稀疏数据),
需要保存住0元素。
from sklearn.preprocessing import MinMaxScaler
X = [[1,2,3,2],
[4,5,7,9],
[8,7,4,3],
[5,9,4,2],
[1,4,7,8]]
mms = MinMaxScaler()
mms.fit(X)
print(mms)
print("最大值",mms.data_max_)
print("最小值",mms.data_min_)
print("===区间缩放,返回值为缩放到[0, 1]区间的数据===")
print(mms.transform(X))
#与上面最后一句等价
# mms_fit = mms.fit_transform(X)
# print(mms_fit)
#运行结果:
MinMaxScaler(copy=True, feature_range=(0, 1))
最大值 [ 8. 9. 7. 9.]
最小值 [ 1. 2. 3. 2.]
===区间缩放,返回值为缩放到[0, 1]区间的数据===
[[ 0. 0. 0. 0. ]
[ 0.42857143 0.42857143 1. 1. ]
[ 1. 0.71428571 0.25 0.14285714]
[ 0.57142857 1. 0.25 0. ]
[ 0. 0.28571429 1. 0.85714286]]
3、Normalizer——归一化
标准化与归一化的区别:
标准化是依照特征矩阵的列处理数据,其通过求z-score的方法,将样本的特征值转换到同一量纲下。
归一化是依照特征矩阵的行处理数据,其目的在于样本向量在点乘运算或其他核函数计算相似性时,
拥有统一的标准,也就是说都转化为“单位向量”。使用preproccessing库的Normalizer类对数据进行归一化。
官方文档翻译:
sklearn.preprocessing.Normalizer(norm=’l2’, copy=True)
norm:可以为l1、l2或max,默认为l2
若为l1时,样本各个特征值除以各个特征值的绝对值之和
若为l2时,样本各个特征值除以各个特征值的平方之和
若为max时,样本各个特征值除以样本中特征值最大的值
归一化的过程是将每个样本缩放到单位范数(每个样本的范数为1),如果后面要使用如二次型(点积)或者其它核方法计算两个样本之间的相似性这个方法会很有用。
Normalization主要思想是对每个样本计算其p-范数,然后对该样本中每个元素除以该范数,这样处理的结果是使得每个处理后样本的p-范数(l1-norm,l2-norm)等于1。
该方法主要应用于文本分类和聚类中。例如,对于两个TF-IDF向量的l2-norm进行点积,就可以得到这两个向量的余弦相似性。(TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。TF意思是词频(Term Frequency),IDF意思是逆向文件频率(Inverse Document Frequency)。)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
from sklearn.preprocessing import Normalizer
X = [[1,2,3,2],
[4,5,7,9],
[8,7,4,3],
[5,9,4,2],
[1,4,7,8]]
nm = Normalizer()
nm.fit(X)
#nm = Normalizer().fit(X) #等价于上面两句
print(nm)
print("norm",nm.norm)
nm1 = nm.fit_transform(X)
print("=======fit_transform=======")
print(nm1)
#print(nm.transform(X)) #等价于上面两句
#运行结果:
Normalizer(copy=True, norm='l2')
norm l2
=======fit_transform=======
[[ 0.23570226 0.47140452 0.70710678 0.47140452]
[ 0.30588765 0.38235956 0.53530338 0.6882472 ]
[ 0.68100522 0.59587957 0.34050261 0.25537696]
[ 0.4454354 0.80178373 0.35634832 0.17817416]
[ 0.0877058 0.35082321 0.61394061 0.70164642]]
总结:数据标准化的意义
(1)消除量纲的影响
(2)对于数据分布不均匀的影响(比如:某列数据跟其他差距很大)
(3)数据标准化用哪个方法没有评价标准,一般数值类型的数据用StandardScaler和MinMaxScaler,
对文本数据类型用Normalizer(归一化)。
三、sigmoid函数
Logistic函数的表示形式如下:
它的函数图像如下,由于函数图像很像一个“S”型,所以该函数又叫 sigmoid 函数。
满足的性质:
1.对称性,关于(0,0.5)中心对称
四、文本数据的处理——TF-IDF
TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。
TF意思是词频(Term Frequency),即:某个词条在文本中出现的次数。
如果某个词很重要,它应该在这篇文章中多次出现。于是,我们进行"词频"(Term Frequency,缩写为TF)统计。
IDF意思是逆向文件频率(Inverse Document Frequency),即:一个词条的重要性。
用统计学语言表达,就是在词频的基础上,要对每个词分配一个"重要性"权重。最常见的词("的"、"是"、"在")给予最小的权重,较常见的词("中国")给予较小的权重,较少见的词("蜜蜂"、"养殖")给予较大的权重。
这个权重叫做"逆文档频率"(Inverse
Document Frequency,缩写为IDF),它的大小与一个词的常见程度成反比。
知道了"词频"(TF)和"逆文档频率"(IDF)以后,将这两个值相乘,就得到了一个词的TF-IDF值。
某个词对文章的重要性越高,它的TF-IDF值就越大。所以,排在最前面的几个词,就是这篇文章的关键词。
该算法的步骤为:
第一步,计算词频。
考虑到文章有长短之分,为了便于不同文章的比较,进行"词频"标准化。
或者
第二步,计算逆文档频率。
这时,需要一个语料库(corpus),用来模拟语言的使用环境。
如果一个词越常见,那么分母就越大,逆文档频率就越小越接近0。分母之所以要加1,是为了避免分母为0(即所有文档都不包含该词)。log表示对得到的值取对数(以e为底数)。
第三步,计算TF-IDF。
TF-IDF算法的优点是简单快速,结果比较符合实际情况。缺点是,单纯以"词频"衡量一个词的重要性,不够全面,
有时重要的词可能出现次数并不多。而且,这种算法无法体现词的位置信息,出现位置靠前的词与出现位置靠后的词,都被视为重要性相同,这是不正确的。(一种解决方法是,对全文的第一段和每一段的第一句话,给予较大的权重。)还可以用TF-IDF结合余弦相似性,衡量文档之间的相似程度
(文章链接:http://www.ruanyifeng.com/blog/2013/03/cosine_similarity.html)。
sklearn.feature_extraction.text.TfidfVectorizer:可以把一大堆文档转换成TF-IDF特征的矩阵。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
from sklearn.feature_extraction.text import TfidfVectorizer
text1 = [
"this is python",
"this is sample",
"anaconda sklearn is good"
]
text2 = [
"this is another",
"today is sunny",
"lr randomforest is model"
]
tfidf = TfidfVectorizer()
tf = tfidf.fit_transform(text2) #训练并转换
print(tfidf.get_feature_names)
print(tfidf.get_stop_words) #停止词
print("====TF-IDF特征的矩阵====")
print(tf.toarray())
print("====输出的各个文本各个词的TF-IDF值=====")
print(tf)
#运行结果:
<bound method CountVectorizer.get_feature_names of TfidfVectorizer(analyzer='word', binary=False, decode_error='strict',
dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
lowercase=True, max_df=1.0, max_features=None, min_df=1,
ngram_range=(1, 1), norm='l2', preprocessor=None, smooth_idf=True,
stop_words=None, strip_accents=None, sublinear_tf=False,
token_pattern='(?u)\\b\\w\\w+\\b', tokenizer=None, use_idf=True,
vocabulary=None)>
<bound method VectorizerMixin.get_stop_words of TfidfVectorizer(analyzer='word', binary=False, decode_error='strict',
dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
lowercase=True, max_df=1.0, max_features=None, min_df=1,
ngram_range=(1, 1), norm='l2', preprocessor=None, smooth_idf=True,
stop_words=None, strip_accents=None, sublinear_tf=False,
token_pattern='(?u)\\b\\w\\w+\\b', tokenizer=None, use_idf=True,
vocabulary=None)>
====TF-IDF特征的矩阵====
[[ 0.65249088 0.38537163 0. 0. 0. 0.
0.65249088 0. ]
[ 0. 0.38537163 0. 0. 0. 0.65249088
0. 0.65249088]
[ 0. 0.32274454 0.54645401 0.54645401 0.54645401 0. 0.
0. ]]
====输出的各个文本各个词的TF-IDF值=====
(0, 6) 0.652490884513
(0, 1) 0.385371627466
(0, 0) 0.652490884513
(1, 1) 0.385371627466
(1, 7) 0.652490884513
(1, 5) 0.652490884513
(2, 1) 0.32274454218
(2, 2) 0.546454011634
(2, 4) 0.546454011634
(2, 3) 0.546454011634
五、离散的特征数据——独热编码(也称为:哑编码)
定性特征不能直接使用:
某些机器学习算法和模型只能接受定量特征的输入,那么需要将定性特征转换为定量特征。最简单的方式是为每一种定性值指定一个定量值,但是这种方式过于灵活,增加了调参的工作。通常使用哑编码的方式将定性特征转换为定量特征:假设有N种定性值,则将这一个特征扩展为N种特征,当原始特征值为第i种定性值时,第i个扩展特征赋值为1,其他扩展特征赋值为0。哑编码的方式相比直接指定的方式,不用增加调参的工作,对于线性模型来说,使用哑编码后的特征可达到非线性的效果。
使用preproccessing库的OneHotEncoder类对数据进行独热编码/哑编码.
举个例子:
在机器学习任务中,对于如性别“male”和“female”这样的特征,通常我们需要对其进行特征数字化。
- 性别:["male","female"]
- 国家:["US","China","England"]
- 城市:["Beijing","London","NewYork","Shanghai"]
可以采用One-Hot编码的方式对上述的样本“["male","China","Shanghai"]”编码,“male”则对应着[1,0],同理"China"对应着[0,1,0],"Shanghai"对应着[0,0,0,1]。则完整的特征数字化的结果为:[1,0,0,1,0,0,0,0,1]。
代码实现如下:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:ZhengzhengLiu
#独热编码/哑编码
from sklearn.preprocessing import OneHotEncoder
#X为训练的数据,按列看,每列中的四个数字表示每个特征可能的取值范围,
# 即每个特征的可能的取值个数
X = [[0,0,3],
[1,1,0],
[0,2,1],
[1,0,2]]
enc = OneHotEncoder() #创建独热编码方法
enc.fit(X) #训练
print(enc.n_values_) #打印每一维数据可能的取值个数
print(enc.feature_indices_)
print("======独热编码=====")
enc1 = enc.transform(X).toarray()
enc2 = enc.transform([[0,1,3]]).toarray()
print(enc1)
print("===============================")
print(enc2)
#运行结果:
[2 3 4]
[0 2 5 9]
======独热编码=====
[[ 1. 0. 1. 0. 0. 0. 0. 0. 1.]
[ 0. 1. 0. 1. 0. 1. 0. 0. 0.]
[ 1. 0. 0. 0. 1. 0. 1. 0. 0.]
[ 0. 1. 1. 0. 0. 0. 0. 1. 0.]]
===============================
[[ 1. 0. 0. 1. 0. 0. 0. 0. 1.]]
上一篇: 【图像处理】python实现图像标准化
下一篇: linux安装redis 使用