赞
踩
集成学习就是将多个弱学习器组合在一起,从而得到一个更好更全面的强监督学习器模型。其中集成学习被分为3大类:bagging(袋装法)不存在强依赖关系,其中基学习器保持并行关系学习。boosting(提升法)存在强依赖关系,其中基学习器存在串行的方式学习。stacking(模型融合)通过组合模型,来提高预测精度。
Ensemble Learning的第一个问题是如何得到若干个个体学习器。这里有两种选择。
目前来说,同质个体学习器的应用是最广泛的,一般我们常说的集成学习的方法都是指的同质个体学习器。而同质个体学习器使用最多的模型是CART决策树和神经网络。
想要获得良好的集成性能,基分类器需要满足两个条件
1———基学习器要一定的性能,并且基学习器的性能不差于随机猜测,且准确率要在50%之上
2———基学习器之间要由差异性,具有多样性,不能基学习器都相同。
学习器的结合策略主要细分为3总。我们假定得到T个弱学习器{h1,h2,,,,ht}
对于回归问题来讲,通常使用的是平均法,对若干个学习器的结果进行求平均。
通常对于分类问题来讲,使用的是投票法。分为三种,相对多数投票法,即少数服从多数;绝对多数投票法,不仅仅要求票数最多,而且还需要要求票数过半;加权投票法,每个弱学习器的分类树乘上一个权重,最后各个类别的加权票数求和,选择最大的。
将不会对弱学习器的结果做逻辑处理,而是再次之上再加上一层学习器。将训练集弱学习器的学习结果作为输入,训练集的输出作为输出,重新训练一个学习器来得到最终的结果。简而言之,再弱学习器之上再进行一次学习。
Bagging是并行式集成学习的最著名代表,名字是由Bootstrap AGGregatING缩写而来,看到Bootstrap我们就会联想到boostrap的随机模拟法和它对应的样本获取方式,它是基于自助采样法(Boostrap sampleing),Bagging也是同理.给定包含m个样本的数据集,先随机抽取一个样本放入采样集中,再把该样本放回,使得下次采样时该样本仍有机会被选中,这样经过m次采样,我们便从原始是数据集中抽取样本得到一个数据量同为m的数据集.说简单一点就是统计里的有放回抽样,且每个样本被抽取的概率相同,均为总样本数分之一。Bagging可以用于多分类,回归的任务.
bagging的算法过程如下:
Boosting由于各个基学习器处于串行的关系,各个基学习器存在强依赖关系,所以Boosting的学习是一个迭代的过程。
Boosting的学习机制为:先从基学习器当中训练出来一个基学习器,再根据基学习器对数据集的表现进行操作(将训练错误的数据的权重增大,训练正确的数据的权重减少。)基于调整后的数据集来训练下一个基学习器。如此重复,在基学习器达到设定的数量的时候,然后将这N个基学习器的结果进行加权求平均操作。Boosting中主要为Adaboost,XGBoost。
从偏差-方差的角度来看,Boosting主要关注降低偏差。从而说明Boosting是一个过拟合的模型。
偏差(variance)和方差(bias)
偏差(bias):预测值和真实值之间的误差。
方差(variance):预测值之间的离散程度,距离其期望值的距离。方差越大,数据的离散程度就会分散。
对于偏差(bais):偏差过高是由于模型的复杂度不够,泛化能力不够,应该通过增加模型复杂度来降低偏差(bais)。
对于方差(variance):方差过高是由于模型的泛化能能力过强,导致了过拟合,应该通过降低模型复杂度来实现。
比如加入正则化来限制模型的学习。
AdaBoost既可以做回归也可以做分类.理论上任何学习器都可以用于Adaboost.但一般来说,使用最广泛的Adaboost弱学习器是决策树和神经网络。对于决策树,Adaboost分类用了CART分类树,而Adaboost回归用了CART回归树。
优缺点总结:
优点总结
暂时省略。。。。
from numpy import * import matplotlib.pyplot as plt import random from sklearn import tree def loadDataSet(filename): numFeat = len(open(filename).readline().split('\t')) dataMat = [] labelMat = [] fr = open(filename) for line in fr.readlines(): lineArr = [] curLine = line.strip().split('\t')#line.strip()首先清除掉一些空格,然后按照'\t'进行划分 for i in range(numFeat - 1):#添加数据 lineArr.append(float(curLine[i])) dataMat.append(lineArr) labelMat.append(float(curLine[-1]))#添加数据对应标签 return dataMat,labelMat #自助法采样 def rand_train(dataMat,labelMat): len_train = len(labelMat) train_data = [] train_label = [] #抽取样本的次数为样本的数目 for i in range(len_train): index = random.randint(0,len_train-1) train_data.append(dataMat[index]) train_label.append(labelMat[index]) return train_data,train_label #决策树学习 #默认并行生成十个基学习器 def bagging_by_tree(dataMat,labelMat,t=10): test_data,test_label = loadDataSet('E:/ZGW/PycharmProjects1/pythonProject1/scikit-learn/ensemble_learning/HorseColicData/horseColicTest.txt') predict_list = [] for i in range(t): train_data,train_label = rand_train(dataMat,labelMat) clf = tree.DecisionTreeClassifier()#初始化决策树模型 clf.fit(train_data,train_label)#训练模型 total = [] y_predicted = clf.predict(test_data)#预测数据 total.append(y_predicted) predict_list.append(total)#结果添加到预测列表当中 return predict_list,test_label #计算错误率 def calc_error(predict_list,test_label): m,n,k = shape(predict_list) #分类问题就使用投票数,投票数占比最多的一个类别。 predict_label = sum(predict_list,axis=0) predict_label = sign(predict_label)#取数字符号(数字前的正负号).如果为负号就说明类别数为-1,如果为正号就说明类别数为+1. for i in range(len(predict_label[0])): if predict_label[0][i] == 0: tip = random.randint(0,1) if tip == 0: predict_label[0][i] = 1 else: predict_label[0][i] = -1 error_count = 0 for i in range(k): if predict_label[0][i] != test_label[i]: error_count += 1 error_rate = error_count / k return error_rate def bagging_by_Onetree(dataMat,labelMat,t=10): test_data,test_label = loadDataSet('E:/ZGW/PycharmProjects1/pythonProject1/scikit-learn/ensemble_learning/HorseColicData/horseColicTest.txt') train_data,train_label = rand_train(dataMat,labelMat) clf = tree.DecisionTreeClassifier() clf.fit(train_data,train_label) y_predicted = clf.predict(test_data) error_count = 0 for i in range(67): if y_predicted[i] != test_label[i]: error_count += 1 return error_count/67 if __name__ == "__main__": fileName = 'E:/ZGW/PycharmProjects1/pythonProject1/scikit-learn/ensemble_learning/HorseColicData/horseColicTraining.txt' dataMat,labelMat = loadDataSet(fileName) train_data,train_label = rand_train(dataMat,labelMat) predict_list , test_label = bagging_by_tree(dataMat,labelMat) print('单一错误率:',bagging_by_Onetree(dataMat,labelMat)) print("Bagging错误率:",calc_error(predict_list,test_label))
AdaBoost-参数
AdaBoost-方法
from sklearn.ensemble import AdaBoostClassifier,RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.pipeline import make_pipeline#连续处理操作 from sklearn.preprocessing import StandardScaler#标准化 from sklearn.datasets import make_moons,make_circles,make_classification#数据多样化的建立 from sklearn.neural_network import MLPClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.svm import SVC from sklearn.tree import DecisionTreeClassifier#需要注意的是版本的对应,这个玩意需要scikit-learn。1.1以上的版本,需要保证python的版本3.9. from sklearn.naive_bayes import GaussianNB from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis from sklearn.gaussian_process import GaussianProcessClassifier from sklearn.gaussian_process.kernels import RBF from matplotlib.colors import ListedColormap from sklearn.inspection import DecisionBoundaryDisplay import numpy as np import pandas as pd import matplotlib.pyplot as plt #分类器名称 names = [ 'Nearest Neighbors', 'Linear SVM', 'RBF SVN', 'Decision Tree', 'Random Forest', 'Neural Net', 'AdaBoost', 'Native Bayes', ] #分类器实例化 classifier = [ KNeighborsClassifier(3), SVC(kernel='linear',C=0.025), SVC(gamma=2,C=1), DecisionTreeClassifier(max_depth=5), RandomForestClassifier(max_depth=5,n_estimators=10,max_features=1), MLPClassifier(alpha=1,max_iter=1000),#float,可选,默认为0.0001。L2惩罚(正则化项)参数。 AdaBoostClassifier(), GaussianNB(), ] #数据的建立 X,y = make_classification(n_features=2,n_redundant=0,n_informative=2,random_state=1, n_clusters_per_class=1) rng = np.random.RandomState(2)#设置随机变量,以重复多次实验。 X = X + 2*rng.uniform(size=X.shape)#在原有的数据基础之上加上一些噪音。 linearly_separable = (X,y) datasets = [ make_moons(noise=0.3,random_state=0), make_circles(noise=0.2,factor=0.5,random_state=1), linearly_separable, ] plt.figure(figsize=(27,9)) i = 1 for ds_cnt,ds in enumerate(datasets): X,y = ds X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.4,random_state=42) x_min,x_max = X[:,0].min() - 0.5,X[:,0].max() + 0.5 y_min,y_max = X[:,1].min() - 0.5,X[:,1].max() + 0.5 #just plot the dataset first cm = plt.cm.RdBu#颜色图 cm_bright = ListedColormap(["#FF0000", "#0000FF"]) ax = plt.subplot(len(datasets),len(classifier)+1,i) if ds_cnt == 0: ax.set_title('Input data') #Plot the training points ax.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap = cm_bright,edgecolors = 'k') #Plot the testing points ax.scatter(X_test[:,0],X_test[:,1],cmap = cm_bright,edgecolors = 'k',c=y_test,alpha=0.6) ax.set_xlim(x_min,x_max) ax.set_ylim(y_min,y_max) ax.set_xticks(()) ax.set_yticks(()) i = i + 1 #iterate over classifier for name,clf in zip(names,classifier): ax = plt.subplot(len(datasets),len(classifier) + 1,i) clf = make_pipeline(StandardScaler(),clf) clf.fit(X_train,y_train) score = clf.score(X_test,y_test) DecisionBoundaryDisplay.from_estimator( clf, X, cmap=cm, alpha=0.8, ax=ax, eps=0.5 ) #Plot the training points ax.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap=cm_bright,edgecolors='k') #Plot the testing points ax.scatter(X_test[:,0],X_test[:,1],c=y_test,cmap=cm_bright,edgecolors='k',alpha=0.6) ax.set_xlim(x_min,x_max) ax.set_ylim(y_min,y_max) ax.set_xticks(()) ax.set_yticks(()) if ds_cnt == 0: ax.set_title(name) ax.text(x_max - 0.3,y_min + 0.3,('%.2f' % score).lstrip('0'),size=15,horizontalalignment='right') i = i + 1 plt.tight_layout() plt.show()
回归
import numpy as np from sklearn.ensemble import AdaBoostRegressor from sklearn.tree import DecisionTreeRegressor import matplotlib.pyplot as plt import seaborn as sns rng = np.random.RandomState(1) X = np.linspace(0,6,100).reshape(100,-1) y = np.sin(X).ravel() + np.sin(6 * X).ravel() + rng.normal(0,0.1,X.shape[0]) regr_1 = DecisionTreeRegressor(max_depth=4) regr_2 = AdaBoostRegressor(DecisionTreeRegressor(max_depth=4),n_estimators=300,random_state=rng) regr_1.fit(X, y) regr_2.fit(X, y) y_1 = regr_1.predict(X) y_2 = regr_2.predict(X) colors = sns.color_palette('colorblind') plt.figure() plt.scatter(X,y,color=colors[0],label = 'trainning samples')#原始数据显示散点图 plt.plot(X,y_1,color = colors[1], label="n_estimators=300", linewidth=2) plt.plot(X,y_2,color = colors[2], label="n_estimators=300", linewidth=2) plt.xlabel('data') plt.ylabel('target') plt.title("Boosted Decision Tree Regression") plt.legend() plt.show()
GBDT(Gradient Boosting Decision Tree)是由决策树(Decision Tree)构成的,所有决策树(Decision Tree)的结果累加起来就是GBDT(Gradient Boosting Decision Tree)的最终结果。无论是处理回归问题还是二分类以及多分类,GBDT使用的决策树通通都是都是CART回归树。目前GBDT的算法比较好的库是xgboost。当然scikit-learn也可以。
这里的“梯度”和“提升”没有直接关系:“梯度”被用来让损失函数快速下降,进而让模型效果“提升”。
优点总结
暂时省略。。。。
import matplotlib.pyplot as plt import numpy as np from sklearn import datasets, ensemble from sklearn.inspection import permutation_importance#特征重要性排列顺序 from sklearn.metrics import mean_squared_error from sklearn.model_selection import train_test_split diabetes = datasets.load_diabetes() X, y = diabetes.data, diabetes.target X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.1, random_state=13 ) params = { "n_estimators": 500, "max_depth": 4, "min_samples_split": 5, "learning_rate": 0.01, #"loss": "squared_error", } reg = ensemble.GradientBoostingRegressor(**params) reg.fit(X_train, y_train) mse = mean_squared_error(y_test, reg.predict(X_test)) print("The mean squared error (MSE) on test set: {:.4f}".format(mse)) test_score = np.zeros((params["n_estimators"],), dtype=np.float64) for i,y_pred in enumerate(reg.staged_predict(X_test)):#返回每个基分类器的预测数据集X的结果。 test_score[i] = mean_squared_error(y_test,y_pred) fig = plt.figure(figsize=(6,6)) plt.subplot(1,1,1) plt.title('Deviance') plt.plot(np.arange(params['n_estimators']) + 1,reg.train_score_,'b-',label='Training Set Deviance') plt.plot(np.arange(params['n_estimators']) + 1,test_score,'r-',label = 'Test Set Deviance') plt.legend(loc='upper right') plt.xlabel('Boosting Iterations') plt.ylabel('Deviance') plt.tight_layout() plt.show() feature_importance = reg.feature_importances_ sorted_idx = np.argsort(feature_importance)#返回的是索引列表 pos = np.arange(sorted_idx.shape[0]) + 0.5 fig = plt.figure(figsize=(12,6)) plt.subplot(1,2,1) plt.barh(pos,feature_importance[sorted_idx],align='center') plt.yticks(pos,np.array(diabetes.feature_names)[sorted_idx]) plt.title('Feature Importance (MDI)') #n_repeats=10:排列特征的次数。置换特征的次数。个人理解可能是交换计算特征重要性的次数。 result = permutation_importance(reg, X_test, y_test, n_repeats=10, random_state=42, n_jobs=2) sorted_idx = result.importances_mean.argsort()#获得到特征影响因素最大的下表索引, abc = result.importances[sorted_idx].T plt.subplot(1,2,2) plt.boxplot(result.importances[sorted_idx].T,vert=False,labels=np.array(diabetes.feature_names)[sorted_idx]) plt.title('Permutation Importance (test set)') plt.tight_layout() plt.show() print()
XGBoost(Extreme Gradient Boosting),即一种高效的梯度提升决策树算法。他在原有的GBDT基础上进行了改进,使得模型效果得到大大提升。作为一种前向加法模型,他的核心是采用集成思想——Boosting思想,将多个弱学习器通过一定的方法整合为一个强学习器。即用多棵树共同决策,并且用每棵树的结果都是目标值与之前所有树的预测结果之差 并将所有的结果累加即得到最终的结果,以此达到整个模型效果的提升。
XGBoost是由多棵CART(Classification And Regression Tree),即分类回归树组成,因此他可以处理分类回归等问题。
在数据科学方面,有大量的Kaggle选手选用XGBoost进行数据挖掘比赛,是各大数据科学比赛的必杀武器;在工业界大规模数据方面,XGBoost的分布式版本有广泛的可移植性,支持在Kubernetes、Hadoop、SGE、MPI、 Dask等各个分布式环境上运行,使得它可以很好地解决工业界大规模数据的问题。
暂时省略
代码在另一个文件当中存放.
GBDT在工业界应用广泛,通常被用于点击率预测,搜索排序等任务。LightGBM (Light Gradient Boosting Machine)是一个实现GBDT算法的框架,支持高效率的并行训练。
优点总结
在stacking方法中,我们把个体学习器叫做初级学习器,用于结合的学习器叫做次级学习器或元学习器(meta-learner),次级学习器用于训练的数据叫做次级训练集。次级训练集是在训练集上用初级学习器得到的。
参考连接:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。