集成学习导航:决策树与随机森林
【机器学习】使用scikitLearn进行决策树分类与回归:DecisionTreeClassifier及DecisionTreeRegressor
【机器学习】集成学习:使用scikitLearn中的VotingClassifier综合多个不同模型进行软硬投票
【机器学习】集成学习:使用scikitLearn中的BaggingClassifier实现bagging和pasting策略
【机器学习】集成学习:使用scikitLearn中的RandomForestClassifier及RandomForestRegressor实现随机森林
提升法:
一、AdaBoost
一类集成学习方法的总称,同样是多个弱学习器,组成一个强学习器:其最具代表性方法,是AdaBoost,具体做法是,新一轮训练,重点关注前一轮训练时的错例,给予错例数据更高的权值,如此循环训练提升模型效果。
AdaBoost确定是无法并行训练,第一个模型训练好后才能训练第二个,最终所有模型输出结果进行加权(如果每个模型能输出概率,否则就为硬投票)产生最终结果。
AdaBoost在训练时,数据初始的权重一致,每训练一个模型,根据模型的预测结果,重新重置权重:
得出结果后,再对权重做归一化处理。
上图中,单个预测模型的权重为αj,此值为模型的权重而非数据的权重,当预测其预测越准时,其取值越大;当预测值和最终结果不同时,该实例权重变大。当单个预测模型准确度越高时(αj取值越大),相对于准确度低的模型,该数据实例权重越大。
这里αj由下列两式直接定义:
(1)错误比率
上式来看,分类器预测错误越多,rj的值越大。
(2)Odds(几率):指该事件发生的概率与该事件不发生概率的比值。
log为一增函数,其定义域为1/rj-1,当rj值越小时,其值越大。故是模型准确率越高时,aj值越大。
举个例子,在以前没有权重时(其实是平局权重时),一共10个点时,对应每个点的权重都是0.1,分错1个,错误率就加0.1;分错3个,错误率就是0.3。经过第一轮训练,数据权重重置后,还是10个点,权重依次是[0.01,0.01,0.01,0.01,0.01,0.01, 0.01,0.01,0.01,0.91],如果分错了第1一个点,那么错误率是0.01,分错了最后一个点,那么错误率就是0.91。这样,在选择决策点的时候自然是要尽量把权重大的点分对才能尽可能降低误差率。权重分布影响着单层决策树决策点的选择(这里使用CART作为基本的决策模型,使用adboost的误差率aj代替了原始决策树的损失函数基尼系数)
在scikitLearn种,对应有AdaBoostClassifier类及AdaBoostRegressor类进行分类及回归操作,其代码如下:
from sklearn.ensemble import AdaBoostClassifier
ada_clf = AdaBoostClassifier(
DecisionTreeClassifier(max_depth=1), n_estimators=200,
#当算法选用SAMME.R时,基础模型需带有predict_proba()输出概率方法,
#此时可以进行软投票,否则应使用 algorithm="SAMME"
algorithm="SAMME.R", learning_rate=0.5, random_state=42)
ada_clf.fit(X_train, y_train)
二、梯度提升Gradient Boosting及梯度提升树GBDT:
梯度提升与AdaBoost的重要差别在于,梯度提升对上一个模型的残差进行拟合。
下面上一段GBDT进行回归的代码:
from sklearn.tree import DecisionTreeRegressor
#第一棵决策树
tree_reg1 = DecisionTreeRegressor(max_depth=2, random_state=42)
tree_reg1.fit(X, y)
DecisionTreeRegressor(max_depth=2, random_state=42)
#第二棵决策树,拟合第一颗的残差
y2 = y - tree_reg1.predict(X)
tree_reg2 = DecisionTreeRegressor(max_depth=2, random_state=42)
tree_reg2.fit(X, y2)
DecisionTreeRegressor(max_depth=2, random_state=42)
#第三颗决策树,继续拟合残差
y3 = y2 - tree_reg2.predict(X)
tree_reg3 = DecisionTreeRegressor(max_depth=2, random_state=42)
tree_reg3.fit(X, y3)
DecisionTreeRegressor(max_depth=2, random_state=42)
X_new = np.array([[0.8]])
#预测结果求和,得出最终结果
y_pred = sum(tree.predict(X_new) for tree in (tree_reg1, tree_reg2, tree_reg3))
也可以直接用scikitLearn给出的现成类:
from sklearn.ensemble import GradientBoostingRegressor
gbrt = GradientBoostingRegressor(max_depth=2, n_estimators=3, learning_rate=1.0, random_state=42)
gbrt.fit(X, y)
注:该算法也可用于分类:详见函数原型GradientBoostingClassifier
class sklearn.ensemble.GradientBoostingClassifier(
loss=’deviance’, learning_rate=0.1,
n_estimators=100, subsample=1.0,
criterion=’friedman_mse’, min_samples_split=2,
min_samples_leaf=1, min_weight_fraction_leaf=0.0,
max_depth=3, min_impurity_decrease=0.0,
min_impurity_split=None, init=None,
random_state=None, max_features=None,
verbose=0, max_leaf_nodes=None,
warm_start=False, presort=’auto’)
实际上,在训练时,最佳模型的数量,往往决定最终拟合结果是欠拟合还是过拟合,下述代码可以在训练过程中,找出最优模型数量:
#warm_start=True,接着训练模型,而非重新训练模型
gbrt = GradientBoostingRegressor(max_depth=2, warm_start=True, random_state=42)
#一开始误差设置为无穷大
min_val_error = float("inf")
error_going_up = 0
for n_estimators in range(1, 120):
gbrt.n_estimators = n_estimators
gbrt.fit(X_train, y_train)
y_pred = gbrt.predict(X_val)
val_error = mean_squared_error(y_val, y_pred)
if val_error < min_val_error:
min_val_error = val_error
error_going_up = 0
else:
error_going_up += 1
if error_going_up == 5:
break # 新增五棵树后误差未改善,提前停止
最佳树的数目,是此时的gbrt.n_estimators-5
三、XGBT库
python提供了额外的XGBT库,其调用形式近似于scikitLearn,此库实现提前停止的代码为:
try:
import xgboost
except ImportError as ex:
xgboost = None
if xgboost is not None: 、
xgb_reg.fit(X_train, y_train,
#提前停止轮次为5
eval_set=[(X_val, y_val)], early_stopping_rounds=5)
y_pred = xgb_reg.predict(X_val)
val_error = mean_squared_error(y_val, y_pred) 、
print("Validation MSE:", val_error)