10.5 堆垛分类(Stacking Classifier)
10.5.1 理论
stacking严格来说并不是一种算法,而是精美而又复杂的,对模型集成的一种策略。
- 首先我们会得到两组数据:训练集和测试集。将训练集分成5份:train1,train2,train3,train4,train5。
- 选定基模型。这里假定我们选择了xgboost, lightgbm 和 randomforest 这三种作为基模型。比如xgboost模型部分:依次用train1,train2,train3,train4,train5作为验证集,其余4份作为训练集,进行5折交叉验证进行模型训练;再在测试集上进行预测。这样会得到在训练集上由xgboost模型训练出来的5份predictions,和在测试集上的1份预测值B1。将这五份纵向重叠合并起来得到A1。lightgbm和randomforest模型部分同理。
- 三个基模型训练完毕后,将三个模型在训练集上的预测值作为分别作为3个"特征"A1,A2,A3,使用LR模型进行训练,建立LR模型。
- 使用训练好的LR模型,在三个基模型之前在测试集上的预测值所构建的三个"特征"的值(B1,B2,B3)上,进行预测,得出最终的预测类别或概率。
做stacking,首先需要安装mlxtend库。安装方法:进入Anaconda Prompt,输入命令 pip install mlxtend 即可。
10.5.2堆垛分类(Stacking Classifier)
堆垛分类学习曲线
def My_StackingClassifier_1(mydata,title): warnings.filterwarnings("ignore") myutil = util() X,y = mydata.data,mydata.target X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42) #基分类器1:AdaBoostClassifier pipe1 = make_pipeline(ColumnSelector(cols=(0, 2)),AdaBoostClassifier()) #基分类器2:RandomForest pipe2 = make_pipeline(ColumnSelector(cols=(1, 2, 3)),RandomForestClassifier()) sclf = StackingClassifier(classifiers=[pipe1, pipe2], meta_classifier=LogisticRegression()) sclf.fit(X_train, y_train) mytitle = title+" "+" StackingClassifier" myutil.print_scores(sclf,X_train,y_train,X_test,y_test,mytitle) myutil.plot_learning_curve(StackingClassifier(classifiers=[pipe1, pipe2], meta_classifier=LogisticRegression()),X,y,mytitle) myutil.show_pic(mytitle) def call_StackingClassifier_1(): mydatas = [datasets.load_iris(), datasets.load_wine(), datasets.load_breast_cancer()] titles = ["鸢尾花数据","红酒数据","乳腺癌数据"] for (mydata,title) in zip(mydatas, titles): My_StackingClassifier_1(mydata,title)
输出
鸢尾花数据 StackingClassifier: 100.00% 鸢尾花数据 StackingClassifier: 100.00% 红酒数据 StackingClassifier: 100.00% 红酒数据 StackingClassifier: 80.00% 乳腺癌数据 StackingClassifier: 100.00% 乳腺癌数据 StackingClassifier: 93.71%
堆垛分类多重验证
def My_StackingClassifier_2(mydata,title): warnings.filterwarnings("ignore") myutil = util() X,y = mydata.data[:, 1:3],mydata.target basemodel1 = AdaBoostClassifier() basemodel2 = lgb.LGBMClassifier() basemodel3 = RandomForestClassifier(random_state=1) lr = LogisticRegression() sclf = StackingClassifier(classifiers=[basemodel1, basemodel2, basemodel3], meta_classifier=lr) print(title+'五重交叉验证:\n') for basemodel, label in zip([basemodel1, basemodel2, basemodel3, sclf], ['adaboost', 'lightgbm', 'Random Forest','StackingClassifier']): scores = model_selection.cross_val_score(basemodel,X, y, cv=5, scoring='accuracy') print("准确度: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label)) def call_StackingClassifier_2(): mydatas = [datasets.load_iris(), datasets.load_wine(), datasets.load_breast_cancer()] titles = ["鸢尾花数据","红酒数据","乳腺癌数据"] for (mydata,title) in zip(mydatas, titles): My_StackingClassifier_2(mydata,title)
输出
鸢尾花数据五重交叉验证: 准确度: 0.86 (+/- 0.10) [adaboost] 准确度: 0.95 (+/- 0.03) [lightgbm] 准确度: 0.94 (+/- 0.04) [Random Forest] 准确度: 0.94 (+/- 0.04) [StackingClassifier] 红酒数据五重交叉验证: 准确度: 0.66 (+/- 0.08) [adaboost] 准确度: 0.58 (+/- 0.06) [lightgbm] 准确度: 0.61 (+/- 0.04) [Random Forest] 准确度: 0.62 (+/- 0.03) [StackingClassifier] 乳腺癌数据五重交叉验证: 准确度: 0.88 (+/- 0.04) [adaboost] 准确度: 0.90 (+/- 0.02) [lightgbm] 准确度: 0.88 (+/- 0.03) [Random Forest] 准确度: 0.89 (+/- 0.02) [StackingClassifier]
11聚类
1.1介绍
分类:事先的类别是已知的,属于有监督学习;
聚类:事先的类别是未知的,属于无监督学习;聚类根据数据的共同性,自由结合,所谓鱼找鱼、虾找虾。由于聚类事现不知道最后应该属于哪个类,所以就不存在目标值,也就不存在得分了。
1.2 三个聚类算法比较
算法 |
特色 |
K均值 |
允许用户设定"簇"的数量 用簇平均值表示簇 |
凝聚 |
允许用户设定"簇"的数量 划分整个层次结构,通过树状图查看 |
DBSCAN |
可以检测没有分配的噪音 允许用户设定eps定义接近程度,从而影响"簇"的大小 可以生成差别很大的两个"簇" |
1.3 K均值聚类(k-Means)
1.3.1原理
K均值聚类算法(K-Means Clustering Algorithm)是一种迭代求解的聚类分析算法,其步骤是,预将数据分为K组,则随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。
K-Means算法基本步骤
- 从数据中选择K个对象作为初始聚类中心;
- 计算每个聚类对象到聚类中心的距离来划分;
- 再次计算每个聚类中心
- 计算标准测度函数,直到到达最大迭代次数,则停止,否则,继续操作。
1.3.2类参数、属性和方法
类
class sklearn.cluster.KMeans(n_clusters=8, *, init='k-means++', n_init=10, max_iter=300, tol=0.0001, precompute_distances='deprecated', verbose=0, random_state=None, copy_x=True, n_jobs='deprecated', algorithm='auto')
属性
属性 |
类别 |
介绍 |
cluster_centers_ |
ndarray of shape (n_clusters, n_features) |
集群中心的坐标。如果算法在完全收敛之前停止(参见tol和max_iter),这些将与标签不一致。labels_ndarray of shape (n_samples,)每个点的标签 |
inertia_ |
float |
样本到最近聚类中心的平方距离之和。 |
n_iter_ |
int |
运行的迭代次数。 |
方法
fit(X[, y, sample_weight]) |
计算k-均值聚类。 |
fit_predict(X[, y, sample_weight]) |
计算聚类中心并预测每个样本的聚类指数。 |
fit_transform(X[, y, sample_weight]) |
计算聚类,将X变换到聚类距离空间。 |
get_params([deep]) |
获取此估计器的参数。 |
predict(X[, sample_weight]) |
预测X中每个样本所属的最近聚类。 |
score(X[, y, sample_weight]) |
与K-均值目标上的X值相反。 |
set_params(**params) |
设置此估计器的参数。 |
transform(X) |
将X变换到一个聚类距离空间。 |
1.3.3对make_blobs数据进行KMeans算法散点图分析
#K均值算法,Sklern KMeans算法 from sklearn.datasets import make_blobs from sklearn.cluster import KMeans import mglearn #pip3 install mglearn import matplotlib.pyplot as plt import numpy as np def KMeans_for_blobs (): blobs = make_blobs(random_state=1,centers=1) X = blobs[0] y = blobs[1] #设置簇个数为3 Kmeans = KMeans(n_clusters=3) Kmeans.fit(X) print("训练集数据集分配簇标签为:\n{}".format(Kmeans.labels_)) print("对训练集数据集预测结果为:",Kmeans.predict(X)) X_blobs = blobs[0] X_min,X_max = X_blobs[:,0].min()-0.5,X_blobs[:,0].max()+0.5 y_min,y_max = X_blobs[:,1].min()-0.5,X_blobs[:,1].max()+0.5 xx, yy = np.meshgrid(np.arange(X_min, X_max, .02),np.arange(y_min, y_max, .02)) Z = Kmeans.predict(np.c_[xx.ravel(),yy.ravel()]) Z = Z.reshape(xx.shape) plt.figure(1) plt.imshow(Z,interpolation='nearest',extent=(xx.min(),xx.max(),yy.min(),yy.max()),cmap=plt.cm.summer,aspect='auto',origin='lower') plt.plot(X_blobs[:,0],X_blobs[:,1],'r,',markersize=5) #用蓝色*代表聚类的中心 centroids = Kmeans.cluster_centers_ plt.scatter(centroids[:,0],centroids[:,1],marker='x',s=150,linewidths=3,color='b',zorder=10) plt.xlim(X_min,X_max) plt.ylim(y_min,y_max) plt.xticks(()) plt.yticks(()) plt.show()
mglearn.plots.plot_kmeans_boundaries() plt.show()
mglearn库,该库集成了sklearn和数据的许多操作方法,很便捷,获取对应数据。
1.3.4 K均值聚类鸢尾花
Util.py
#画聚类散点图 def draw_scatter_for_Clustering(self,X,y,result,title,algorithm): print(title+"原始数据集分配簇标签为:\n{}".format(y)) print(title+" "+algorithm+" 训练簇标签为:\n{}".format(result)) plt.scatter(X[:,0],X[:,1],c=y,cmap=plt.cm.spring,edgecolor='k') self.show_pic(title+"原始数据集分配簇标签图") plt.scatter(X[:,0],X[:,1],c=result,cmap=plt.cm.spring,edgecolor='k') self.show_pic(title+" "+algorithm+"训练簇标签标签图")
def KMeans_for_iris(): myutil = util() X,y = datasets.load_iris().data,datasets.load_iris().target Kmeans = KMeans(n_clusters=3) Kmeans.fit(X) result = Kmeans.fit_predict(X) title = "鸢尾花" myutil.draw_scatter_for_Clustering(X,y,result,title,"KMeans")
输出
鸢尾花原始数据集分配簇标签为: [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] 鸢尾花Kmeans训练簇标签为: [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 2 2 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 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 1 1 1 1 2 1 1 1 1 1 1 2 2 1 1 1 1 2 1 2 1 2 1 1 2 2 1 1 1 1 1 2 1 1 1 1 2 1 1 1 2 1 1 1 2 1 1 2]
1.3.5 K均值聚类红酒
def KMeans_for_wine(): myutil = util() X,y = datasets.load_wine().data,datasets.load_wine().target Kmeans = KMeans(n_clusters=3) Kmeans.fit(X) result = Kmeans.fit_predict(X) title = "红酒" myutil.draw_scatter_for_Clustering(X,y,result,title,"KMeans")
输出
红酒原始数据集分配簇标签为: [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 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 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] 红酒 KMeans 训练簇标签为: [1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 1 2 2 1 1 2 1 1 1 1 1 1 2 2 1 1 2 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 2 0 2 0 0 2 0 0 2 2 2 0 0 1 2 0 0 0 2 0 0 2 2 0 0 0 0 0 2 2 0 0 0 0 0 2 2 0 2 0 2 0 0 0 2 0 0 0 0 2 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 2 0 0 2 2 2 2 0 0 0 2 2 0 0 2 2 0 2 2 0 0 0 0 2 2 2 0 2 2 2 0 2 0 2 2 0 2 2 2 2 0 0 2 2 2 2 2 0]
1.3.6 K均值聚类乳腺癌
def KMeans_for_breast_cancer(): myutil = util() X,y = datasets.load_breast_cancer().data,datasets.load_breast_cancer().target Kmeans = KMeans(n_clusters=2) Kmeans.fit(X) result = Kmeans.fit_predict(X) title = "乳腺癌" myutil.draw_scatter_for_Clustering(X,y,result,title,"KMeans")
输出
乳腺癌原始数据集分配簇标签为: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 … 1 1 1 1 1 1 1 0 0 0 0 0 0 1] 乳腺癌 KMeans 训练簇标签为: [1 1 1 0 1 0 1 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 1 1 0 1 1 1 1 0 1 1 1 1 0 … 0 0 0 0 0 0 0 0 1 1 1 0 1 0]
1.3.7 K均值聚类两个月亮
#两个月亮 def KMeans_for_two_moon(): myutil = util() X, y = datasets.make_moons(n_samples=200,noise=0.05, random_state=0) scaler = StandardScaler() scaler.fit(X) X_scaled = scaler.transform(X) # 打印处理后的数据形态 print("处理后的数据形态:",X_scaled.shape) # 处理后的数据形态: (200, 2) 200个样本 2类 Kmeans = KMeans(n_clusters=2) result=Kmeans.fit_predict(X_scaled) title = "两个月亮" #绘制簇分配结果 myutil.draw_scatter_for_Clustering(X,y,result,title,"KMeans")
输出
处理后的数据形态: (200, 2) 两个月亮原始数据集分配簇标签为: [0 1 1 0 1 1 0 1 0 1 0 1 1 1 0 0 0 1 0 0 1 1 0 1 0 1 1 1 1 0 0 0 1 1 0 1 1 0 0 1 1 0 0 1 1 0 0 0 1 1 0 1 1 0 1 0 0 1 0 0 1 0 1 0 1 0 0 1 0 0 1 0 1 1 1 0 1 0 0 1 1 0 1 1 1 0 0 0 1 1 0 0 1 0 1 1 1 1 0 1 1 1 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1 1 0 0 0 1 1 1 1 0 1 0 1 1 0 0 0 0 1 1 0 1 1 1 0 0 1 0 1 1 0 0 1 1 0 1 1 1 0 1 1 1 0 0 0 0 1 1 1 0 0 0 1 0 1 1 1 0 0 1 0 0 0 0 0 0 1 0 1 1 0 1] 两个月亮 KMeans 训练簇标签为: [1 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 1 1 1 0 1 1 0 0 0 1 1 0 1 1 1 0 1 0 1 0 0 1 0 0 1 0 1 1 0 1 1 0 1 0 1 0 1 1 0 1 1 0 1 0 1 0 1 1 0 1 0 0 1 0 0 1 1 0 1 0 0 1 0 0 1 0 0 0 0 1 1 0 0 1 0 1 1 1 1 0 1 1 1 1 1 0 0 1 0 0 1 1 1 1 1 1 1 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 1 1 1 0 0 0 1 1 0 0 1 1 0 1 0 0 1 1 0 0 1 0 0 0 1 0 0 0 1 1 1 1 0 0 0 1 1 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 1 1 0 0 1 0]
1.3.8 K均值聚类的缺点
- 依赖随机种子
- 对簇形状的假设约束比较强
- 要求指定寻找簇的个数