13 数据处理和优化
13.1数据处理
13.1.1标准化的原因
通常情况下是为了消除量纲的影响。譬如一个百分制的变量与一个5分值的变量在一起怎么比较?只有通过数据标准化,都把它们标准到同一个标准时才具有可比性,一般标准化采用的是Z标准化,即均值为0,方差为1,当然也有其他标准化,比如0--1标准化等等,可根据自己的数据分布情况和模型来选择。
作用:去均值和方差归一化。且是针对每一个特征维度来做的,而不是针对样本。
标准差标准化(standardScale)使得经过处理的数据符合标准正态分布,即均值为0,标准差为1,其转化函数为:
其中μ为所有样本数据的均值,σ为所有样本数据的标准差。
13.1.2 适用情况
看模型是否具有伸缩不变性。
不是所有的模型都一定需要标准化,有些模型对量纲不同的数据比较敏感,譬如SVM等。当各个维度进行不均匀伸缩后,最优解与原来不等价,这样的模型,除非原始数据的分布范围本来就不叫接近,否则必须进行标准化,以免模型参数被分布范围较大或较小的数据主导。但是如果模型在各个维度进行不均匀伸缩后,最优解与原来等价,例如logistic regression等,对于这样的模型,是否标准化理论上不会改变最优解。但是,由于实际求解往往使用迭代算法,如果目标函数的形状太"扁",迭代算法可能收敛得很慢甚至不收敛。所以对于具有伸缩不变性的模型,最好也进行数据标准化。
那么问题是,当我们在训练模型的时候,一定要对数据进行变换吗?这得视情况而定。很多人对多层感知机有个误解,认为输入的数据必须在[0,1]这个范围内。虽然标准化后在训练模型效果会更好,但实际上并没有这个要求。但是最好使输入数据中心集中在0周围,所以把数据缩放到[0,1]其实并不是一个好的选择。
如果你的输出激活函数的范围是[0,1](sigmoid函数的值域),那你必须保证你的目标值也在这个范围内。但通常情况下,我们会使输出激活函数的范围适应目标函数的分布,而不是让你的数据来适应激活函数的范围。
当我们使用激活函数的范围为[0,1]时,有些人可能更喜欢把目标函数缩放到[0.1,0.9]这个范围。我怀疑这种小技巧的之所以流行起来是因为反向传播的标准化太慢了导致的。但用这种方法可能会使输出的后验概率值不对。如果你使用一个有效的训练算法的话,完全不需要用这种小技巧,也没有必要去避免溢出(overflow)
13.1.3三种数据变换方法的含义与应用
名称 | 中文名 | 解释 |
---|---|---|
Rescaling | 重缩放/归一化 | 通常是指增加或者减少一个常数,然后乘以/除以一个常数,来改变数据的衡量单位。例如:将温度的衡量单位从摄氏度转化为华氏温度。 |
Normalizing | 正则化 | 通常是指除以向量的范数。例如:将一个向量的欧氏长度等价于1 。在神经网络中,"正则化"通常是指将向量的范围重缩放至最小化或者一定范围,使所有的元素都在[0,1]范围内。通常用于文本分类或者文本聚类中。 |
Standardizing | 标准化 | 通常是为了消除不同属性或样方间的不齐性,使同一样方内的不同属性间或同一属性在不同样方内的方差减小。例如:如果一个向量包含高斯分布的随机值,你可能会通过除以标准偏差来减少均值,然后获得零均值单位方差的"标准正态"随机变量。 |
1)Standardizing
z = (x - u) / s
u是训练样本的平均值,如果with_mean=False,则为0;
s是训练样本的标准偏差,如果with_std=False,则为1。
2)标准化(Standard Scaler)
计算训练集的平均值和标准差,以便测试数据集使用相同的变换。
3)归一化:将数据特征缩放至某一范围(scaling features to a range)
3.1) MinMax Scaler
X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) min
其中,min,max=特征范围。这种变换常用作零均值、单位方差标度的替代方法。将数据缩放至给定的最小值与最大值之间,通常是0与1之间。
3.2)Max Abs Scaler
将最大的绝对值缩放至单位大小(数据集的标准差非常非常小,有时数据中有很多很多零(稀疏数据)需要保存住0元素)。
4)sklearn.preprocessing.Binarizer
大于阈值的值映射到1,而小于或等于阈值的值映射到0。默认阈值为0时,只有正值映射到1。
5)谈谈正则化
正则化背景
监督机器学习问题无非就是"在调整参数时尽量减少误差" ,也就是在规则化参数的同时最小化误差。最小化误差是为了让我们的模型拟合我们的训练数据,而规则化参数是防止我们的模型过分拟合我们的训练数据。
问题背景:参数太多,会导致我们的模型复杂度上升,容易过拟合。
作用:
1、约束参数,降低模型复杂度。
2、规则项的使用还可以约束我们的模型的特性。这样就可以将人对这个模型的先验知识融入到模型的学习当中,强行地让学习到的模型具有人想要的特性,例如稀疏、低秩、平滑等等。
正则化公式
第一项-Loss函数
不同的loss函数,具有不同的拟合特性
Loss函数 | 方法 |
---|---|
Square loss | 最小二乘法 |
Hinge Loss(合页损失函数,SVM) | SVM |
exp-Loss(指数损失函数,AdaBoost) | 提升 Boosting算法 |
log-Loss(对数损失函数,LR) | 逻辑回归 |
cross-entropy loss (交叉熵损失函数,Softmax) | |
quadratic loss (平方误差损失函数) | 线性回归 |
absolution loss (绝对值损失函数) |
第二项- 规则化函数Ω(w)
一般是模型复杂度的单调递增函数,模型越复杂,规则化值就越大。比如,规则化项可以是模型参数向量的范数。然而,不同的选择对参数w的约束不同,取得的效果也不同,但我们在论文中常见的都聚集在:零范数、一范数、二范数、迹范数、Frobenius范数和核范数等等。
范数表达式
||x||p =
L0:||x||0 =
向量中非0 元素的个数
L1:||x||1 =
向量各绝对值之和(Lasso正则)稀疏化。
特征选择
可解性强
L2:||x||2 =
欧几里得距离(Ridge正则):得到稠密解,符合训练集过于复杂造成的过拟合。对应参数接近0但不为0。
13.1.4 Scaler类
代码语言:javascript复制class sklearn.preprocessing.StandardScaler(*, copy=True, with_mean=True, with_std=True)
属性
属性 | 类型 | 解释 |
---|---|---|
scale_ | ndarray of shape (n_features,) or None. | 每个特征对数据进行相对缩放,以实现零均值和单位方差。通常使用np.sqrt公司(变量)。如果方差为零,我们就不能得到单位方差,数据就保持原样,给出了1的比例因子。当标度为假时,标度为空。 |
mean_ | ndarray of shape (n_features,) or None. | 训练集中每个特征的平均值。当_mean=False时,等于无。 |
var_ | var_ndarray of shape (n_features,) or None. | 训练集中每个特征的方差。用于计算比例尺。当with_std=False时,等于无。 |
n_samples_seen_ | int or ndarray of shape (n_features,). | 估计器为每个特征处理的样本数。如果没有丢失的样本,则n_samples_seen将是一个整数,否则它将是一个dtype int数组。如果使用sample_weights,则它将是一个float(如果没有丢失数据)或一个dtype float数组,该数组对迄今为止看到的权重求和。将在新调用时重置为fit,但在部分fit调用中递增。 |
方法
fit(X[, y, sample_weight]) | 计算平均值和标准差,用于以后的定标。 |
---|---|
fit_transform(X[, y]) | 适应数据,然后转换它。 |
get_params([deep]) | 获取此估计器的参数。 |
inverse_transform(X[, copy]) | 将数据缩小到原始表示形式。 |
partial_fit(X[, y, sample_weight]) | 在线计算X轴上的平均值和标准差,以便以后缩放。 |
set_params(**params) | 设置此估计器的参数。 |
transform(X[, copy]) | 通过定心和缩放执行标准化 |
案例
代码语言:javascript复制from sklearn.datasets import make_blobs
# 导入画图工具
import matplotlib.pyplot as plt
# 导入数据划分模块、分为训练集和测试集
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
def my_preprocessing ():
# 产生40个新样本,分成2类,随机生成器的种子为8, 标准差为2
X,y = make_blobs(n_samples=40,centers=2, random_state=5,cluster_std=2)
#将数据集用散点图方式进行可视化分析
plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.cool)
plt.show()
代码语言:javascript复制X轴:(-12,0)
y轴:(5,13)
#使用StandardScaler进行处理
x_1 = StandardScaler().fit_transform(X)
plt.scatter(x_1[:,0],x_1[:,1],c=y,cmap=plt.cm.cool)
plt.title("StandardScaler")
plt.show()
X轴:(-3,3)
y轴:(-2,3)
StandardScaler原理:将所有数据转换为均值为0,方差为1的状态。
13.1.5 MinMaxScaler类
代码语言:javascript复制class sklearn.preprocessing.MinMaxScaler(feature_range=0, 1, *, copy=True, clip=False)
属性
属性 | 类型 | 解释 |
---|---|---|
min_ | ndarray of shape (n_features,) | 每个功能调整最小。相当于min - X.min(axis=0) * self.scale_ |
scale_ | ndarray of shape (n_features,) | 每个特征数据的相对比例。相当于(max - min) / (X.max(axis=0) - X.min(axis=0)) |
data_min_ | ndarray of shape (n_features,) | 数据中显示的每个特征的最小值 |
data_max_ | ndarray of shape (n_features,) | 数据中每个特征的最大值 |
data_range_ | ndarray of shape (n_features,) | 在数据中看到的每个特征范围(data_max_ - data_min_) |
n_samples_seen_ | Int | 估计器处理的样本数。它将在新调用时重置为fit,但会在partial_fit 调用中递增 |
方法
fit(X[, y]) | 计算用于以后缩放的最小值和最大值。 |
---|---|
fit_transform(X[, y]) | 适应数据,然后转换它。 |
get_params([deep]) | 获取此估计器的参数。 |
inverse_transform(X) | 根据特征范围撤消X的缩放。 |
partial_fit(X[, y]) | 在线计算X上的最小值和最大值,以便以后缩放。 |
set_params(**params) | 设置此估计器的参数。 |
transform(X) | 根据特征范围缩放X的特征。 |
from sklearn.preprocessing import MinMaxScaler
x_2 = MinMaxScaler().fit_transform(X)
plt.scatter(x_2[:,0], x_2[:,1],c=y,cmap=plt.cm.cool)
plt.title("MinMaxScaler")
plt.show()
X轴:(0,1)
y轴:(0,1)
MinMaxScaler原理:将所有数据压缩到长宽都是1的方块中去。
代码语言:javascript复制X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0)) ;
X_scaler = X_std/ (max - min) min
13.1.6 RobustScaler类
代码语言:javascript复制class sklearn.preprocessing.RobustScaler(*, with_centering=True, with_scaling=True, quantile_range=25.0, 75.0, copy=True, unit_variance=False)
使用对异常值具有鲁棒性的统计数据来缩放特征。
这个定标器移除中位数,并根据分位数范围(默认为IQR:四分位数范围)来缩放数据。IQR是第一个四分位数(第25个分位数)和第三个四分位数(第75个分位数)之间的范围。
通过计算训练集中样本的相关统计信息,对每个特征分别进行定心和缩放。然后存储中位数和四分位间距,以便使用变换方法在以后的数据上使用。
数据集的标准化是许多机器学习估计器的共同要求。通常,这是通过去除平均值和缩放到单位方差来实现的。然而,异常值通常会以负的方式影响样本均值/方差。在这种情况下,中位数和四分位间距通常会给出更好的结果。
属性
属性 | 类型 | 解释 |
---|---|---|
center_ | array of floats | 训练集中每个特征的中值。 |
scale_ | array of floats | 训练集中每个特征的(比例)四分位范围。 |
方法
fit(X[, y]) | 计算用于缩放的中位数和分位数。 |
---|---|
fit_transform(X[, y]) | 适应数据,然后转换它。 |
get_params([deep]) | 获取此估计器的参数。 |
inverse_transform(X) | 将数据缩小到原始表示形式。 |
set_params(**params) | 设置此估计器的参数。 |
transform(X) | 集中和缩放数据。 |
from sklearn.preprocessing import RobustScaler
x_3 = RobustScaler().fit_transform(X)
plt.scatter(x_3[:,0], x_3[:,1],c=y,cmap=plt.cm.cool)
plt.title("RobustScale")
plt.show()
X轴:(-3,2)
y轴:(-1,2.0)
RobustScaler原理:与StandardScaler略同,结果不同。
如果你的数据有离群点,对数据进行均差和方差的标准化效果并不好。这种情况你可以使用robust_scale 和 RobustScaler 作为替代。它们有对数据中心化和数据的缩放鲁棒性更强的参数。
13.1.7 Normalizer类
代码语言:javascript复制class sklearn.preprocessing.Normalizer(norm='l2', *, copy=True)
将样本分别标准化为单位标准。
具有至少一个非零分量的每个样本(即数据矩阵的每一行)独立于其他样本重新缩放,使得其范数(l1、l2或inf)等于1。
这种转换器能够与密集的numpy阵列和稀疏的矩阵(如果要避免复制/转换的负担,请使用CSR格式)。
例如,将输入缩放到单位规范是文本分类或聚类的常见操作。例如,两个l2规范化TF-IDF向量的点积是向量的余弦相似性,并且是信息检索界常用的向量空间模型的基本相似性度量。
方法
fit(X[, y]) | 什么也不做,返回估计器不变。 |
---|---|
fit_transform(X[, y]) | 适应数据,然后转换它。 |
get_params([deep]) | 获取此估计器的参数。 |
set_params(**params) | 设置此估计器的参数。 |
transform(X[, copy]) | 将X的每个非零行缩放到单位标准。 |
from sklearn.preprocessing import Normalizer
x_4 = Normalizer().fit_transform(X)
plt.scatter(x_4[:,0], x_4[:,1],c=y,cmap=plt.cm.cool)
plt.title("Normalizer")
plt.show()
X轴:(-0.9,-0.1)
y轴:(-0.5,1.0)
Normalizer原理:把特征向量变成一个半径为1的圆或球(保留特征向量忽略数值)。
MaxAbsScaler、QuantileTransformer、Binarizer类
代码语言:javascript复制from sklearn.preprocessing import MaxAbsScaler
from sklearn.preprocessing import QuantileTransformer
from sklearn.preprocessing import Binarizer
x_5 = MaxAbsScaler().fit_transform(X)
plt.scatter(x_5[:,0], x_5[:,1],c=y,cmap=plt.cm.cool)
plt.title("MaxAbsScaler")
plt.show()
x_6 = QuantileTransformer().fit_transform(X)
plt.scatter(x_6[:,0], x_6[:,1],c=y,cmap=plt.cm.cool)
plt.title("QuantileTransformer")
plt.show()
x_7 = Binarizer().fit_transform(X)
plt.scatter(x_7[:,0], x_7[:,1],c=y,cmap=plt.cm.cool)
plt.title("Binarizer")
plt.show()
X轴:(-1,0)
y轴:(-4,1)
X轴:(0,1)
y轴:(0,1)
集中在[0,1]
13.1.8数据处理的作用
代码语言:javascript复制from sklearn.neural_network import MLPClassifier
from sklearn import datasets
def sklearn_for_Nerver():
wine = datasets.load_wine()
X_train,X_test,y_train,y_test = train_test_split(wine.data,wine.target,random_state=62)
mlp = MLPClassifier(hidden_layer_sizes=[100],max_iter=4000,random_state=62)
mlp.fit(X_train,y_train)
print("改造前训练模型得分{:.2%}".format(mlp.score(X_train,y_train)))
print("改造前测试模型得分{:.2%}".format(mlp.score(X_test,y_test)))
scaler = MinMaxScaler()
scaler.fit(X_train)
X_train_pp = scaler.transform(X_train)
X_test_pp = scaler.transform(X_test)
mlp.fit(X_train_pp,y_train)
print("改造后训练模型得分{:.2%}".format(mlp.score(X_train_pp,y_train)))
print("改造后测试模型得分{:.2%}".format(mlp.score(X_test_pp,y_test)))
输出
代码语言:javascript复制改造前训练模型得分62.41%
改造前测试模型得分48.89%
改造后训练模型得分100.00%
改造后测试模型得分100.00%