ML Notes
This article records my process of learning machine learning.
数据预处理
标准化
Reason: 对于大多数数据挖掘算法来说,数据集的标准化是基本要求。这是因为,如果特征不服从或者近似服从标准正态分布(即,零均值、单位标准差的正态分布)的话,算法的表现会大打折扣。实际上,我们经常忽略数据的分布形状,而仅仅做零均值、单位标准差的处理。在一个机器学习算法的目标函数里的很多元素所有特征都近似零均值,方差具有相同的阶。如果某个特征的方差的数量级大于其它的特征,那么,这个特征可能在目标函数中占主导地位,这使得模型不能从其它特征有效地学习。
Z-score标准化
这种方法基于原始数据的均值mean和标准差standard deviation进行数据的标准化。将特征A的原始值x使用z-score标准化到x’。z-score标准化方法适用于特征A的最大值和最小值未知的情况,或有超出取值范围的离群数据的情况。将数据按其特征(按列进行)减去其均值,然后除以其方差。最后得到的结果是,对每个特征/每列来说所有数据都聚集在0附近,方差值为1。数学公式如下:
函数scale为数组形状的数据集的标准化提供了一个快捷实现:
1 | from sklearn import preprocessing |
Min-Max 标准化
Min-max标准化方法是对原始数据进行线性变换。设minA和maxA分别为特征A的最小值和最大值,将A的一个原始值x通过min-max标准化映射成在区间[0,1]中的值x',其公式为:
可以使用MinMaxScaler实现,以下是一个将简单的数据矩阵缩放到[0, 1]的例子:
1 | from sklearn import preprocessing |
MaxAbs标准化
MaxAbs的工作原理与Min-max非常相似,但是它只通过除以每个特征的最大值将训练数据特征缩放至 [-1, 1] 范围内,这就意味着,训练数据应该是已经零中心化或者是稀疏数据。公式如下:
可以使用MaxAbsScale实现,以下是使用上例中数据运用这个缩放器的例子:
1 | from sklearn import preprocessing |
非线性转换
Reason: 对于大多数数据挖掘算法来说,如果特征不服从或者近似服从标准正态分布(即,零均值、单位标准差的正态分布)的话,算法的表现会大打折扣。非线性转换就是将我们的特征映射到均匀分布或者高斯分布(即正态分布)。
映射到均匀分布
相比线性缩放,该方法不受异常值影响,它将数据映射到了零到一的均匀分布上,将最大的数映射为1,最小的数映射为0。其它的数按从小到大的顺序均匀分布在0到1之间,如有相同的数则取平均值,如数据为np.array([[1],[2],[3],[4],[5]])则经过转换为:np.array([[0],[0.25],[0.5],[0.75],[1]]),数据为np.array([[1],[2],[9],[10],[2]])则经过转换为:np.array([[0],[0.375],[0.75],[1.0],[0.375]])。第二个例子具体过程如下图:
在sklearn中使用QuantileTransformer方法实现,用法如下:
1 | from sklearn.preprocessing import QuantileTransformer |
映射到高斯分布
映射到高斯分布是为了稳定方差,并最小化偏差。在最新版sklearn 0.20.x中PowerTransformer现在有两种映射方法,Yeo-Johnson映射,公式如下:
Box-Cox映射,公式如下:
在sklearn 0.20.x中使用PowerTransformer方法实现,用法如下:
1 | from sklearn.preprocessing import PowerTransformer |
归一化
Reason: 归一化是缩放单个样本以具有单位范数的过程。归一化实质是一种线性变换,线性变换有很多良好的性质,这些性质决定了对数据改变后不会造成“失效”,反而能提高数据的表现,这些性质是归一化的前提。归一化能够加快模型训练速度,统一特征量纲,避免数值太大。值得注意的是,归一化是对每一个样本做转换,所以是对数据的每一行进行变换。而之前我们讲过的方法是对数据的每一列做变换。
L1范式归一化
L1范式定义如下:
表示向量x中每个元素的绝对值之和。L1范式归一化就是将样本中每个特征除以特征的L1范式。
在sklearn中使用normalize方法实现,用法如下:
1 | from sklearn.preprocessing import normalize |
L2范式归一化
L2范式定义如下:
表示向量元素的平方和再开平方根。L2范式归一化就是将样本中每个特征除以特征的L2范式。
在sklearn中使用normalize方法实现,用法如下:
1 | from sklearn.preprocessing import normalize |
离散值编码
LabelEncoder
在数据挖掘中,特征经常不是数值型的而是分类型的。举个例子,一个人可能有["male", "female"],["from Europe", "from US", "from Asia"],["uses Firefox", "uses Chrome", "uses Safari", "uses Internet Explorer"]等分类的特征。这些特征能够被有效地编码成整数,比如["male", "from US", "uses Internet Explorer"]可以被表示为[0, 1, 3],["female", "from Asia", "uses Chrome"]表示为[1, 2, 1]。
在sklearn中,通过LabelEncoder来实现:
1 | from sklearn.preprocessing import LabelEncoder |
OneHotEncoder
这种整数特征表示并不能在sklearn的估计器中直接使用,因为这样的连续输入,估计器会认为类别之间是有序的,但实际却是无序的。如将male,female,转换为1,0。1比0要大,机器就会把这个关系考虑进去,而male,female之间是没有这样的关系的。所以我们需要使用另外一种编码方式,OneHot编码。
在sklearn中通过OneHotEncoder来实现,使用方法如下:
1 | import numpy as np |
生成多项式特征
Reason: 在数据挖掘中,获取数据的代价经常是非常高昂的。所以有时就需要人为的制造一些特征,并且有的特征之间是有关联的。生成多项式特征可以轻松的为我们获取更多的数据,并获得特征的更高维度和互相间关系的项且引入了特征之间的非线性关系,可以有效的增加模型的复杂度。
PolynomialFeatures
在sklearn中通过PolynomialFeatures方法来生成多项式特征,使用方法如下:
1 | import numpy as np |
特征转换情况如下:
在一些情况下,只需要特征间的交互项,这可以通过设置 interaction_only=True来得到:
1 | import numpy as np |
特征转换情况如下:
估算缺失值
Reason: 由于各种原因,真实世界中的许多数据集都包含缺失数据,这类数据经常被编码成空格、
NaNs,或者是其他的占位符。但是这样的数据集并不能被sklearn学习算法兼容,因为大多的学习算法都默认假设数组中的元素都是数值,因而所有的元素都有自己的意义。 使用不完整的数据集的一个基本策略就是舍弃掉整行或整列包含缺失值的数据。但是这样就付出了舍弃可能有价值数据(即使是不完整的 )的代价。 处理缺失数值的一个更好的策略就是从已有的数据推断出缺失的数值。
Imputer
sklearn中使用Imputer方法估算缺失值,使用方法如下:
1 | from sklearn.impute import SimpleImputer |
其中strategy参数用来选择代替缺失值方法:
1 | `mean`表示使用平均值代替缺失值 |
missing_values参数表示何为缺失值:
1 | `NaN`表示`np.nan`为缺失值 |
回归算法(此处涉及线性回归)
线性回归模型
LinearRegression
LinearRegression的构造函数中有两个常用的参数可以设置:
fit_intercept:是否有截据,如果没有则直线过原点,默认为Ture。normalize:是否将数据归一化,默认为False。
LinearRegression类中的fit函数用于训练模型,fit函数有两个向量输入:
X:大小为**[样本数量,特征数量]**的ndarray,存放训练样本Y:值为整型,大小为**[样本数量]**的ndarray,存放训练样本的标签值
LinearRegression类中的predict函数用于预测,返回预测值,predict函数有一个向量输入:
X:大小为**[样本数量,特征数量]**的ndarray,存放预测样本
LinearRegression的使用代码如下:
1 | import pandas as pd |
衡量线性回归的性能指标
R-Squared
公式如下:
其中ymean表示所有测试样本标签值的均值。为什么这个指标会有刚刚我们提到的性能呢?我们分析下公式:
其实分子表示的是模型预测时产生的误差,分母表示的是对任意样本都预测为所有标签均值时产生的误差,由此可知:
- R2leq1,当我们的模型不犯任何错误时,取最大值
1; - 当我们的模型性能跟基模型性能相同时,取
0; - 如果为负数,则说明我们训练出来的模型还不如基准模型,此时,很有可能我们的数据不存在任何线性关系。
R2使用代码
1 | from sklearn.metrics import r2_score |