开通VIP,畅享免费电子书等14项超值服
首页
好书
留言交流
下载APP
联系客服
2022.12.07北京
Sklearn(全称Scikit-Learn)是基于Python语言的机器学习工具。它建立在NumPy,SciPy,Pandas和Matplotlib之上,里面的API的设计非常好,所有对象的接口简单,很适合新手上路。
在Sklearn里面有六大任务模块:分别是分类、回归、聚类、降维、模型选择和预处理,如下图从其官网的截屏。
要使用上述六大模块的方法,可以用以下的伪代码,注意import后面我用的都是一些通用名称,如SomeClassifier,SomeRegressor,SomeModel,具体化的名称由具体问题而定,比如
上面具体化的例子分别是随机森林分类器、线性回归器、K均值聚类、主成分分析、网格追踪法、独热编码。
fromsklearnimportSomeRegressorfromsklearn.linear_modelimportSomeRegressorfromsklearn.ensembleimportSomeRegressor聚类(Clustering)fromsklearn.clusterimportSomeModel降维(DimensionalityReduction)fromsklearn.decompositionimportSomeModel模型选择(ModelSelection)fromsklearn.model_selectionimportSomeModel预处理(Preprocessing)fromsklearn.preprocessingimportSomeModelSomeClassifier,SomeRegressor,SomeModel其实都叫做估计器(estimator),就像Python里「万物皆对象」那样,Sklearn里「万物皆估计器」。
此外,Sklearn里面还有很多自带数据集供,引入它们的伪代码如下。
本贴我们用以下思路来讲解:
本帖目录如下:
第一章-机器学习简介
1.1定义和组成元素
1.2数据
1.3任务
1.4性能指标
1.5模型
第二章-Sklearn数据
2.1数据格式
2.2自带数据集
第三章-核心API
3.1估计器
3.2预测器
3.3转换器
第四章-高级API
4.1Ensemble估计器
4.2Multiclass估计器
4.3Multioutput估计器
4.4ModelSelection估计器
4.5Pipeline估计器
总结
建议认真仔细读第一章!
1.1
定义和组成元素
什么是机器学习?字面上来讲就是(人用)计算机来学习。谈起机器学习就一定要提起汤姆米切尔(TomM.Mitchell),就像谈起音乐就会提起贝多芬,谈起篮球就会提起迈克尔乔丹,谈起电影就会提起莱昂纳多迪卡普里奥。米切尔对机器学习定义的原话是:
AcomputerprogramissaidtolearnfromexperienceEwithrespecttosomeclassoftasksTandperformancemeasurePifitsperformanceattasksinT,asmeasuredbyP,improveswithexperienceE.
整段英文有点抽象难懂对吗?首先注意到两个词computerprogram和learn,翻译成中文就是机器(计算机程序)和学习,再把上面英译中:
假设用性能度量P来评估机器在某类任务T的性能,若该机器通利用经验E在任务T中改善其性能P,那么可以说机器对经验E进行了学习。
在该定义中,除了核心词机器和学习,还有关键词经验E,性能度量P和任务T。在计算机系统中,通常经验E是以数据D的形式存在,而机器学习就是给定不同的任务T从数据中产生模型M,模型M的好坏就用性能度量P来评估。
由上述机器学习的定义可知机器学习包含四个元素
下面四小节分别介绍数据、任务、性能度量和模型。
1.2
数据
数据(data)是经验的另一种说法,也是信息的载体。数据可分为
结构化数据(structureddata)是由二维表结构来逻辑表达和实现的数据。非结构化数据是没有预定义的数据,不便用数据库二维表来表现的数据。
非结构化数据包括图片,文字,语音和视屏等如下图。
计算机追根到底还是只能最有效率的处理数值型的结构化数据,如何从原始数据加工成计算机可应用的数据会在后面讲明。
机器学习模型主要使用的是结构化数据,即二维的数据表。非结构化数据可以转换成结构化数据,比如把
对于结构化数据,我们用勒布朗詹姆斯(LebronJames)四场比赛的数据举例。
下面术语大家在深入了解机器学习前一定要弄清楚:
计算机处理数值型的结构型数据最有效率,但是现实世界到处出是原始数据,分为两类
拿情况一的图片为例,通过特定函数imread将彩色图片用RGB像素表示出来,再按红绿蓝的顺序,将所有像素排成一个数值列向量(columnvector),而计算机可以接受这样的输入。具体转换过程见下图。
推特(twitter)的每条推文(tweet)规定只能发280个字符。在编码推文时,将280个字符的序列用独热编码(one-hotencoding)到包含128个字符的ASCII表,如下所示。
这样,每条推文都可以编码为2维张量形状(280,128),比如一条tweet是“Ilovepython:)”,这句话映射到ASCII表变成:
如果收集到1百万条推文,那么整个数据集的形状为(1000000,280,128)。传统机器学习的对率回归可以来做情感分析。
篮球比赛结果非输即赢,是一个二类(binaryclass)变量
二类变量用「0-1编码」,比如比赛结果={赢,输}表示成y=[1001],1代表赢,0代表输。
而足球比赛结果是有赢、平、输三种,是一个多类(multi-class)变量。
多类变量分别用0,1,2来表示,那么y=[0102]。但更常见的是用独热编码(one-hotencoding),即
在统计中,把研究对象的全体称为总体(population),而把组成总体的各个元素称为个体,把从总体中抽取的若干个体称为样本(sample)。
举个调查中国男性平均身高的例子:
统计学中做的事情就是用样本数据的统计(statistics)来推出总体数据的参数(parameter)。样本数据也叫做样本内数据,除样本内数据之外的总体数据叫做样本外数据。
在机器学习中,样本内和样本外数据的定义稍微有些不同,如下图:
样本内数据是用来训练模型的数据,也叫训练数据。它们是已知的,可计算统计的。
样本外数据是未来的没见过的新数据。它们是未知的,不可计算统计的。
机器学习在样本内数据训练模型用来预测:
1.3
任务
根据学习的任务模式(训练数据是否有标签),机器学习可分为四大类:
深度学习只是一种方法,而不是任务模式,因此与上面四类不属于同一个维度,但是深度学习与它们可以叠加成:深度有监督学习、深度非监督学习、深度半监督学习和深度增强学习。迁移学习也是一种方法,也可以分类为有监督迁移学习、非监督迁移学习、半监督迁移学习和增强迁移学习。
下图画出机器学习各类之间的关系。
由于Sklearn里面模型主要处理「有监督学习」和「无监督学习」两类,我们接下来也只讨论这两类。
有监督学习(supervisedlearning)利用输入数据及其对应标签来训练模型。这种学习方法类似学生通过研究问题和参考答案来学习,在掌握问题和答案之间的对应关系后,学生可自己给出相似新问题的答案了。
在有监督学习中,数据=(特征,标签),而其主要任务是分类和回归。以上述詹姆斯的个人统计为例。
如果预测的是离散值(discretevalue),例如比赛结果赢或输,此类学习任务称为分类(classification)。
如果预测的是连续值(continuousvalue),例如詹姆斯效率65.1,70.3等等,此类学习任务称为回归(regression)。
无监督学习(unsupervisedlearning)是找出输入数据的模式。比如,它可以根据电影的各种特征做聚类,用这种方法收集数据为电影推荐系统提供标签。此外无监督学习还可以降低数据的维度,它可以帮助我们更好的理解数据。
在无监督学习中,数据=(特征,)。
除了根据詹姆斯个人统计来预测骑士队输赢或者个人效率值外,我们还可以对该数据做聚类(clustering),即将训练集中的数据分成若干组,每组成为一个簇(cluster)。
假设聚类方法将数据聚成二个簇A和B,如下图
后来发现簇A代表赢,簇B代表输。聚类的用处就是可以找到一个潜在的原因来解释为什么样例1和3可以赢球。难道真的是只要詹姆斯三双就可以赢球?
注:下面对降维的理解不是那么严谨,只为了让小白对降维大概有个概念。
詹姆斯完整统计数据还有抢断、盖帽和犯规,但这些对预测比赛输赢、效率值都没什么用,因此可以通过降维的方法将其去除。
1.4
性能度量
回归和分类任务中最常见的误差函数以及一些有用的性能度量如下。
回归任务的误差函数估量在数据集D上模型的连续型预测值h(x)与连续型真实值y的距离,h(x)和y可以取任意实数。误差函数是一个非负实值函数,通常使用ED[h]来表示。图表展示如下。
分类任务的误差函数估量在数据集D上模型的离散型预测值h(x)与离散型真实值y的不一致程度,惯例是y和h(x)取±1,比如正类取1负类取-1。图表展示如下。
除上述损失函数之外,分类任务还有很多其他有用的性能度量。
错误率:分类错误的样本数占样本总数的比例称为错误率(errorrate),相应的分类正确的样本数占样本总数的比例称为精度(accuracy)。在10个样本中有2个样本分类错误,则错误率为20%,而精度为80%。
查准率和查全率:错误率和精度虽然常用,但是不能满足所有任务需求。假定用训练好的模型预测骑士赢球,显然,错误率衡量了多少比赛实际是赢球但预测成输球。但是若我们关心的是“预测出的比赛中有多少是赢球”,或“赢球的比赛中有多少被预测出了”,那么错误率这个单一指标显然就不够用了,这时需要引进更为细分的性能度量,即查准率(precision)和查全率(recall)。
其他概念比如混淆矩阵、ROC、AUC我们再下帖的实例用到时再细讲。
1.5
模型
有监督模型如下图所示:
无监督模型包括各种聚类分析(KMeans,DBSCAN)、主成分分析(PCA)、独立成分分析(ICA)、隐含狄利克雷分配(LDA)等等。
如要了解更多机器学习的细节,请参考本帖次条的〖机器学习帖子汇总〗,里面是我写的所有关于「有监督学习」的内容。
Sklearn和之前讨论的NumPy,SciPy,Pandas,Matplotlib相似,就是一个处理特殊任务的包,Sklearn就是处理机器学习(有监督学习和无监督学习)的包,更精确的说,它里面有六个任务模块和一个数据引入模块:
本节就来看看Sklearn里数据格式和自带数据集。
2.1
数据格式
在Sklean里,模型能即用的数据有两种形式:
上述数据在机器学习中通常用符号X表示,是模型自变量。它的大小=[样本数,特征数],图下图所示。该房屋数据有21000条包括平方英尺,卧室数,楼层,日期,翻新年份等等21栏。该数据形状为[21000,21]
有监督学习除了需要特征X还需要标签y,而y通常就是Numpy一维数组,无监督学习没有y。
2.2
自带数据集
Sklearn里面有很多自带数据集供用户使用。
数据集包括150条鸢尾花的四个特征(萼片长/宽和花瓣长/宽)和三个类别。在盘Seaborn时是从csv文件读取的,本帖从Sklearn里面的datasets模块中引入,代码如下:
fromsklearn.datasetsimportload_irisiris=load_iris()数据是以「字典」格式存储的,看看iris的键有哪些。
dict_keys(['data','target','target_names','DESCR','feature_names','filename'])键里面的名称解释如下:
具体感受一下iris数据中特征的大小、名称和前五个示例。
(150,4)['sepallength(cm)','sepalwidth(cm)','petallength(cm)','petalwidth(cm)']array([[5.1,3.5,1.4,0.2],[4.9,3.,1.4,0.2],[4.7,3.2,1.3,0.2],[4.6,3.1,1.5,0.2],[5.,3.6,1.4,0.2]])150个样本,4个特征,没毛病!再感受一下标签的大小、名称和全部示例。
(150,)['setosa''versicolor''virginica']array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2])150个标签,3类别(分别用0,1,2数值来代表setosa,versicolor,virginica)。
用Pandas的DataFrame(将X和y合并)和Seaborn的pairplot(看每个特征之间的关系)来用表格和图来展示一下数据集的内容。
PandasDataFrame
SeabornPairplot
看完鸢尾花的iris数据展示后,现在来看看Sklearn三种引入数据形式。
上面这个星号*是什么意思,指的是具体文件名,敲完
点击键盘上的
Load一个数字小数据集digits
dict_keys(['data','target','target_names','images','DESCR'])Fetch一个加州房屋大数据集california_housing
dict_keys(['data','target','feature_names','DESCR'])Make一个高斯分位数数据集gaussian_quantile?
Sklearn里万物皆估计器。估计器是个非常抽象的叫法,可把它不严谨的当成一个模型(用来回归、分类、聚类、降维),或当成一套流程(预处理、网格最终)。
本节三大API其实都是估计器:
这三句看似废话,其实蕴藏了很多内容。其实我对第1点这个估计器的起名不太满意,我觉得应该叫拟合器(fitter)-具有拟合功能的估计器。看完这一节你就会明白「拟合器」这种叫法更合理。
3.1
估计器
定义:任何可以基于数据集对一些参数进行估计的对象都被称为估计器。
两个核心点:1.需要输入数据,2.可以估计参数。估计器首先被创建,然后被拟合。
创建估计器:需要设置一组超参数,比如
在创建好的估计器model可以直接访问这些超参数,用.符号。
但model中有很多超参数,你不可能一开始都知道要设置什么值,没设置的用Sklearn会给个合理的默认值,因此新手不用担心。
拟合估计器:需要训练集。在有监督学习中的代码范式为
model.fit(X_train,y_train)
在无监督学习中的代码范式为
model.fit(X_train)
拟合之后可以访问model里学到的参数,比如线性回归里的特征前的系数coef_,或K均值里聚类标签labels_。
说了这么多抽象的东西,现在展示有监督学习的「线性回归」和无监督学习的「K均值」的具体例子。
首先从sklearn下的linear_model中引入LinearRegression,再创建估计器起名model,设置超参数normalize为True,指的在每个特征值上做标准化,这样会加速数值运算。
创建完后的估计器会显示所有的超参数,比如我们设置好的normalize=True,其他没设置的都是去默认值,比如n_jobs=None是只用一个核,你可以将其设为2就是两核并行,甚至设为-1就是电脑里所有核并行。
自己创建一个简单数据集(没有噪声完全线性)只为了讲解估计器里面的特征。
还记得Sklearn里模型要求特征X是个两维变量么(样本数×特征数)?但在本例中X是一维,因为我们用np.newaxis加一个维度,它做的事情就是把[1,2,3]转成[[1],[2],[3]]。再把X和y丢进fit()函数来拟合线性模型的参数。
拟合完后的估计器和创建完的样子看起来一样,但是已经用「model.param_」可以访问到学好的参数了,展示如下。
print(model.coef_)print(model.intercept_)[2.]1.0斜率为2,截距为1,没毛病。和访问超参数时不一样,注意访问参数要加一个下划线_。
首先从sklearn下的cluster中引入KMeans,再创建估计器起名model,设置超参数n_cluster为3(为了展示方便而我们知道用的iris数据集有3类,实际上应该选不同数量的n_cluster,根据elbow图来决定,下帖细讲)。
再者,iris数据里是有标签y的,我们假装没有y才能无监督的聚类啊,要不然应该做有监督的分类的。
创建完后的估计器会显示所有的超参数,比如我们设置好的n_cluster=3,其他没设置的都是去默认值,比如max_iter=300是最多迭代次数为300,算法不收敛也停了。
还记得iris里的特征有四个吗(萼片长、萼片宽、花瓣长、花瓣宽)?四维特征很难可视化,因此我们只取两个特征(萼片长、萼片宽)来做聚类并且可视化结果。注意下面代码X=iris.data[:,0:2]。
有点乱,解释一下KMeans模型这几个参数:
需要强调的是真实标签iris.label和聚类标签model.labels_看起来差的很远。类别0都一致,但是类别1和2弄反了,这是因为在KMeans算法里标注的类别索引和真实类别索引不一样(我现在也没找到什么方法能够让它们一致)。
虽然上面以有监督学习的LinearRegression和无监督学习的KMeans举例,但实际上你可以将它们替换成其他别的模型,比如有监督学习的LogisticRegression和无监督学习的DBSCAN。它们都是「估计器」,因此都有fit()方法。使用它们的通用伪代码如下:
#无监督学习fromsklearn.xxximportSomeModel#xxx可以是cluster或decomposition等model=SomeModel(hyperparameter)model.fit(X)3.2
预测器
定义:预测器在估计器上做了一个延展,延展出预测的功能。
两个核心点:1.基于学到的参数预测,2.预测有很多指标。最常见的就是predict()函数:
因为要做预测,首先将数据分成80:20的训练集(X_train,y_train)和测试集(X_test,y_test),在用从训练集上拟合fit()的模型在测试集上预测predict()。
fromsklearn.model_selectionimporttrain_test_splitX_train,X_test,y_train,y_test=train_test_split(iris['data'],iris['target'],test_size=0.2)print('ThesizeofX_trainis',X_train.shape)print('Thesizeofy_trainis',y_train.shape)print('ThesizeofX_testis',X_test.shape)print('Thesizeofy_testis',y_test.shape)ThesizeofX_trainis(120,4)Thesizeofy_trainis(120,)ThesizeofX_testis(30,4)Thesizeofy_testis(30,)让我们来看个有监督学习的「对率回归」和继续上节无监督学习的「K均值」的例子。
首先从sklearn下的linear_model中引入LogisticRegression,再创建估计器起名model,设置超参数mutli_class为multinomial因为有三种鸢尾花,是个多分类问题。
接着再训练集上拟合参数,这时估计器model里面已经可以访问这些参数了。
predict&predict_proba
对于分类问题,我们不仅想知道预测的类别是什么,有时还想知道预测该类别的信心如何。前者用predict(),后者用predict_proba()。
解释一下p_pred-测试集里有30个数据,鸢尾花有3类,因此predict_proba()生成一个30×3的数组,每行的概率加起来为1。
为了验证我们的理解,我们看Sklearn是不是把「每行中最大概率值对应的那一类」作为预测结果。
是的!前三行Class1Prob最大,预测是第一类;第四行Class2Prob最大,预测是第二类;第四行Class3Prob最大,预测是第三类。
score&decision_function
预测器里还有额外的两个函数可以使用。在分类问题中
为了验证我们的理解,我们看Sklearn是不是把「每行中最高得分值对应的那一类」作为预测结果。
是的!前两行Class3Score最大,预测是第三类;后三行Class1Score最大,预测是第一类。
继续上一节的KMeans模型,首先用fit()训练。
再用predict()在测试集上预测出类别inx_pred,和真实标签y_test比对。再次强调,inx_pred和y_test给三个类别的索引定义是不同的。
最后画出两幅图(都是在测试集上),左图是根据聚类预测的标签画出散点图,而右图是根据真实标签画出散点图,对比两幅图看很像,聚类的效果也不错。
KMeans模型里也有score()函数,输出是值是它要优化的目标函数的对数。
-9.662259042197803小节估计器都有fit()方法,预测器都有predict()和score()方法,言外之意不是每个预测器都有predict_proba()和decision_function()方法,这个在用的时候查查官方文档就清楚了(比如RandomForestClassifier就没有decision_function()方法)。
使用它们的通用伪代码如下:
#无监督学习fromsklearn.xxximportSomeModel#xxx可以是cluster或decomposition等model=SomeModel(hyperparameter)model.fit(X)idx_pred=model.predict(X_new)s=model.score(X_new)3.3
转换器
定义:转换器也是一种估计器,两者都带拟合功能,但估计器做完拟合来预测,而转换器做完拟合来转换。
核心点:估计器里fit+predict,转换器里fit+transform。
本节介绍两大类转换器
LabelEncoder&OrdinalEncoder
LabelEncoder和OrdinalEncoder都可以将字符转成数字,但是
首先给出要编码的列表enc和要解码的列表dec。
从sklearn下的preprocessing中引入LabelEncoder,再创建转换器起名LE,不需要设置任何超参数。
fromsklearn.preprocessingimportLabelEncoderLE=LabelEncoder()print(LE.fit(enc))print(LE.classes_)print(LE.transform(dec))LabelEncoder()['draw''lose''win'][002]上面结果解释如下
除了LabelEncoder能编码,OrdinalEncoder也可以。首先从sklearn下的preprocessing中引入OrdinalEncoder,再创建转换器起名OE,不需要设置任何超参数。下面结果和上面类似,就不再多解释了。
fromsklearn.preprocessingimportOrdinalEncoderOE=OrdinalEncoder()enc_DF=pd.DataFrame(enc)dec_DF=pd.DataFrame(dec)print(OE.fit(enc_DF))print(OE.categories_)print(OE.transform(dec_DF))OrdinalEncoder(categories='auto',dtype=
要解决这个问题,一个常见的方法是给每个分类创建一个二元属性,即独热编码(one-hotencoding)。如何用它看下段。
OneHotEncoder
独热编码其实就是把一个整数用向量的形式表现。下图就是对数字0-9做独热编码。
转换器OneHotEncoder可以接受两种类型的输入:
一.用LabelEncoder编码好的一维数组(元素为整数),重塑(用reshape(-1,1))成二维数组作为OneHotEncoder输入。
fromsklearn.preprocessingimportOneHotEncoderOHE=OneHotEncoder()num=LE.fit_transform(enc)print(num)OHE_y=OHE.fit_transform(num.reshape(-1,1))OHE_y[2012]<4x3sparsematrixoftype'
想看该矩阵里具体内容,用toarray()函数。
OHE_y.toarray()array([[0.,0.,1.],[1.,0.,0.],[0.,1.,0.],[0.,0.,1.]])二.用DataFrame作为OneHotEncoder输入。
OHE=OneHotEncoder()OHE.fit_transform(enc_DF).toarray()array([[0.,0.,1.],[1.,0.,0.],[0.,1.,0.],[0.,0.,1.]])和上面结果类似,不解释了。
数据要做的最重要的转换之一是特征缩放(featurescaling)。当输入的数值的量刚不同时,机器学习算法的性能都不会好。
具体来说,对于某个特征,我们有两种方法:
MinMaxScaler
整套转换器「先创建再fit在transform」的流程应该很清楚了。自己读下面代码看看是不是秒懂。唯一需要注意的就是输入X要求是两维。
牢记转换器「先创建再fit在transform」的流程就行了。
fromsklearn.preprocessingimportStandardScalerX_scale=StandardScaler().fit_transform(X.reshape(-1,1))X_scalearray([[-0.47424487],[-0.46069502],[-0.44714517],[-0.43359531],[-0.42004546],[2.23572584]])警示:fit()函数只能作用在训练集上,千万不要作用在测试集上,要不然你就犯了数据窥探的错误了!拿标准化举例,用训练集fit出来的均值和标准差参数,来对测试集做标准化。
Sklearn里核心API接口是估计器,那高级API接口就是元估计器(meta-estimator),即由很多基估计器(baseestimator)组合成的估计器。
meta_model(base_model)
本节讨论五大元估计器,分别带集成功能的ensemble,多分类和多标签的multiclass,多输出的multioutput,选择模型的model_selection,和流水线的pipeline。
在下面五节,我们会用的鸢尾花数据iris和数字数据digits,还有一些自己创建的数据。
4.1
Ensemble估计器
最常用的Ensemble估计器排列如下:
我们用鸢尾花数据iris,拿
来举例。首先将数据分成80:20的训练集和测试集,并引入metrics来计算各种性能指标。
RandomForestClassifier通过控制n_estimators超参数来决定基估计器的个数,本例是4棵决策树(森林由树组成);此外每棵树的最大树深为5(max_depth=5)。
估计器有fit(),元估计器当然也有fit()。在估计器那一套又可以照搬到元估计器(起名RF)上了。看看RF里包含的估计器个数和其本身。
拟合RF完再做预测,用metrics里面的accuracy_score来计算准确率。训练准确率98.33%,测试准确率100%。
和随机森林由同质分类器「决策树」不同,投票分类器由若干个异质分类器组成。下例用VotingClassifier建立个含有对率回归(LR)、随机森林(RF)和高斯朴素贝叶斯(GNB)三个分类器的集成模型。
RandomForestClassifier的基分类器只能是决策树,因此只用通过控制n_estimators超参数来决定树的个数,而VotingClassifier的基分类器要实实在在的输入其本身。
看看Ensemble里包含的估计器个数和其本身。
比如元估计器和它三个组成元素的表现。还是集成后的Ensemble表现最好。
LR-Accuracy(Train):0.975RF-Accuracy(Train):0.9833GNB-Accuracy(Train):0.95Ensemble-Accuracy(Train):0.9833LR-Accuracy(Test):1RF-Accuracy(Test):1GNB-Accuracy(Test):1Ensemble-Accuracy(Test):14.2
Multiclass估计器
sklearn.multiclass可以处理多类别(multi-class)的多标签(multi-label)的分类问题。
从小节4.2到4.4,我们都会使用数字数据集digits。首先将数据分成80:20的训练集和测试集。
dict_keys(['data','target','target_names','images','DESCR'])X_train,X_test,y_train,y_test=train_test_split(digits['data'],digits['target'],test_size=0.2)print('ThesizeofX_trainis',X_train.shape)print('Thesizeofy_trainis',y_train.shape)print('ThesizeofX_testis',X_test.shape)print('Thesizeofy_testis',y_test.shape)ThesizeofX_trainis(1437,64)Thesizeofy_trainis(1437,)ThesizeofX_testis(360,64)Thesizeofy_testis(360,)训练集和测试集分别有1437和360张图像。每张照片是包含8×8的像素,将其打平(flatten)把2维的8×8重塑成1维的64。
看看训练集中前100张图片和对应的标签(左下角蓝色小字)。像素很低(为了我们跑模型快些),但基本上还是能看清。
手写数字有0-9十类,但手头上只有两分类估计器(比如像支撑向量机)怎么用呢?我们可以采取下面三种常见策略:
OneVsOneClassifier
考虑一个具体天气多分类问题,天气可以是晴天、阴天和雨天,在OvO中,三个分类器为f1,f2和f3。
结果如下
根据多数原则得到的结合预测为●,如下图所示。
回到数字分类问题上,代码如下:
10类45个OvO分类器,没错,10*9/2=45。
训练集分类全对,测试集准确率98%。
OneVsRestClassifier
在OvA中,把数据分成“某个”和“其他”
三分类分解成三个二分类,对应的分类器为f1,f2和f3。
三个分类器都预测了●,根据多数原则得到的预测是●。
10类45个OvA分类器,没错。
训练集准确率几乎100%,测试集准确率96%。
到目前为止,所有的样例都总是被分配到仅一个类。有些情况下,你也许想让分类器给一个样例输出多个类别。在无人驾驶的应用中,在下图识别出有车和指示牌,没有交通灯和人。
我们不打算深入物体识别。先看一个简单点的例子,仅仅是为了阐明「多标签分类」的原理。在手写数字的例子上,我们特意为每个数字设计了多标签:
再建立多标签y_train_multilabel,代码如下(OneVsRestClassifier也可以用来做多标签分类):
[[TrueTrue][FalseFalse][FalseFalse]...[FalseFalse][FalseFalse][FalseFalse]]看下图训练集第1和2个图片是数字4和5,对应上面两标签当然是
训练模型,只不过这时用的是y_train_multilabel。
有两个估计器,每个对应一个标签。
展示一下测试集上100张图片。
第一张图片是数字2,它是偶数(标签1为true),小于等于4(标签2为true)。
print(y_test[:1])print(ova_ml.predict(X_test[:1,:]))[2][[11]]4.3
Multioutput估计器
sklearn.multioutput可以处理多输出(multi-output)的分类问题。
多输出分类是多标签分类的泛化,在这里每一个标签可以是多类别(大于两个类别)的。一个例子就是预测图片每一个像素(标签)的像素值是多少(从0到255的256个类别)。
Multioutput估计器有两个:
MultiOutputClassifier
首先引入MultiOutputClassifier和RandomForestClassifier。你看,这两个都是元估计器,因此在Sklearn里面估计器可以随意组合。
fromsklearn.multioutputimportMultiOutputClassifierfromsklearn.ensembleimportRandomForestClassifier在手写数字的例子上,我们也为特意每个数字设计了多标签而且每个标签的类别都大于二。
代码如下:
用含有100棵决策树的随机森林来解决这个多输入分类问题。
看看这个模型在测试集前五张照片上的预测。
array([[0,2],[0,2],[0,0],[2,9],[1,5]])这个ndarray第一列是标签1的类别,第二列是标签2的类别。预测结果是这五张照片分别显示数字2,2,0,9,5(标签2),它们前三个数2,2,0都小于等于4(标签1第一类),第四个数9大于等于7(标签1第二类),而第五个数5在4和7之间(标签1第三类)。
再看看真实标签。
array([[0,2],[0,2],[0,0],[2,9],[1,5]])相当好!
4.4
ModelSelection估计器
模型选择(ModelSelction)在机器学习非常重要,它主要用于评估模型表现,常见的ModelSelection估计器有以下几个:
接下来我们来看这两个调参的估计器,网格追踪和随机追踪。
网格追踪:参数1在[1,10,100,1000]中取值,参数2在[0.01,0.1,110]中取值,注意并不是等间距取值。模型在所有16个组合跑,选取一对对应最小交叉验证误差的参数。
随机追踪:根据指定分布随机搜索,可以选择独立于参数个数,比如log(参数1)服从0到3的均匀分布,log(参数2)服从-2到1的均匀分布。此外,会设定一个预算参数。
原理讲清楚了,看代码吧。
解释一下代码:
解释一下运行结果:
4.5
Pipeline估计器
Pipeline估计器又叫流水线,把各种估计器串联(Pipeline)或并联(FeatureUnion)的方式组成一条龙服务。用好了它真的能大大提高效率。
Pipeline
Pipeline将若干个估计器按顺序连在一起,比如
特征提取->降维->拟合->预测
在整个Pipeline中,它的属性永远和最后一个估计器属性一样
下面用一个简单例子来说明如果用Pipeline来做「先填补缺失值-再标准化」这两步的。先生成含缺失值NaN的数据X。
首先引入Pipeline,再引入
第4-7行创建了流水线,范式非常简单,就在Pipeline()里一个输入「含名称的估计器的列表」。SimpleImputer起名叫impute,MinMaxScaler起名叫normalize。
由于最后一个估计器是转换器,因此pipe也是个转换器。写好了就可以那它来做「先填补缺失值-再标准化」的重复工作了。
看看运行结果,值都被填满了,而且两列也被标准化了。
来验证上面流水线的参数,我们可以按顺序来运行这两个转换器,结果是一样的。
FeatureUnion
如果我们想在一个节点同时运行几个估计器,我们可用FeatureUnion。下例首先建立一个DataFrame,
我们现在按下列步骤来清洗数据。
上面两步是平行进行的。
首先我们自己定义一个从DataFrame里面获取每列的类,起名叫DataFrameSelector。
接下来建立一个流水线full_pipe,它并联着两个流水线
下面代码非常漂亮。
将结果打印出来,齐活!
[[1.0.120.1.0.0.1.][0.777777780.721.0.0.1.0.][0.555555560.481.0.0.0.1.][0.0.520.0.1.1.0.][0.044444441.0.1.0.1.0.][0.111111110.1.0.0.1.0.][0.088888890.920.1.0.1.0.][0.341666670.520.1.0.1.0.][0.155555560.40.1.0.1.0.]]5总结Sklearn里面设计API遵循五大原则。
所有对象的接口一致且简单,在「估计器」中
在「预测器」中
在「转换器」中
所有估计器里设置的超参数和学到的参数都可以通过实例的变量直接访问来检验其值,区别是超参数的名称最后没有下划线_,而参数的名称最后有下划线_。举例如下:
Sklearn模型接受的数据集的格式只能是「Numpy数组」和「Scipy稀疏矩阵」。超参数的格式只能是「字符」和「数值」。
不接受其他的类!
模块都能重复「连在一起」或「并在一起」使用,比如两种形式流水线(pipeline)
Sklearn给大多超参数提供了合理的默认值,大大降低了建模的难度。
结合本帖讲的总结一套机器学习的初级框架:
确定任务:是「有监督」的分类或回归?还是「无监督」的聚类或降维?确定好后基本就能知道用Sklearn里哪些模型了。
数据预处理:这步最繁琐,要处理缺失值、异常值;要编码分类型变量;要正规化或标准化数值型变量,等等。但是有了Pipeline神器一切变得简单高效。
训练和评估:这步最简单,训练用估计器fit()先拟合,评估用预测器predict()来评估。
选择模型:启动ModelSelection估计器里的GridSearchCV和RandomizedSearchCV,选择得分最高的那组超参数(即模型)。
本帖讲的东西有点抽象,但最核心的东西就是弄懂估计器以及元估计器的原理。剩下的就是1)了解各种模型,2)知道模型中每个参数的含义,3)查阅Sklearn官方文档。非深度的机器学习不像深度学习有那么多调参技巧(tuningtrick),按照上面那套框架足够了。