1。KNN分类算法 由于knn算法涉及到距离的概念,KNN算法需要先进行归一化处理1。1归一化处理scalerfromsklearn。preprocessingimportStandardScalerstandardScalerStandardScaler()standardScaler。fit(Xtrain)XtrainstandardstandardScaler。transform(Xtrain)XteststandardstandardScaler。transform(Xtest) 归一化之后送入模型进行训练fromsklearn。neighborsimportKNeighborsClassifierknnclfKNeighborsClassifier(nneighbors8)knnclassifier。fit(Xtrainstandard,ytrain)ypredictknnclf。predict(Xteststandard)默认的预测指标为分类准确度knnclf。score(Xtest,ytest)1。2网格搜索GridSearchCV 使用网格搜索来确定KNN算法合适的超参数fromsklearn。neighborsimportKNeighborsClassifierknnclfKNeighborsClassifier(nneighbors8)knnclassifier。fit(Xtrainstandard,ytrain)ypredictknnclf。predict(Xteststandard)默认的预测指标为分类准确度knnclf。score(Xtest,ytest)1。3交叉验证GridSearchCV本身就包括了交叉验证,也可自己指定参数cv默认GridSearchCV的KFold平分为3份自己指定交叉验证,查看交叉验证成绩fromsklearn。modelselectionimportcrossvalscore默认为分成3份crossvalscore(knnclf,Xtrain,ytrain,cv5)这里默认的scoring标准为accuracy有许多可选的参数,具体查看官方文档封装成函数,在fit完模型之后,一次性查看多个评价指标的成绩这里选的只是针对分类算法的指标,也可以是针对回归,聚类算法的评价指标defcvscoretraintest(model):numcv5scorelist〔accuracy,f1,neglogloss,rocauc〕forscoreinscorelist:print(score,train:,crossvalscore(model,Xtrain,ytrain,cvnumcv,scoringscore)。mean())print(score,test:,crossvalscore(model,Xtest,ytest,cvnumcv,scoringscore)。mean())2。线性回归2。1简单线性回归fromsklearn。linearmodelimportLinearRegressionlinregLinearRegression()linreg。fit(Xtrain,ytrain)查看截距和系数printlinreg。interceptprintlinreg。coeflinreg。score(Xtest,ytest)ypredictlinreg。predict(Xtest)2。2多元线性回归 在更高维度的空间中的直线,即数据不只有一个维度,而具有多个维度 代码和上面的简单线性回归相同3。梯度下降法 使用梯度下降法之前,需要对数据进行归一化处理 回到顶部3。1随机梯度下降线性回归 SGDregfromsklearn。linearmodelimportSGDRegressorsgdregSGDRegressor(maxiter100)sgdreg。fit(Xtrainstandard,ytrainboston)sgdreg。score(Xteststandard,ytestboston)3。2确定梯度下降计算的准确性 以多元线性回归的目标函数(损失函数)为例 比较使用数学推导式(得出具体解析解)的方法和debug的近似方法的比较编写损失函数defJ(theta,Xb,y):try:returnnp。sum((yXb。dot(theta))2)len(y)except:returnfloat(‘inf‘)编写梯度函数(使用数学推导方式得到的)defdJmath(theta,Xb,y):returnXb。T。dot(Xb。dot(theta)y)2。0len(y)编写梯度函数(用来debug的形式)defdJdebug(theta,Xb,y,epsilon0。01):resnp。empty(len(theta))foriinrange(len(theta)):theta1theta。copy()theta1〔i〕epsilontheta2theta。copy()theta2〔i〕epsilonres〔i〕(J(theta1,Xb,y)J(theta2,Xb,y))(2epsilon)returnres批量梯度下降,寻找最优的thetadefgradientdescent(dJ,Xb,y,initialtheta,eta,niters1e4,epsilon1e8):thetainitialthetaiiter0whileiiterniters:gradientdJ(theta,Xb,y)lastthetathetathetathetaetagradientif(abs(J(theta,Xb,y)J(lasttheta,Xb,y))epsilon):breakiiter1returntheta函数入口参数第一个,要指定dJ函数是什么样的Xbnp。hstack(〔np。ones((len(X),1)),X〕)initialthetanp。zeros(Xb。shape〔1〕)eta0。01使用debug方式thetagradientdescent(dJdebug,Xb,y,initialtheta,eta)使用数学推导方式thetagradientdescent(dJmath,Xb,y,initialtheta,eta)得出的这两个theta应该是相同的4。PCA算法 由于是求方差最大,因此使用的是梯度上升法 PCA算法不能在前处理进行归一化处理,否则将会找不到主成分4。1代码流程对于二维的数据样本来说fromsklearn。decompositionimportPCApcaPCA(ncomponents1)指定需要保留的前n个主成分,不指定为默认保留所有pca。fit(X) 比如,要使用KNN分类算法,先进行数据的降维操作fromsklearn。decompositionimportPCApcaPCA(ncomponents2)这里也可以给一个百分比,代表想要保留的数据的方差占比pca。fit(Xtrain)训练集和测试集需要进行相同降维处理操作Xtrainreductionpca。transform(Xtrain)Xtestreductionpca。transform(Xtest)降维完成后就可以送给模型进行拟合knnclfKNeighborsClassifier()knnclf。fit(Xtrainreduction,ytrain)knnclf。score(Xtestreduction,ytest)4。2降维的维数和精度的取舍 指定的维数,能解释原数据的方差的比例pca。explainedvarianceratio指定保留所有的主成分pcaPCA(ncomponentsXtrain。shape〔1〕)pca。fit(Xtrain)pca。explainedvarianceratio查看降维后特征的维数pca。ncomponents 把数据降维到2维,可以进行scatter的可视化操作4。3PCA数据降噪 先使用pca降维,之后再反向,升维fromsklearn。decompositionimportPCApcaPCA(0。7)pca。fit(X)pca。ncomponentsXreductionpca。transform(X)Xinversedpca。inversetransform(Xreduction)5。多项式回归与模型泛化 多项式回顾需要指定最高的阶数,degree 拟合的将不再是一条直线只有一个特征的样本,进行多项式回归可以拟合出曲线,并且在二维平面图上进行绘制而对于具有多个特征的样本,同样可以进行多项式回归,但是不能可视化拟合出来的曲线5。1多项式回归和Pipelinefromsklearn。preprocessingimportPolynomialFeaturesfromsklearn。linearmodelimportLinearRegressionfromsklearn。preprocessingimportStandardScalerfromsklearn。pipelineimportPipelinepolyregPipeline(〔(poly,PolynomialFeatures(degree2)),(stdscaler,StandardScaler()),(linreg,LinearRegression())〕)polyreg。fit(X,y)ypredictpolyreg。predict(X)对二维数据点可以绘制拟合后的图像plt。scatter(X,y)plt。plot(np。sort(x),ypredict〔np。argsort(x)〕,color‘r‘)plt。show()更常用的是,把pipeline写在函数中defPolynomialRegression(degree):returnPipeline(〔(poly,PolynomialFeatures(degreedegree)),(stdscaler,StandardScaler()),(linreg,LinearRegression())〕)poly2regPolynomialRegression(degree2)poly2reg。fit(X,y)y2predictpoly2reg。predict(X)meansquarederror(y,y2predict)5。2GridSearchCV和Pipeline 明确:GridSearchCV:用于寻找给定模型的最优的参数Pipeline:用于将几个流程整合在一起(PolynomialFeatures()、StandardScaler()、LinearRegression()) 如果非要把上两者写在一起,应该把指定好paramgrid参数的gridsearch作为成员,传递给Pipeline5。3模型泛化之岭回归(Ridge) 首先明确:模型泛化是为了解决模型过拟合的问题岭回归是模型正则化的一种处理方式,也称为L2正则化岭回归是线性回归的一种正则化处理后的模型(作为pipeline的成员使用)fromsklearn。linearmodelimportRidgefromsklearn。preprocessingimportPolynomialFeaturesfromsklearn。preprocessingimportStandardScalerfromsklearn。pipelineimportPipelinedefRidgeRegression(degree,alpha):returnPipeline(〔(poly,PolynomialFeatures(degreedegree)),(stdscaler,StandardScaler()),(ridgereg,Ridge(alphaalpha))〕)ridgeregRidgeRegression(degree20,alpha0。0001)ridgereg。fit(Xtrain,ytrain)ypredictridgereg。predict(Xtest)meansquarederror(ytest,ypredict) 代码中: alpha为L2正则项前面的系数,代表的含义与LASSO回归相同alpha越小,越倾向于选择复杂模型alpha越大,越倾向于选择简单模型 Ridge回归、LASSO回归的区别Ridge:更倾向于保持为曲线LASSO:更倾向于变为直线(即趋向于使得部分theta变成0,因此有特征选择的作用)5。4模型泛化之LASSO回归岭回归是模型正则化的一种处理方式,也称为L1正则化岭回归是线性回归的一种正则化处理后的模型(作为pipeline的成员使用)fromsklearn。linearmodelimportLassofromsklearn。preprocessingimportPolynomialFeaturesfromsklearn。preprocessingimportStandardScalerfromsklearn。pipelineimportPipelinedefLassoRegression(degree,alpha):returnPipeline(〔(poly,PolynomialFeatures(degreedegree)),(stdscaler,StandardScaler()),(lassoreg,Lasso(alphaalpha))〕)lassoregLassoRegression(3,0。01)lassoreg。fit(Xtrain,ytrain)ypredictlassoreg。predict(Xtest)meansquarederror(ytest,ypredict)6。逻辑回归 将样本特征与样本发生的概率联系起来。既可看做回归算法,也可分类算法通常作为二分类算法6。1绘制决策边界不规则决策边界绘制方法defplotdecisionboundary(model,axis):x0,x1np。meshgrid(np。linspace(axis〔0〕,axis〔1〕,int((axis〔1〕axis〔0〕)100))。reshape(1,1),np。linspace(axis〔2〕,axis〔3〕,int((axis〔3〕axis〔2〕)100))。reshape(1,1))Xnewnp。c〔x0。ravel(),x1。ravel()〕ypredictmodel。predict(Xnew)zzypredict。reshape(x0。shape)frommatplotlib。colorsimportListedColormapcustomcmapListedColormap(〔‘EF9A9A‘,‘FFF59D‘,‘90CAF9‘〕)plt。contourf(x0,x1,zz,linewidth5,cmapcustomcmap)此处为线性逻辑回归fromsklearn。linearmodelimportLogisticRegressionlogregLogisticRegression()logreg。fit(Xtrain,ytrain)logreg。score(Xtest,ytest)绘制决策边界plotdecisionboundary(logreg,axis〔4,7。5,1。5,4。5〕)plt。scatter(X〔y0,0〕,X〔y0,1〕,color‘r‘)plt。scatter(X〔y1,0〕,X〔y1,1〕,color‘blue‘)plt。show()6。2多项式逻辑回归 同样,类似于多项式回归,需要使用Pipeline构造多项式特征项fromsklearn。pipelineimportPipelinefromsklearn。preprocessingimportPolynomialFeaturesfromsklearn。preprocessingimportStandardScalerfromsklearn。linearmodelimportLogisticRegressiondefPolynomialLogisticRegression(degree):returnPipeline(〔(‘poly‘,PolynomialFeatures(degreedegree)),(‘stdscaler‘,StandardScaler()),(‘logreg‘,LogisticRegression())〕)polylogregPolynomialLogisticRegression(degree2)polylogreg。fit(X,y)polylogreg。score(X,y) 如果有需要,可以绘制出决策边界plotdecisionboundary(polylogreg,axis〔4,4,4,4〕)plt。scatter(X〔y0,0〕,X〔y0,1〕)plt。scatter(X〔y1,0〕,X〔y1,1〕)plt。show()6。3逻辑回归中的正则化项和惩罚系数C 公式为: CJ()L1 CJ()L2 上式中:C越大,L1、L2的作用越弱,模型越倾向复杂C越小,相对L1、L2作用越强,J()作用越弱,模型越倾向简单defPolynomialLogisticRegression(degree,C,penalty‘l2‘):returnPipeline(〔(‘poly‘,PolynomialFeatures(degreedegree)),(‘stdscaler‘,StandardScaler()),(‘logreg‘,LogisticRegression(CC,penaltypenalty))逻辑回归模型,默认为penalty‘l2‘〕)6。4OVR和OVO 将只适用于二分类的算法,改造为适用于多分类问题 scikit封装了OvOOvR这两个类,方便其他二分类算法,使用这两个类实现多分类 例子中:logreg是已经创建好的逻辑回归二分类器fromsklearn。multiclassimportOneVsRestClassifierovrOneVsRestClassifier(logreg)ovr。fit(Xtrain,ytrain)ovr。score(Xtest,ytest)fromsklearn。multiclassimportOneVsOneClassifierovoOneVsOneClassifier(logreg)ovo。fit(Xtrain,ytrain)ovo。score(Xtest,ytest)7。支撑向量机SVM 注意由于涉及到距离的概念,因此,在SVM拟合之前,必须先进行数据标准化 支撑向量机要满足的优化目标是: 使最优决策边界到与两个类别的最近的样本的距离最远 即,使得margin最大化 分为:HardMarginSVMSoftMarginSVM7。1SVM的正则化 为了改善SVM模型的泛化能力,需要进行正则化处理,同样有L1、L2正则化 正则化即弱化限定条件,使得某些样本可以不再Margin区域内 惩罚系数C是乘在正则项前面的 min12w2Ci1mi,L1正则项min12w2Ci1mi,L1正则项 min12w2Ci1m2i,L2正则项min12w2Ci1mi2,L2正则项 变化规律:C越大,容错空间越小,越偏向于HardMarginC越小,容错空间越大,越偏向于SoftMargin7。2线性SVMfromsklearn。preprocessingimportStandardScalerstandardScalerStandardScaler()standardScaler。fit(X)XstandardstandardScaler。transform(X)fromsklearn。svmimportLinearSVCsvcLinearSVC(C1e9)svc。fit(Xstandard,y) 简洁起见,可以用Pipeline包装起来fromsklearn。preprocessingimportStandardScalerfromsklearn。svmimportLinearSVCfromsklearn。pipelineimportPipelinedefLinearsvc(C1。0):returnPipeline(〔(stdscaler,StandardScaler()),(linearSVC,LinearSVC(CC))〕)linearsvcLinearsvc(C1e5)linearsvc。fit(X,y)7。3多项式特征SVM 明确:使用多项式核函数的目的都是将数据升维,使得原本线性不可分的数据变得线性可分 在SVM中使用多项式特征有两种方式使用线性SVM,通过pipeline将poly、std、linearsvc三个连接起来使用多项式核函数SVM,则Pipeline只用包装std、kernelSVC两个类7。3。1传统Pipeline多项式SVM传统上使用多项式特征的SVMfromsklearn。preprocessingimportPolynomialFeatures,StandardScalerfromsklearn。svmimportLinearSVCfromsklearn。pipelineimportPipelinedefPolynomialSVC(degree,C1。0):returnPipeline(〔(ploy,PolynomialFeatures(degreedegree)),(stdstandard,StandardScaler()),(linearSVC,LinearSVC(CC))〕)polysvcPolynomialSVC(degree3)polysvc。fit(X,y)7。3。2多项式核函数SVM使用多项式核函数的SVMfromsklearn。svmimportSVCdefPolynomialKernelSVC(degree,C1。0):returnPipeline(〔(stdstandard,StandardScaler()),(kernelSVC,SVC(kernel‘poly‘,degreedegree,CC))〕)polykernelsvcPolynomialKernelSVC(degree3)polykernelsvc。fit(X,y)7。3。3高斯核SVM(RBF) 将原本是mnmn的数据变为mmmmfromsklearn。preprocessingimportStandardScalerfromsklearn。svmimportSVCfromsklearn。pipelineimportPipelinedefRBFkernelSVC(gamma1。0):returnPipeline(〔(stdstandard,StandardScaler()),(svc,SVC(kernelrbf,gammagamma))〕)svcRBFkernelSVC(gamma1。0)svc。fit(X,y) 超参数gamma规律:gamma越大,高斯核越窄,头部越尖gamma越小,高斯核越宽,头部越平缓,图形叉得越开 若gamma太大,会造成过拟合 若gamma太小,会造成欠拟合,决策边界变为直线7。4使用SVM解决回归问题 指定margin区域垂直方向上的距离epsilon 通用可以分为线性SVR和多项式SVRfromsklearn。preprocessingimportStandardScalerfromsklearn。svmimportLinearSVRfromsklearn。svmimportSVRfromsklearn。pipelineimportPipelinedefStandardLinearSVR(epsilon0。1):returnPipeline(〔(stdscaler,StandardScaler()),(linearSVR,LinearSVR(epsilonepsilon))〕)svrStandardLinearSVR()svr。fit(Xtrain,ytrain)svr。score(Xtest,ytest)可以使用crossvalscore来获得交叉验证的成绩,成绩更加准确8。决策树 非参数学习算法、天然可解决多分类问题、可解决回归问题(取叶子结点的平均值)、非常容易产生过拟合 可以考虑使用网格搜索来寻找最优的超参数 划分的依据有基于信息熵、基于基尼系数(scikit默认用gini,两者没有特别优劣之分) ID3、C4。5都是使用entropy评判方式 CART(ClassificationandRegressionTree)使用的是gini评判方式 常用超参数:maxdepthminsamplessplit(设置最小的可供继续划分的样本数量)minsamplesleaf(指定叶子结点最小的包含样本的数量)maxleafnodes(指定,最多能生长出来的叶子结点的数量)8。1分类fromsklearn。treeimportDecisionTreeClassifierdtclfDecisionTreeClassifier(maxdepth2,criteriongini)dtclfDecisionTreeClassifier(maxdepth2,criterionentropy)dtclf。fit(X,y)8。2回归fromsklearn。treeimportDecisionTreeRegressordtregDecisionTreeRegressor()dtreg。fit(Xtrain,ytrain)dtreg。score(Xtest,ytest)计算的是R2值9。集成学习和随机森林9。1HardVotingClassifier 把几种分类模型包装在一起,根据每种模型的投票结果来得出最终预测类别 可以先使用网格搜索把每种模型的参数调至最优,再来Votingfromsklearn。ensembleimportVotingClassifierfromsklearn。linearmodelimportLogisticRegressionfromsklearn。svmimportSVCfromsklearn。treeimportDecisionTreeClassifiervotingclfVotingClassifier(estimators〔(logclf,LogisticRegression()),(svmclf,SVC()),(dtclf,DecisionTreeClassifier())〕,voting‘hard‘)votingclf。fit(Xtrain,ytrain)votingclf。score(Xtest,ytest)9。2SoftVotingClassifier 更合理的投票应该考虑每种模型的权重,即考虑每种模型对自己分类结果的有把握程度 所以,每种模型都应该能估计结果的概率逻辑回归KNN决策树(叶子结点一般不止含有一类数据,因此可以有概率)SVM中的SVC(可指定probability参数为True)softvotingclfVotingClassifier(estimators〔(logclf,LogisticRegression()),(svmclf,SVC(probabilityTrue)),(dtclf,DecisionTreeClassifier(randomstate666))〕,voting‘soft‘)softvotingclf。fit(Xtrain,ytrain)softvotingclf。score(Xtest,ytest)9。3Bagging(放回取样) (1)Bagging(放回取样)和Pasting(不放回取样),由参数bootstrap来指定True:放回取样False:不放回取样 (2)这类集成学习方法需要指定一个baseestimator (3)放回取样,会存在oob(outofbag)的样本数据,比例约37,正好作为测试集 obbscoreTrueFalse,是否使用oob作为测试集 (4)产生差异化的方式:只针对特征进行随机采样:randomsubspace既针对样本,又针对特征随机采样:randompatchesrandomsubspacesclfBaggingClassifier(DecisionTreeClassifier(),nestimators500,maxsamples500,bootstrapTrue,oobscoreTrue,njobs1,maxfeatures1,bootstrapfeaturesTrue)randomsubspacesclf。fit(X,y)randomsubspacesclf。oobscorerandompatchesclfBaggingClassifier(DecisionTreeClassifier(),nestimators500,maxsamples100,bootstrapTrue,oobscoreTrue,njobs1,maxfeatures1,bootstrapfeaturesTrue)randompatchesclf。fit(X,y)randompatchesclf。oobscore 参数解释:maxsamples:如果和样本总数一致,则不进行样本随机采样 maxfeatures:指定随机采样特征的个数(应小于样本维数) bootstrapfeatures:指定是否进行随机特征采样 oobscore:指定是都用oob样本来评分 bootstrap:指定是否进行放回取样 9。4随机森林和ExtraTree9。4。1随机森林 随机森林是指定了BaseEstimator为DecisionTree的Bagging集成学习模型 已经被scikit封装好,可以直接使用fromsklearn。ensembleimportRandomForestClassifierrfclfRandomForestClassifier(nestimators500,randomstate666,oobscoreTrue,njobs1)rfclf。fit(X,y)rfclf。oobscore因为随机森林是基于决策树的,因此,决策树的相关参数这里都可以指定修改rfclf2RandomForestClassifier(nestimators500,randomstate666,maxleafnodes16,oobscoreTrue,njobs1)rfclf2。fit(X,y)rfclf。oobscore9。4。2ExtraTree BaseEstimator为DecisionTree的Bagging集成学习模型 特点:决策树在结点划分上,使用随机的特征和阈值 提供了额外的随机性,可以抑制过拟合,但会增大Bias(偏差) 具有更快的训练速度fromsklearn。ensembleimportExtraTreesRegressoretclfExtraTreesClassifier(nestimators500,bootstrapTrue,oobscoreTrue,randomstate666)etclf。fit(X,y)etclf。oobscore9。5AdaBoosting 每个子模型模型都在尝试增强(boost)整体的效果,通过不断的模型迭代,更新样本点的权重 AdaBoosting没有oob的样本,因此需要进行traintestsplit 需要指定BaseEstimatorfromsklearn。ensembleimportAdaBoostClassifierfromsklearn。treeimportDecisionTreeClassifieradaclfAdaBoostClassifier(DecisionTreeClassifier(maxdepth2),nestimators500)adaclf。fit(Xtrain,ytrain)adaclf。score(Xtest,ytest)9。6GradientBoosting 训练一个模型m1,产生错误e1 针对e1训练第二个模型m2,产生错误e2 针对e2训练第二个模型m3,产生错误e3 。。。。。。 最终的预测模型是:m1m2m3。。。m1m2m3。。。 GradientBoosting是基于决策树的,不用指定BaseEstimatorfromsklearn。ensembleimportGradientBoostingClassifiergbclfGradientBoostingClassifier(maxdepth2,nestimators30)gbclf。fit(Xtrain,ytrain)gbclf。score(Xtest,ytest)总结 上述提到的集成学习模型,不仅可以用于解决分类问题,也可解决回归问题fromsklearn。ensembleimportBaggingRegressorfromsklearn。ensembleimportRandomForestRegressorfromsklearn。ensembleimportExtraTreesRegressorfromsklearn。ensembleimportAdaBoostRegressorfromsklearn。ensembleimportGradientBoostingRegressor例子: 决策树和AdaBoosting回归问题效果对比importnumpyasnpimportmatplotlib。pyplotaspltfromsklearn。treeimportDecisionTreeRegressorfromsklearn。ensembleimportAdaBoostRegressor构造测试函数rngnp。random。RandomState(1)Xnp。linspace(5,5,200)〔:,np。newaxis〕ynp。sin(X)。ravel()np。sin(6X)。ravel()rng。normal(0,0。1,X。shape〔0〕)回归决策树dtregDecisionTreeRegressor(maxdepth4)集成模型下的回归决策树adadtregAdaBoostRegressor(DecisionTreeRegressor(maxdepth4),nestimators200,randomstaterng)dtreg。fit(X,y)adadtreg。fit(X,y)预测y1dtreg。predict(X)y2adadtreg。predict(X)画图plt。figure()plt。scatter(X,y,ck,labeltrainningsamples)plt。plot(X,y1,cg,labelnestimators1,linewidth2)plt。plot(X,y2,cr,labelnestimators200,linewidth2)plt。xlabel(data)plt。ylabel(target)plt。title(BoostedDecisionTreeRegression)plt。legend()plt。show()10。Kmeans聚类 Kmeans算法实现:文章介绍了kmeans算法的基本原理和scikit中封装的kmeans库的基本参数的含义 Kmeans源码解读:这篇文章解读了scikit中kmeans的源码 本例的notebook笔记文件:git仓库 实例代码:frommatplotlibimportpyplotaspltfromsklearn。sns。set()matplotlibinline10。1传统Kmeans聚类 构造数据集fromsklearn。datasets。samplesgeneratorimportmakeblobsX,ytruemakeblobs(nsamples300,centers4,clusterstd0。60,randomstate0)plt。scatter(X〔:,0〕,X〔:,1〕,s50) fromsklearn。clusterimportKMeanskmeansKMeans(nclusters4)kmeans。fit(X)ykmeanskmeans。predict(X) 绘制聚类结果,画出聚类中心plt。scatter(X〔:,0〕,X〔:,1〕,cykmeans,s50,cmap‘viridis‘)centerskmeans。clustercentersplt。scatter(centers〔:,0〕,centers〔:,1〕,c‘black‘,s80,marker‘x‘)10。2非线性边界聚类 对于非线性边界的kmeans聚类的介绍,查阅于《python数据科学手册》P410 构造数据fromsklearn。datasetsimportmakemoonsX,ymakemoons(200,noise0。05,randomstate0) 传统kmeans聚类失败的情况labelsKMeans(nclusters2,randomstate0)。fitpredict(X)plt。scatter(X〔:,0〕,X〔:,1〕,clabels,s50,cmap‘viridis‘) 应用核方法,将数据投影到更高纬的空间,变成线性可分fromsklearn。clusterimportSpectralClusteringmodelSpectralClustering(nclusters2,affinity‘nearestneighbors‘,assignlabels‘kmeans‘)labelsmodel。fitpredict(X)plt。scatter(X〔:,0〕,X〔:,1〕,clabels,s50,cmap‘viridis‘) 10。3预测结果与真实标签的匹配 手写数字识别例子fromsklearn。datasetsimportloaddigitsdigitsloaddigits() 进行聚类kmeansKMeans(nclusters10,randomstate0)clusterskmeans。fitpredict(digits。data)kmeans。clustercenters。shape(10,64) 可以将这些族中心点看做是具有代表性的数字fig,axplt。subplots(2,5,figsize(8,3))centerskmeans。clustercenters。reshape(10,8,8)foraxi,centerinzip(ax。flat,centers):axi。set(xticks〔〕,yticks〔〕)axi。imshow(center,interpolation‘nearest‘,cmapplt。cm。binary) 进行众数匹配fromscipy。statsimportmodelabelsnp。zeroslike(clusters)foriinrange(10):得到聚类结果第i类的TrueFlase类型的index矩阵mask(clustersi)根据index矩阵,找出这些target中的众数,作为真实的labellabels〔mask〕mode(digits。target〔mask〕)〔0〕有了真实的指标,可以进行准确度计算accuracyscore(digits。target,labels)0。793544796883695110。4聚类结果的混淆矩阵fromsklearn。metricsimportconfusionmatrixmatconfusionmatrix(digits。target,labels)np。filldiagonal(mat,0)sns。heatmap(mat。T,squareTrue,annotTrue,fmt‘d‘,cbarFalse,xticklabelsdigits。targetnames,yticklabelsdigits。targetnames)plt。xlabel(‘truelabel‘)plt。ylabel(‘predictedlabel‘) 10。5t分布邻域嵌入预处理 即将高纬的非线性的数据 通过流形学习 投影到低维空间fromsklearn。manifoldimportTSNE投影数据此过程比较耗时tsenTSNE(ncomponents2,init‘pca‘,randomstate0)digitsprojtsen。fittransform(digits。data)计算聚类的结果kmeansKMeans(nclusters10,randomstate0)clusterskmeans。fitpredict(digitsproj)将聚类结果和真实标签进行匹配labelsnp。zeroslike(clusters)foriinrange(10):mask(clustersi)labels〔mask〕mode(digits。target〔mask〕)〔0〕计算准确度accuracyscore(digits。target,labels)11。高斯混合模型(聚类、密度估计) kmeans算法的非概率性和仅根据到族中心的距离指派族的特征导致该算法性能低下 且kmeans算法只对简单的,分离性能好的,并且是圆形分布的数据有比较好的效果 本例中所有代码的实现已上传至git仓库11。1观察Kmeans算法的缺陷 通过实例来观察Kmeans算法的缺陷matplotlibinlineimportmatplotlib。sns。set()importnumpyasnp生成数据点fromsklearn。datasets。samplesgeneratorimportmakeblobsX,ytruemakeblobs(nsamples400,centers4,clusterstd0。60,randomstate0)XX〔:,::1〕flipaxesforbetterplotting绘制出kmeans聚类后的标签的结果fromsklearn。clusterimportKMeanskmeansKMeans(4,randomstate0)labelskmeans。fit(X)。predict(X)plt。scatter(X〔:,0〕,X〔:,1〕,clabels,s40,cmap‘viridis‘);centerskmeans。clustercentersplt。scatter(centers〔:,0〕,centers〔:,1〕,c‘black‘,s80,marker‘x‘) kmeans算法相当于在每个族的中心放置了一个圆圈,(针对此处的二维数据来说) 半径是根据最远的点与族中心点的距离算出 下面用一个函数将这个聚类圆圈可视化fromsklearn。clusterimportKMeansfromscipy。spatial。distanceimportcdistdefplotkmeans(kmeans,X,nclusters4,rseed0,axNone):labelskmeans。fitpredict(X)plottheinputdataaxaxorplt。gca()ax。axis(‘equal‘)ax。scatter(X〔:,0〕,X〔:,1〕,clabels,s40,cmap‘viridis‘,zorder2)plottherepresentationoftheKMeansmodelcenterskmeans。clustercentersax。scatter(centers〔:,0〕,centers〔:,1〕,c‘black‘,s150,marker‘x‘)radii〔cdist(X〔labelsi〕,〔center〕)。max()fori,centerinenumerate(centers)〕用列表推导式求出每一个聚类中心i0,1,2,3在自己的所属族的距离的最大值labelsi返回一个布尔型index,所以X〔labelsi〕只取出i这个族类的数据点求出这些数据点到聚类中心的距离cdist(X〔labelsi〕,〔center〕)再求最大值。max()forc,rinzip(centers,radii):ax。addpatch(plt。Circle(c,r,fc‘CCCCCC‘,lw3,alpha0。5,zorder1))如果数据点不是圆形分布的kmeans算法的聚类效果就会变差rngnp。random。RandomState(13)这里乘以一个2,2的矩阵,相当于在空间上执行旋转拉伸操作Xstretchednp。dot(X,rng。randn(2,2))kmeansKMeans(nclusters4,randomstate0)plotkmeans(kmeans,Xstretched) 11。2引出高斯混合模型 高斯混合模型能够计算出每个数据点,属于每个族中心的概率大小 在默认参数设置的、数据简单可分的情况下, GMM的分类效果与kmeans基本相同fromsklearn。mixtureimportGaussianMixturegmmGaussianMixture(ncomponents4)。fit(X)labelsgmm。predict(X)plt。scatter(X〔:,0〕,X〔:,1〕,clabels,s40,cmap‘viridis‘);gmm的中心点叫做meanscentersgmm。meansplt。scatter(centers〔:,0〕,centers〔:,1〕,c‘black‘,s80,marker‘x‘); 得到数据的概率分布结果probsgmm。predictproba(X)print(probs〔:5〕。round(3))〔〔0。0。4690。0。531〕〔1。0。0。0。〕〔1。0。0。0。〕〔0。0。0。1。〕〔1。0。0。0。〕〕 编写绘制gmm绘制边界的函数frommatplotlib。patchesimportEllipsedefdrawellipse(position,covariance,axNone,kwargs):Drawanellipsewithagivenpositionandcovarianceaxaxorplt。gca()Convertcovariancetoprincipalaxesifcovariance。shape(2,2):U,s,Vtnp。linalg。svd(covariance)anglenp。degrees(np。arctan2(U〔1,0〕,U〔0,0〕))width,height2np。sqrt(s)else:angle0width,height2np。sqrt(covariance)DrawtheEllipsefornsiginrange(1,4):ax。addpatch(Ellipse(position,nsigwidth,nsigheight,angle,kwargs))defplotgmm(gmm,X,labelTrue,axNone):axaxorplt。gca()labelsgmm。fit(X)。predict(X)iflabel:ax。scatter(X〔:,0〕,X〔:,1〕,clabels,s40,cmap‘viridis‘,zorder2)else:ax。scatter(X〔:,0〕,X〔:,1〕,s40,zorder2)ax。axis(‘equal‘)wfactor0。2gmm。weights。max()forpos,covar,winzip(gmm。means,gmm。covariances,gmm。weights):drawellipse(pos,covar,alphawwfactor)在圆形数据上的聚类结果gmmGaussianMixture(ncomponents4,randomstate42)plotgmm(gmm,X) 在偏斜拉伸数据上的聚类结果gmmGaussianMixture(ncomponents4,covariancetype‘full‘,randomstate42)plotgmm(gmm,Xstretched) 11。3将GMM用作密度估计 GMM本质上是一个密度估计算法;也就是说,从技术的角度考虑, 一个GMM拟合的结果并不是一个聚类模型,而是描述数据分布的生成概率模型。非线性边界的情况构建非线性可分数据fromsklearn。datasetsimportmakemoonsXmoon,ymoonmakemoons(200,noise。05,randomstate0)plt。scatter(Xmoon〔:,0〕,Xmoon〔:,1〕); ?如果使用2个成分聚类(即废了结果设置为2),基本没什么效果gmm2GaussianMixture(ncomponents2,covariancetype‘full‘,randomstate0)plotgmm(gmm2,Xmoon) ?如果设置为多个聚类成分gmm16GaussianMixture(ncomponents16,covariancetype‘full‘,randomstate0)plotgmm(gmm16,Xmoon,labelFalse) 这里采用16个高斯曲线的混合形式不是为了找到数据的分隔的簇,而是为了对输入数据的总体分布建模。11。4由分布函数得到生成模型 分布函数的生成模型可以生成新的,与输入数据类似的随机分布函数(生成新的数据点) 用GMM拟合原始数据获得的16个成分生成的400个新数据点Xnewgmm16。sample(400)Xnew〔0〕〔:5〕Xnewgmm16。sample(400)plt。scatter(Xnew〔0〕〔:,0〕,Xnew〔0〕〔:,1〕); 11。5需要多少成分? 作为一种生成模型,GMM提供了一种确定数据集最优成分数量的方法。赤池信息量准则(Akaikeinformationcriterion)AIC贝叶斯信息准则(Bayesianinformationcriterion)BICncomponentsnp。arange(1,21)models〔GaussianMixture(n,covariancetype‘full‘,randomstate0)。fit(Xmoon)forninncomponents〕plt。plot(ncomponents,〔m。bic(Xmoon)forminmodels〕,label‘BIC‘)plt。plot(ncomponents,〔m。aic(Xmoon)forminmodels〕,label‘AIC‘)plt。legend(loc‘best‘)plt。xlabel(‘ncomponents‘); 观察可得,在812个主成分的时候,AIC较小评价指标一、分类算法 常用指标选择方式 平衡分类问题: 分类准确度、ROC曲线 类别不平衡问题: 精准率、召回率 对于二分类问题,常用的指标是f1、rocauc 多分类问题,可用的指标为f1weighted1。分类准确度 一般用于平衡分类问题(每个类比的可能性相同)fromsklearn。metricsimportaccuracyscoreaccuracyscore(ytest,ypredict)(真值,预测值)2。混淆矩阵、精准率、召回率精准率:正确预测为1的数量,占,所有预测为1的比例召回率:正确预测为1的数量,占,所有确实为1的比例先真实值,后预测值fromsklearn。metricsimportconfusionmatrixconfusionmatrix(ytest,ylogpredict)fromsklearn。metricsimportprecisionscoreprecisionscore(ytest,ylogpredict)fromsklearn。metricsimportrecallscorerecallscore(ytest,ylogpredict) 多分类问题中的混淆矩阵多分类结果的精准率fromsklearn。metricsimportprecisionscoreprecisionscore(ytest,ypredict,averagemicro)多分类问题中的混淆矩阵fromsklearn。metricsimportconfusionmatrixconfusionmatrix(ytest,ypredict)移除对角线上分类正确的结果,可视化查看其它分类错误的情况同样,横坐标为预测值,纵坐标为真实值cfmconfusionmatrix(ytest,ypredict)rowsumsnp。sum(cfm,axis1)errmatrixcfmrowsumsnp。filldiagonal(errmatrix,0)plt。matshow(errmatrix,cmapplt。cm。gray)plt。show()3。F1score F1score是精准率precision和召回率recall的调和平均数fromsklearn。metricsimportf1scoref1score(ytest,ypredict)4。精准率和召回率的平衡 可以通过调整阈值,改变精确率和召回率(默认阈值为0)拉高阈值,会提高精准率,降低召回率降低阈值,会降低精准率,提高召回率返回模型算法预测得到的成绩这里是以逻辑回归算法为例decisionscorelogreg。decisionfunction(Xtest)调整阈值为5ypredict2np。array(decisionscore5,dtype‘int‘)返回的结果是0、15。精准率召回率曲线(PR曲线)fromsklearn。metricsimportprecisionrecallcurveprecisions,recalls,thresholdsprecisionrecallcurve(ytest,decisionscore)这里的decisionscore是上面由模型对Xtest预测得到的对象绘制PR曲线精确率召回率曲线plt。plot(precisions,recalls)plt。show()将精准率和召回率曲线,绘制在同一张图中注意,当取最大的threshold值的时候,精准率1,召回率0, 但是,这个最大的threshold没有对应的值 因此thresholds会少一个plt。plot(thresholds,precisions〔:1〕,color‘r‘)plt。plot(thresholds,recalls〔:1〕,color‘b‘)plt。show()6。ROC曲线 ReciverOperationCharacteristicCurveTPR:TruePositiverateFPR:FalsePositiveRateFPRFPTNFPFPRFPTNFP 绘制ROC曲线fromsklearn。metricsimportroccurvefprs,tprs,thresholdsroccurve(ytest,decisionscores)plt。plot(fprs,tprs)plt。show() 计算ROC曲线下方的面积的函数 rocareaundercurvescorefromsklearn。metricsimportrocaucscorerocaucscore(ytest,decisionscores) 曲线下方的面积可用于比较两个模型的好坏 总之,上面提到的decisionscore是一个概率值,如01二分类问题,应该是将每个样本预测为1的概率, 如某个样本的ytest为1,ypredictprobablity为0。875 每个测试样本对应一个预测的概率值 通常在模型fit完成之后,都会有相应的得到概率的函数,如 model。predictprob(Xtest) model。decisionfunction(Xtest)二、回归算法1。均方误差MSEfromsklearn。metricsimportmeansquarederrormeansquarederror(ytest,ypredict)2。平均绝对值误差MAEfromsklearn。metricsimportmeanabsoluteerrormeanabsoluteerror(ytest,ypredict)3。均方根误差RMSE scikit中没有单独定于均方根误差,需要自己对均方误差MSE开平方根4。R2评分fromsklearn。metricsimportr2scorer2score(ytest,ypredict)5。学习曲线 观察模型在训练数据集和测试数据集上的评分,随着训练数据集样本数增加的变化趋势。importnumpyasnpimportmatplot。pyplotaspltfromsklearn。metricsimportmeansquarederrordefplotlearningcurve(algo,Xtrain,Xtest,ytrain,ytest):trainscore〔〕testscore〔〕foriinrange(1,len(Xtrain)1):algo。fit(Xtrain〔:i〕,ytrain〔:i〕)ytrainpredictalgo。predict(Xtrain〔:i〕)trainscore。append(meansquarederror(ytrain〔:i〕,ytrainpredict))ytestpredictalgo。predict(Xtest)testscore。append(meansquarederror(ytest,ytestpredict))plt。plot(〔iforiinrange(1,len(Xtrain)1)〕,np。sqrt(trainscore),labeltrain)plt。plot(〔iforiinrange(1,len(Xtrain)1)〕,np。sqrt(testscore),labeltest)plt。legend()plt。axis(〔0,len(Xtrain)1,0,4〕)plt。show()调用plotlearningcurve(LinearRegression(),Xtrain,Xtest,ytrain,ytest)