Intro
使用鸢尾花数据集:
from sklearn.datasets import load_iris
data = load_iris()
features = data.data
labels = data.target
其中features
是特征矩阵,labels
是真实分类。
1. 预处理(preprocessing)
1.1 预处理的目的
数据预处理的目的在于:使得特征数据在处理后,能让学习模型得到更好的效果。预处理通常会解决原始数据存在的如下问题:
- 量纲不同:比如可能存在两个特征,都是“长度”,但其中一个以千米为单位,一个以毫米为单位。直接让模型去学习这两个特征,明显是不科学的。
- 信息冗余:经常会有好几个特征表达同一个含义;或者某个特征过于具体或连续,但其实我们只需要一个区段标记或者“是”与“否”的标记。
- 定性(Categorical)的特征:比如国籍、XX状态等,需要处理成数值编码才可以被学习。
- 缺失值。
下面具体地介绍几种预处理的手段:
1.2 无量纲化
1.2.1 标准化(standardization)
常用的z-score标准化计算公式:
在sklearn库中,实现标准化的类是:StandardScaler。
from sklearn.preprocessing import StandardScaler
StandardScaler().fit_transform(features)
可以对比下转换前和转换后,第一行数据的形态:
# 转换前
[5.1, 3.5, 1.4, 0.2]
# 转换后
[-9.00681170e-01, 1.03205722e+00, -1.34127240e+00, -1.31297673e+00]
1.2.2 最大-最小值缩放(min-max scaler)
其实区间缩放的方式不止最大-最小值这一种,但这是最常用的一种,也是归一化方式的一种。公式如下:
sklearn中实现的类为MinMaxScaler:
from sklearn.preprocessing import MinMaxScaler
MinMaxScaler().fit_transform(features)
转换后特征变成 [0, 1] 区间内的数值:
# 转换后
[0.22222222, 0.625, 0.06779661, 0.04166667]
1.2.2 L2归一化(L2 Normalization)
其实上面的最大-最小值缩放也是归一化的一种,但通常说归一化,指的还是L2的归一化方式。公式如下:
特征转换后得到的也是 [0, 1] 区间内的数值。
代码如下:
from sklearn.preprocessing import Normalizer
Normalizer().fit_transform(features)
# 转换后
[0.80377277, 0.55160877, 0.22064351, 0.0315205 ]
标准化与归一化的区别在于:标准化是对一个特征的所有值求z-score,它并不会改变整个特征的分布。而归一化是对一个数据点做处理,得到的是一个更好的新的分布。
1.3 哑编码/独热编码
定性(categorical)的特征无法直接被学习器学习,必需先转换成数值型的编码。哑编码是最常用的方式,在sklearn中有OneHotEncoder类:
from sklearn.preprocessing import OneHotEncoder
OneHotEncoder().fit_transform(labels.reshape(-1, 1))
1.4 基于多项式的变换
数据变换,总体来说就是根据一定的规律造指标。这里介绍的是多项式,其实还可以基于指数函数或者log函数。多项式变换的核心在于“度”(degree)的选择,选择正确的度对于运算复杂度和最终预测结果都有很大的影响。
sklearn用于实现变换的类为:PolynomialFeatures。
from sklearn.preprocessing import PolynomialFeatures
# 其实可定义参数degree,默认值为2
PolynomialFeatures().fit_transform(features)
2. 特征选择
对特征数据的预处理只是第一步,在实际输入到学习器之前,还需要对特征的必要性进行排查。不必要的特征需要删除。
特征的选择通常从两方面来考虑:
- 特征方差取值:方差大的特征更具有选择性。
- 特征相关性:与label相关性越强的特征越好。
下面介绍三种常用的特征选择操作。
2.1 过滤(Filter)
2.1.1 方差过滤
单独计算每个特征的方差,设定阈值并只保留大于阈值的特征。在sklearn中是使用feature_selection库的VarianceThreshold类来实现。
from sklearn.feature_selection import VarianceThreshold
# threshold就是阈值
VarianceThreshold(threshold=3).fit_transform(features)
2.1.2 相关系数过滤
计算各个特征对目标值的相关系数以及相关系数的P值。用feature_selection库的SelectKBest类结合相关系数来选择特征的代码如下:
from sklearn.feature_selection import SelectKBest
from scipy.stats import pearsonr
SelectKBest(lambda X, Y: array(map(lambda x: pearsonr(x, Y), X.T)).T, k=2).fit_transform(features, labels)
2.1.3 卡方检验过滤
经典的卡方检验是检验定性自变量对定性因变量的相关性。假设自变量有N种取值,因变量有M种取值,考虑自变量等于i且因变量等于j的样本频数的观察值与期望的差距。
用feature_selection库的SelectKBest类结合卡方检验来选择特征的代码如下:
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
# 选择K个最好的特征,返回选择特征后的数据
SelectKBest(chi2, k=2).fit_transform(features, labels)
2.2 包裹(Wrapper)
2.2.1 递归特征消除
递归消除特征法使用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,再基于新的特征集进行下一轮训练。使用feature_selection库的RFE类来选择特征的代码如下:
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
#递归特征消除法,返回特征选择后的数据
#参数estimator为基模型
#参数n_features_to_select为选择的特征个数
RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(features, labels)
3. 特征降维
当特征选择完成后,可以直接训练模型了,但是可能由于特征矩阵过大,导致计算量大,训练时间长的问题,因此降低特征矩阵维度也是必不可少的。常见的降维方法除了以上提到的基于L1惩罚项的模型以外,另外还有主成分分析法(PCA)和线性判别分析(LDA),线性判别分析本身也是一个分类模型。PCA和LDA有很多的相似点,其本质是要将原始的样本映射到维度更低的样本空间中,但是PCA和LDA的映射目标不一样:PCA是为了让映射后的样本具有最大的发散性;而LDA是为了让映射后的样本有最好的分类性能。所以说PCA是一种无监督的降维方法,而LDA是一种有监督的降维方法。
3.1 主成分分析(PCA)
from sklearn.decomposition import PCA
# 主成分分析法,返回降维后的数据
# 参数n_components为主成分数目
PCA(n_components=2).fit_transform(features)
3.2 线性判别(LDA)
from sklearn.lda import LDA
# 线性判别分析法,返回降维后的数据
# 参数n_components为降维后的维数
LDA(n_components=2).fit_transform(features, labels)