欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

程序员文章站 2022-07-16 17:07:27
...

一、数据预处理基础知识点

链接:https://www.zhihu.com/question/29316149/answer/110159647

通过特征提取,我们能得到未经处理的特征,这时的特征可能有以下问题:

  • 不属于同一量纲:即特征的规格不一样,不能够放在一起比较。无量纲化可以解决这一问题。
  • 信息冗余:对于某些定量特征,其包含的有效信息为区间划分,例如学习成绩,假若只关心“及格”或不“及格”,那么需要将定量的考分,转换成“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.]

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)


1、StandardScaler

标准化需要计算特征的均值和标准差,公式表达为:python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码),使用preproccessing库的

StandardScaler类对数据进行标准化。

Python: sklearn库中数据预处理函数fit_transform()和transform()的区别详见博客链接:


http://blog.csdn.net/quiet_girl/article/details/72517053


python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

#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可以用于回归模型中的目标值处理


2、MinMaxScaler


将数据特征缩放至某一范围(scalingfeatures to a range),被称为“区间缩放法”,常见的一种为利用两个最值进行缩放。即:另一种标准化方法是将数据缩放至给定的最小值与最大值之间,通常是0与1之间,可用MinMaxScaler实现者将最大的绝对值缩放至单位大小,可用MaxAbsScaler实现。公式表达为:

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

使用这种标准化方法的原因是,有时数据集的标准差非常非常小,有时数据中有很多很多零(稀疏数据),

需要保存住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。

        p-范数的计算公式:||X||p=(|x1|^p+|x2|^p+...+|xn|^p)^1/p

该方法主要应用于文本分类和聚类中。例如,对于两个TF-IDF向量的l2-norm进行点积,就可以得到这两个向量的余弦相似性。TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术TF意思是词频(Term Frequency),IDF意思是逆向文件频率(Inverse Document Frequency)。

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)


#!/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)数据标准化用哪个方法没有评价标准,一般数值类型的数据用StandardScalerMinMaxScaler,

对文本数据类型用Normalizer(归一化)。


三、sigmoid函数

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

Logistic函数的表示形式如下:

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

它的函数图像如下,由于函数图像很像一个“S”型,所以该函数又叫 sigmoid 函数。

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

满足的性质:

1.对称性,关于(0,0.5)中心对称

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)
在逻辑回归logistic中,将大于0.5的值映射为1,小于0.5映射为0,成为一个分类的问题。


四、文本数据的处理——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值就越大。所以,排在最前面的几个词,就是这篇文章的关键词


该算法的步骤为:

第一步,计算词频

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

考虑到文章有长短之分,为了便于不同文章的比较,进行"词频"标准化。

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

或者

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

第二步,计算逆文档频率。

这时,需要一个语料库(corpus),用来模拟语言的使用环境。

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

如果一个词越常见,那么分母就越大,逆文档频率就越小越接近0。分母之所以要加1,是为了避免分母为0(即所有文档都不包含该词)。log表示对得到的值取对数(以e为底数)。

第三步,计算TF-IDF。

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)
可以看到,TF-IDF与一个词在文档中的出现次数成正比,与该词在整个语言中的出现次数成反比。
所以,自动提取关键词的算法就很清楚了,就是计算出文档的每个词的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

五、离散的特征数据——独热编码(也称为:哑编码)

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

定性特征不能直接使用:

某些机器学习算法和模型只能接受定量特征的输入,那么需要将定性特征转换为定量特征。最简单的方式是为每一种定性值指定一个定量值,但是这种方式过于灵活,增加了调参的工作。通常使用哑编码的方式将定性特征转换为定量特征:假设有N种定性值,则将这一个特征扩展为N种特征,当原始特征值为第i种定性值时,第i个扩展特征赋值为1,其他扩展特征赋值为0。哑编码的方式相比直接指定的方式,不用增加调参的工作,对于线性模型来说,使用哑编码后的特征可达到非线性的效果

使用preproccessing库的OneHotEncoder类对数据进行独热编码/哑编码.

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

举个例子:

在机器学习任务中,对于如性别“male”和“female这样的特征,通常我们需要对其进行特征数字化。

有如下的三个特征属性:
  • 性别:["male","female"]
  • 国家:["US""China","England"]
  • 城市:["Beijing","London","NewYork","Shanghai"]
对于某一个样本,如["male","China""Shanghai"],我们需要将这个分类值的特征数字化,最直接的方法,我们可以采用序列化的方式:[0,1,3]。但是这样的特征处理并不能直接放入机器学习算法中。

可以采用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]

python3机器学习——sklearn0.19.1版本——数据处理(一)(数据标准化、tfidf、独热编码)

代码实现如下:

#!/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.]]