算法流程
xi = np.arange(1,11)
yi = np.array([0,0,0,1,1]*2)
display(xi,yi)
改变形状
#一个参数为-1时,那么reshape函数会根据另一个参数的维度计算出数组的另外一个shape属性值。
xi.reshape(-1,1)
算法
gbdt = GradientBoostingClassifier(n_estimators=3,max_depth=1)
gbdt.fit(xi.reshape(-1,1),yi)
第一颗决策树构建
plt.figure(figsize=(9,6))
_ = tree.plot_tree(gbdt[0,0],filled=True)
计算
F0 = np.log(4/6)
F0
𝑦˜𝑖
# 残差,概率,负梯度
yi_1 = yi - 1/(1 + np.exp(-F0))
yi_1
计算每个分裂点
# 计算每个裂分点mse
mse1 = []
for i in range(1,11):
if i == 10:
mse1.append(np.var(yi_1))
else:
mse1.append((np.var(yi_1[:i])*i + np.var(yi_1[i:])*(10 - i))/10)
print(np.round(mse1,4))
mse1 = np.asarray(mse1)
gamma预测值
代码实现
# 两个分支,左边这个分支预测值
np.round(yi_1[:8].sum()/(((yi[:8] - yi_1[:8])*(1 - yi[:8] + yi_1[:8])).sum()),3)
另一个分支
np.round(yi_1[8:].sum()/(((yi[8:] - yi_1[8:])*(1 - yi[8:] + yi_1[8:])).sum()),3)
# 第一颗数据预测的值
y_1 = [-0.625]*8 + [2.5]*2
y_1
预测
gbdt[0,0].predict(xi.reshape(-1,1))
由此可看,数据一致。
更新概率
代码实现
# 学习率 learning_rate = 0.1
F1 = F0 + y_1*0.1
F1.round(4)
再求负梯度
# 残差,概率,负梯度
yi_2 = yi - 1/(1 + np.exp(-F1))
yi_2.round(4)
拟合第二颗树
# 计算每个裂分点mse
mse2 = []
for i in range(1,11):
if i == 10:
mse2.append(np.var(yi_2))
else:
mse2.append((np.var(yi_2[:i])*i + np.var(yi_2[i:])*(10 - i))/10)
print(np.round(mse2,4))
mse2 = np.asarray(mse2)
# mse2
第二棵树画图
plt.figure(figsize=(9,6))
_ = tree.plot_tree(gbdt[1,0],filled=True)
# 两个分支,左边这个分支预测值
np.round(yi_2[:8].sum()/(((yi[:8] - yi_2[:8])*(1 - yi[:8] + yi_2[:8])).sum()),3)
# 两个分支,左边这个分支预测值
np.round(yi_2[8:].sum()/(((yi[8:] - yi_2[8:])*(1 - yi[8:] + yi_2[8:])).sum()),3)
剩下的都是重复工作了。