工具学习 -python -04 Sklearn
借着别人的文章(王圣元 [王的机器] ),复盘一下python的基础知识点。感谢原作者的分享!
Sklearn (全称 Scikit-Learn) 是基于 Python 语言的机器学习工具。它建立在 NumPy, SciPy, Pandas 和 Matplotlib 之上,里面的 API 的设计非常好,所有对象的接口简单,很适合新手上路。
在 Sklearn 里面有六大任务模块:分别是分类、回归、聚类、降维、模型选择和预处理,如下图从其官网的截屏。
image.png要使用上述六大模块的方法,可以用以下的伪代码,注意 import 后面我用的都是一些通用名称,如 SomeClassifier, SomeRegressor, SomeModel,具体化的名称由具体问题而定,比如
- SomeClassifier = RandomForestClassifier
- SomeRegressor = LinearRegression
- SomeModel = KMeans, PCA
- SomeModel = GridSearchCV, OneHotEncoder
# 分类 (Classification)
from sklearn import SomeClassifier
from sklearn.linear_model import SomeClassifier
from sklearn.ensemble import SomeClassifier
# 回归 (Regression)
from sklearn import SomeRegressor
from sklearn.linear_model import SomeRegressor
from sklearn.ensemble import SomeRegressor
# 聚类 (Clustering)
from sklearn.cluster import SomeModel
# 降维 (Dimensionality Reduction)
from sklearn.decomposition import SomeModel
# 模型选择 (Model Selection)
from sklearn.model_selection import SomeModel
# 预处理 (Preprocessing)
from sklearn.preprocessing import SomeModel
SomeClassifier, SomeRegressor, SomeModel 其实都叫做估计器 (estimator),就像 Python 里「万物皆对象」那样,Sklearn 里「万物皆估计器」。
此外,Sklearn 里面还有很多自带数据集供,引入它们的伪代码如下。
数据集 (Dataset)
from sklearn.datasets import SomeData
本文我们用以下思路来讲解:
-
第一章介绍机器学习,从定义出发引出机器学习四要素:数据、任务、性能度量和模型。加这一章的原因是不把机器学习相关概念弄清楚之后很难完全弄明白 Sklearn。
-
第二章介绍 Sklearn,从其 API 设计原理出发分析其五大特点:一致性、可检验、标准类、可组合和默认值。最后再分析 Sklearn 里面自带数据以及储存格式。
-
第三章介绍 Sklearn 里面的三大核心 API,包括估计器、预测器和转换器。这一章的内容最重要,几乎所有模型都会用到这三大 API。
-
第四章介绍 Sklearn 里面的高级 API,即元估计器,有可以大大简化代码量的流水线 (Pipeline 估计器),有集成模型 (Ensemble 估计器)、有多类别-多标签-多输出分类模型 (Multiclass 和 Multioutput 估计器) 和模型选择工具 (Model Selection 估计器)。
1 机器学习简介
1.1 定义和组成元素
什么是机器学习?字面上来讲就是 (人用) 计算机来学习。谈起机器学习就一定要提起汤姆米切尔 (Tom M.Mitchell),就像谈起音乐就会提起贝多芬,谈起篮球就会提起迈克尔乔丹,谈起电影就会提起莱昂纳多迪卡普里奥。米切尔对机器学习定义的原话是:
A computer program is said to learn from experience E with respect to some class of tasks T and performance measure P if its performance at tasks in T, as measured by P, improves with experience E.
假设用性能度量 P 来评估机器在某类任务 T 的性能,若该机器通利用经验 E 在任务 T 中改善其性能 P,那么可以说机器对经验 E 进行了学习。
在该定义中,除了核心词机器和学习,还有关键词经验 E,性能度量 P 和任务 T。在计算机系统中,通常经验 E 是以数据 D 的形式存在,而机器学习就是给定不同的任务 T 从数据中产生模型 M,模型 M 的好坏就用性能度量 P 来评估。
由上述机器学习的定义可知机器学习包含四个元素:
数据 (Data),任务 (Task),性能度量 (Quality Metric) 和 模型 (Model)
1.2 数据
数据 (data) 是经验的另一种说法,也是信息的载体。数据可分为
- 结构化数据和非结构化数据 (按数据具体类型划分)
- 原始数据和加工数据 (按数据表达形式划分)
- 样本内数据和样本外数据 (按数据统计性质划分)
在统计中,把研究对象的全体称为总体 (population),而把组成总体的各个元素称为个体,把从总体中抽取的若干个体称为样本 (sample)。举个调查中国男性平均身高的例子:普查所有男性金钱花费和时间成本太高,通常会抽取若干男性作为样本,计算样本里的男性平均身高作为总体里的所有男性平均身高的推理 (inference)。
统计学中做的事情就是用样本数据的统计 (statistics) 来推出总体数据的参数 (parameter)。样本数据也叫做样本内数据,除样本内数据之外的总体数据叫做样本外数据。
在机器学习中,样本内和样本外数据的定义稍微有些不同
样本内数据是用来训练模型的数据,也叫训练数据。它们是已知的,可计算统计的。样本外数据是未来的没见过的新数据。它们是未知的,不可计算统计的。
1.3 任务
根据学习的任务模式 (训练数据是否有标签),机器学习可分为四大类:
- 有监督学习 (有标签)
- 无监督学习 (无标签)
- 半监督学习 (有部分标签)
- 增强学习 (有评级标签)
深度学习只是一种方法,而不是任务模式,因此与上面四类不属于同一个维度,但是深度学习与它们可以叠加成:深度有监督学习、深度非监督学习、深度半监督学习和深度增强学习。迁移学习也是一种方法,也可以分类为有监督迁移学习、非监督迁移学习、半监督迁移学习和增强迁移学习。
1.4 性能度量
回归和分类任务中最常见的误差函数以及一些有用的性能度量如下。
image.png除上述损失函数之外,分类任务还有很多其他有用的性能度量。
错误率:分类错误的样本数占样本总数的比例称为错误率 (error rate),相应的分类正确的样本数占样本总数的比例称为精度 (accuracy)。在 10 个样本中有 2 个样本分类错误,则错误率为 20%,而精度为 80%。
查准率和查全率:错误率和精度虽然常用,但是不能满足所有任务需求。假定用训练好的模型预测骑士赢球,显然,错误率衡量了多少比赛实际是赢球但预测成输球。但是若我们关心的是“预测出的比赛中有多少是赢球”,或“赢球的比赛中有多少被预测出了”,那么错误率这个单一指标显然就不够用了,这时需要引进更为细分的性能度量,即查准率 (precision) 和查全率 (recall)。
其他概念比如混淆矩阵、ROC、AUC 我们再下帖的实例用到时再细讲。
1.5 模型
有监督模型如下图所示:
image.png无监督模型包括各种聚类分析 (KMeans, DBSCAN)、主成分分析 (PCA)、独立成分分析 (ICA)、隐含狄利克雷分配 (LDA) 等等。
2 Sklearn 数据
Sklearn 和之前讨论的 NumPy, SciPy, Pandas, Matplotlib 相似,就是一个处理特殊任务的包,Sklearn 就是处理机器学习 (有监督学习和无监督学习) 的包,更精确的说,它里面有六个任务模块和一个数据引入模块:
-
有监督学习的分类任务
-
有监督学习的回归任务
-
无监督学习的聚类任务
-
无监督学习的降维任务
-
数据预处理任务
-
模型选择任务
-
数据引入
2.1 数据格式
在 Sklean 里,模型能即用的数据有两种形式:
- Numpy 二维数组 (ndarray) 的稠密数据 (dense data),通常都是这种格式。
- SciPy 矩阵 (scipy.sparse.matrix) 的稀疏数据 (sparse data),比如文本分析每个单词 (字典有 100000 个词) 做独热编码得到矩阵有很多 0,这时用 ndarray 就不合适了,太耗内存。
上述数据在机器学习中通常用符号 X 表示,是模型自变量。它的大小 = [样本数, 特征数]。有监督学习除了需要特征 X 还需要标签 y,而 y 通常就是 Numpy 一维数组,无监督学习没有 y。
2.2 自带数据集
Sklearn 里面有很多自带数据集供用户使用。来看看 Sklearn 三种引入数据形式。
打包好的数据:对于小数据集,用 sklearn.datasets.load_*
分流下载数据:对于大数据集,用 sklearn.datasets.fetch_*
随机创建数据:为了快速展示,用 sklearn.datasets.make_*
3 核心 API
Sklearn 里万物皆估计器。估计器是个非常抽象的叫法,可把它不严谨的当成一个模型 (用来回归、分类、聚类、降维),或当成一套流程 (预处理、网格最终)。
本节三大 API 其实都是估计器:
- 估计器 (estimator) 当然是估计器
- 预测器 (predictor) 是具有预测功能的估计器
- 转换器 (transformer) 是具有转换功能的估计器
这三句看似废话,其实蕴藏了很多内容。其实我对第 1 点这个估计器的起名不太满意,我觉得应该叫拟合器 (fitter) - 具有拟合功能的估计器。看完这一节你就会明白「拟合器」这种叫法更合理。
3.1 估计器
定义:任何可以基于数据集对一些参数进行估计的对象都被称为估计器。
两个核心点:1. 需要输入数据,2. 可以估计参数。估计器首先被创建,然后被拟合。
创建估计器:需要设置一组超参数,比如
- 线性回归里超参数 normalize=True
- K 均值里超参数 n_clusters=3
在创建好的估计器 model 可以直接访问这些超参数,用 . 符号。
- model.normalize
- model.n_clusters
但 model 中有很多超参数,你不可能一开始都知道要设置什么值,没设置的用 Sklearn 会给个合理的默认值,因此新手不用担心。
拟合估计器:需要训练集。
在有监督学习中的代码范式为:model.fit( X_train, y_train )
在无监督学习中的代码范式为:model.fit( X_train )
拟合之后可以访问 model 里学到的参数,比如线性回归里的特征前的系数 coef_,或 K 均值里聚类标签 labels_。
- model.coef_
- model.labels_
说了这么多抽象的东西,现在展示有监督学习的「线性回归」的具体例子。
线性回归
# 首先从 sklearn 下的 linear_model 中引入 LinearRegression,再创建估计器起名 model,设置超参数 normalize 为 **True**,指的在每个特征值上做标准化,这样会加速数值运算。
from sklearn.linear_model import LinearRegression
model = LinearRegression(normalize=True)
# 自己创建一个简单数据集 (没有噪声完全线性) 只为了讲解估计器里面的特征。
x = np.arange(10)
y = 2 * x + 1
plt.plot( x, y, 'o' )
# Sklearn 里模型要求特征 X 是个两维变量么 (样本数×特征数)?但在本例中 X 是一维,因为我们用 np.newaxis 加一个维度,它做的事情就是把 [1, 2, 3] 转成 [[1],[2],[3]]。再把 X 和 y 丢进 fit() 函数来拟合线性模型的参数。
X = x[:, np.newaxis]
model.fit( X, y )
#拟合完后的估计器和创建完的样子看起来一样,但是已经用「model.param_」可以访问到学好的参数了,展示如下。
print( model.coef_ )
print( model.intercept_ )
3.2 预测器
定义:预测器在估计器上做了一个延展,延展出预测的功能。
两个核心点:1. 基于学到的参数预测,2. 预测有很多指标。最常见的就是 predict() 函数:
-
model.predict(X_test):评估模型在新数据上的表现
-
model.predict(X_train):确认模型在老数据上的表现
举个例子:
# 加载数据集
from sklearn.datasets import load_iris
iris = load_iris()
# 切分数据集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split( iris['data'], iris['target'], test_size=0.2 )
# 创建估计器
from sklearn.linear_model import LinearRegression
model = LinearRegression(solver = 'lbfgs')
# 拟合估计器
model.fit(X_train, y_train)
# 预测器
y_pred = model.predict( X_test ) #预测的类别
p_pred = model.predict_proba( X_test ) # 预测该类别的信心
预测器里还有额外的两个函数可以使用。在分类问题中
score() 返回的是分类准确率
decision_function() 返回的是每个样例在每个类下的分数值
print( model.score( X_test, y_test ) )
decision_score = model.decision_function( X_test )
print( decision_score )
小节: 估计器都有 fit() 方法,预测器都有 predict() 和 score() 方法,言外之意不是每个预测器都有 predict_proba() 和 decision_function() 方法
3.3 转换器
定义:转换器也是一种估计器,两者都带拟合功能,但估计器做完拟合来预测,而转换器做完拟合来转换。
核心点:估计器里 fit + predict,转换器里 fit + transform。
本节介绍两大类转换器
- 将分类型变量 (categorical) 编码成数值型变量 (numerical)
- 规范化 (normalize) 或标准化 (standardize) 数值型变量
3.3.1分类型变量编码
LabelEncoder & OrdinalEncoder
LabelEncoder和 OrdinalEncoder 都可以将字符转成数字,但是
-
LabelEncoder的输入是一维,比如 1d ndarray
-
OrdinalEncoder 的输入是二维,比如 DataFrame
# 首先给出要编码的列表 enc 和要解码的列表 dec。
enc = ['win','draw','lose','win']
dec = ['draw','draw','win']
# LabelEncoder编码
# 从 sklearn 下的 preprocessing 中引入 LabelEncoder,再创建转换器起名 LE。
from sklearn.preprocessing import LabelEncoder
LE = LabelEncoder()
print( LE.fit(enc) ) --LabelEncoder()
print( LE.classes_ ) --['draw' 'lose' 'win']
print( LE.transform(dec) ) --[0 0 2]
# OrdinalEncoder编码
# 从 sklearn 下的 preprocessing 中引入 OrdinalEncoder,再创建转换器起名 OE
from sklearn.preprocessing import OrdinalEncoder
OE = OrdinalEncoder()
enc_DF = pd.DataFrame(enc)
dec_DF = pd.DataFrame(dec)
print( OE.fit(enc_DF) ) --OrdinalEncoder(categories='auto', dtype=<class 'numpy.float64'>)
print( OE.categories_ ) --[array(['draw', 'lose', 'win'], dtype=object)]
print( OE.transform(dec_DF) ) --[[0.] [0.] [2.]]
OneHotEncoder
转换器 OneHotEncoder 可以接受两种类型的输入:
- 用 LabelEncoder 编码好的一维数组
- DataFrame
from sklearn.preprocessing import OneHotEncoder
# 1. 用 LabelEncoder 编码好的一维数组 (元素为整数),重塑 成二维数组作为 OneHotEncoder 输入。
OHE = OneHotEncoder()
num = LE.fit_transform( enc )
print( num ) --[2 0 1 2]
OHE_y = OHE.fit_transform( num.reshape(-1,1) )
OHE_y.toarray() # 想看该矩阵里具体内容,用 toarray() 函数。
--array([[0., 0., 1.],
[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
# 2. 用 DataFrame作为 OneHotEncoder 输入
OHE = OneHotEncoder()
OHE.fit_transform( enc_DF ).toarray()
3.3.2特征缩放
数据要做的最重要的转换之一是特征缩放 (feature scaling)。当输入的数值的量刚不同时,机器学习算法的性能都不会好。具体来说,对于某个特征,我们有两种方法:
- 标准化 (standardization):每个维度的特征减去该特征均值,除以该维度的标准差。
- 规范化 (normalization):每个维度的特征减去该特征最小值,除以该特征的最大值与最小值之差。
MinMaxScaler 与 StandardScaler
整套转换器「先创建再 fit 在 transform」的流程应该很清楚了。自己读下面代码看看是不是秒懂。唯一需要注意的就是输入 X 要求是两维。
# MinMaxScaler
from sklearn.preprocessing import MinMaxScaler
X = np.array( [0, 0.5, 1, 1.5, 2, 100] )
X_scale = MinMaxScaler().fit_transform( X.reshape(-1,1) )
# StandardScaler
from sklearn.preprocessing import StandardScaler
X_scale = StandardScaler().fit_transform( X.reshape(-1,1) )
警示: fit() 函数只能作用在训练集上,千万不要作用在测试集上,要不然你就犯了数据窥探的错误了!拿标准化举例,用训练集 fit 出来的均值和标准差参数,来对测试集做标准化。
4 高级 API
Sklearn 里核心 API 接口是估计器,那高级 API 接口就是元估计器 (meta-estimator),即由很多基估计器 (base estimator) 组合成的估计器。元估计器把估计器当成参数。代码范式大概如下:
meta_model( base_model )
本节讨论五大元估计器,分别带集成功能的 ensemble,多分类和多标签的 multiclass,多输出的 multioutput,选择模型的 model_selection,和流水线的 pipeline。
1 ensemble.BaggingClassifier
2 ensemble.VotingClassifier
3 multiclass.OneVsOneClassifier
4 multiclass.OneVsRestClassifier
5 multioutput.MultiOutputClassifier
6 model_selection.GridSearchCV
7 model_selection.RandomizedSearchCV
8 pipeline.Pipeline
在下面五节,我们会用的鸢尾花数据 iris 和数字数据 digits,还有一些自己创建的数据。
4.1 Ensemble 估计器
Ensemble 估计器是用来做集成学习,该估计器里面有若干个分类器 (classifier) 或回归器 (regressor)。
最常用的 Ensemble 估计器排列如下:
-
AdaBoostClassifier
: 逐步提升分类器 -
AdaBoostRegressor
: 逐步提升回归器 -
BaggingClassifier
: 装袋分类器 -
BaggingRegressor
: 装袋回归器 -
GradientBoostingClassifier
: 梯度提升分类器 -
GradientBoostingRegressor
: 梯度提升回归器 -
RandomForestClassifier
: 随机森林分类器 -
RandomForestRegressor
: 随机森林回归器 -
VotingClassifier
: 投票分类器 -
VotingRegressor
: 投票回归器
我们用鸢尾花数据 iris,拿
含同质估计器 RandomForestClassifier
含异质估计器 VotingClassifier
来举例。首先将数据分成 80:20 的训练集和测试集,并引入 metrics 来计算各种性能指标。
from sklearn.datasets import load_iris
iris = load_iris()
from sklearn.model_selection import train_test_split
from sklearn import metrics
X_train, X_test, y_train, y_test = train_test_split( iris['data'], iris['target'], test_size=0.2 )```
RandomForestClassifier
随机森林 (random forest) 是决策树 (decision tree) 的一种集成模型,每棵决策树处理的数据用装袋法 (bagging) 生成。随机森林可以减小预测的方差,并且可以评估特征重要性。
from sklearn.ensemble import RandomForestClassifier
# 4 棵决策树 (森林由树组成);此外每棵树的最大树深为 5
RF = RandomForestClassifier( n_estimators=4, max_depth=5 )
RF.fit( X_train, y_train )
# 拟合 RF 完再做预测
print ( "RF - Accuracy (Train): %.4g" % metrics.accuracy_score(y_train, RF.predict(X_train)) )
--RF - Accuracy (Train): 0.9833
print ( "RF - Accuracy (Test): %.4g" % metrics.accuracy_score(y_test, RF.predict(X_test)) )
--RF - Accuracy (Test): 1
print( RF.n_estimators ) --4
RF.estimators_
image.png
VotingClassifier
和随机森林由同质分类器「决策树」不同,投票分类器由若干个异质分类器组成。下例用 VotingClassifier 建立个含有对率回归 (LR)、随机森林 (RF) 和高斯朴素贝叶斯 (GNB) 三个分类器的集成模型。
RandomForestClassifier 的基分类器只能是决策树,因此只用通过控制 n_estimators 超参数来决定树的个数,而 VotingClassifier 的基分类器要实实在在的输入其本身
from sklearn.linear_model import LinearRegression
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier
LR = LinearRegression(solver= 'lbfgs', multi_class='multinomial')
RF = RandomForestClassifier( n_estimators=5)
GNB = GaussianNB()
Ensemble = VotingClassifier(estimators = [('lr', LR), ('rf', RF),
('gnb', GNB)], voting='hard' )
Ensemble.fit( X_train, y_train )
print( len(Ensemble.estimators_) )
Ensemble.estimators_
image.png
比较元估计器和它三个组成元素的表现。还是集成后的 Ensemble 表现最好。
LR.fit( X_train, y_train )
RF.fit( X_train, y_train )
GNB.fit( X_train, y_train )
image.png
LR - Accuracy (Train): 0.975
RF - Accuracy (Train): 0.9833
GNB - Accuracy (Train): 0.95
Ensemble - Accuracy (Train): 0.9833
LR - Accuracy (Test): 1
RF - Accuracy (Test): 1
GNB - Accuracy (Test): 1
Ensemble - Accuracy (Test): 1
4.2 Multiclass 估计器
sklearn.multiclass 可以处理多类别 (multi-class) 的多标签 (multi-label) 的分类问题。
从小节 4.2 到 4.4,我们都会使用数字数据集 digits。首先将数据分成 80:20 的训练集和测试集。
from sklearn.datasets import load_digits
digits = load_digits()
digits.keys()
X_train, X_test, y_train, y_test
= train_test_split( digits['data'],
digits['target'],
test_size=0.2 )
4.2.1 多类别分类
手写数字有 0-9 十类,但手头上只有两分类估计器 (比如像支撑向量机) 怎么用呢?我们可以采取下面三种常见策略:
-
一对一 (One vs One, OvO):一个分类器用来处理数字 0 和数字 1,一个用来处理数字 0 和数字 2,一个用来处理数字 1 和 2,以此类推。N 个类需要 N(N-1)/2 个分类器。
-
一对其他 (One vs All, OvA):训练 10 个二分类器,每一个对应一个数字,第一个分类 1 和「非1」,第二个分类 2 和「非2」,以此类推。N 个类需要 N 个分类器。
OneVsOneClassifier
print( len(ovo_lr.estimators_) )
ovo_lr.estimators
image.png
OneVsRestClassifier
print( len(ova_lr.estimators_) )
ova_lr.estimators_
image.png
4.2.2 多标签分类
为了阐明「多标签分类」的原理。在手写数字的例子上,我们特意为每个数字设计了多标签:
-
标签 1 - 奇数、偶数
-
标签 2 - 小于等于 4,大于 4
再建立多标签 y_train_multilabel,代码如下 (OneVsRestClassifier 也可以用来做多标签分类):
from sklearn.multiclass import OneVsRestClassifier
y_train_multilabel = np.c_[ y_train%2==0, y_train<=4 ]
print(y_train_multilabel) --[[ True True] [False False] [False False] ... [False False] [False False] [False False]]
训练模型,只不过这时用的是 y_train_multilabel。
image.pngprint( len(ova_ml.estimators_) )
ova_ml.estimators_
image.png
4.3 Multioutput 估计器*
sklearn.multioutput 可以处理多输出 (multi-output) 的分类问题。
Multioutput 估计器有两个:
-
MultiOutputRegressor
: 多输出回归 -
MultiOutputClassifier
: 多输出分类
本节只关注多输出分类。
MultiOutputClassifier
首先引入 MultiOutputClassifier 和 RandomForestClassifier。你看,这两个都是元估计器,因此在 Sklearn 里面估计器可以随意组合。
from sklearn.multioutput import MultiOutputClassifier
from sklearn.ensemble import RandomForestClassifier
在手写数字的例子上,我们也为特意每个数字设计了多标签而且每个标签的类别都大于二。
- 标签 1 - 小于等于 4,4 和 7 之间,大于等于 7 (三类)
- 标签 2 - 数字本身 (十类)
代码如下:
from sklearn.multioutput import MultiOutputClassifier
from sklearn.ensemble import RandomForestClassifier
用含有 100 棵决策树的随机森林来解决这个多输入分类问题。
# 这个模型在测试集前五张照片上的预测。
MO.predict( X_test[:5,:] )
--array([[0, 2],
[0, 2],
[0, 0],
[2, 9],
[1, 5]])
# 真实标签
y_test_1st = y_test.copy()
y_test_1st[ y_test<=4 ] = 0
y_test_1st[ np.logical_and(y_test>4, y_test<7) ] = 1
y_test_1st[ y_test>=7 ] = 2
y_test_multioutput
= np.c_[ y_test_1st, y_test ]
y_test_multioutput[:5]
--array([[0, 2],
[0, 2],
[0, 0],
[2, 9],
[1, 5]]
4.4 Model Selection 估计器
模型选择 (Model Selction) 在机器学习非常重要,它主要用于评估模型表现,常见的 Model Selection 估计器有以下几个:
-
cross_validate
: 评估交叉验证的表现。 -
learning_curve
: 建立学习曲线。 -
GridSearchCV
: 用交叉验证从网格中一组超参数搜索出最佳超参数。 -
RandomizedSearchCV
: 用交叉验证从一组随机超参数搜索出最佳超参数。
本小节关注调节超参数的两个估计器,即上面列出的最后两个。它们都要用到交叉验证,我们来看这两个调参的估计器,网格追踪和随机追踪。
网格追踪:参数 1 在 [1, 10, 100, 1000] 中取值,**参数 2 **在 [0.01, 0.1, 1 10] 中取值,注意并不是等间距取值。模型在所有 16 个组合跑,选取一对对应最小交叉验证误差的参数。
随机追踪:根据指定分布随机搜索,可以选择独立于参数个数,比如 log(参数 1) 服从 0 到 3 的均匀分布, log(参数 2) 服从 -2 到 1 的均匀分布。此外,会设定一个预算参数。
原理讲清楚了,看代码吧。
image.png
4.5 Pipeline 估计器
Pipeline 估计器又叫流水线,把各种估计器串联 (Pipeline) 或并联 (FeatureUnion) 的方式组成一条龙服务。用好了它真的能大大提高效率。
4.5.1 Pipeline
Pipeline 将若干个估计器按顺序连在一起,比如
特征提取 -> 降维 -> 拟合 -> 预测
在整个 Pipeline 中,它的属性永远和最后一个估计器属性一样
-
如果最后一个估计器是预测器,那么 Pipeline 是预测器
-
如果最后一个估计器是转换器,那么 Pipeline 是转换器
下面用一个简单例子来说明如果用 Pipeline 来做「先填补缺失值-再标准化」这两步的。先生成含缺失值 NaN 的数据 X。
image.png首先引入 Pipeline,再引入
-
处理缺失值的转换器 SimpleImputer
-
做规划化的转换器 MinMaxScaler
由于最后一个估计器是转换器,因此 pipe 也是个转换器。写好了就可以那它来做「先填补缺失值-再标准化」的重复工作了。
看看运行结果,值都被填满了,而且两列也被标准化了。
image.png4.5.2 FeatureUnion
如果我们想在一个节点同时运行几个估计器,我们可用 FeatureUnion。下例首先建立一个 DataFrame,
-
前两列智力 IQ 和脾气 temper 都是分类型变量
-
后两列收入 income 和身高 height 都是数值型变量
-
每列中都有缺失值
image.png image.gif
我们现在按下列步骤来清洗数据。
-
对分类型变量:获取 -> 中位数填充 -> 独热编码
-
对数值型变量:获取 -> 均值填充 -> 标准化
上面两步是平行进行的。
首先我们自己定义一个从 DataFrame 里面获取每列的类,起名叫 DataFrameSelector
。
接下来建立一个流水线 full_pipe,它并联着两个流水线
- categorical_pipe 处理分类型变量
DataFrameSelector 用来获取
SimpleImputer 用出现最多的值来填充 None
OneHotEncoder 来编码返回非稀疏矩阵 - numeric_pipe 处理数值型变量
DataFrameSelector 用来获取
SimpleImputer 用均值来填充 NaN
normalize 来规范化数值
下面代码非常漂亮。
image.png将结果打印出来,齐活!
X_proc = full_pipe.fit_transform( X )
print( X_proc )
5 总结
结合本帖讲的总结一套机器学习的初级框架:
确定任务:是「有监督」的分类或回归?还是「无监督」的聚类或降维?确定好后基本就能知道用 Sklearn 里哪些模型了。
数据预处理:这步最繁琐,要处理缺失值、异常值;要编码分类型变量;要正规化或标准化数值型变量,等等。但是有了 Pipeline 神器一切变得简单高效。
训练和评估:这步最简单,训练用估计器 fit() 先拟合,评估用预测器 predict() 来评估。
选择模型:启动 Model Selection 估计器里的 GridSearchCV 和 RandomizedSearchCV,选择得分最高的那组超参数 (即模型)。