24/8/11算法笔记 梯度回归树最佳分裂条件计算

Bagging(套袋法)的核心在于自助采样(bootstrap)/随机采样这一概念,即从数据集中进行有放回采样,也就是说,同样的一个样本可能被多次进行采样

举例说明:

估计全国所有人口年龄的平均值:可在全国所有人口中随机抽取不同的集合(这些集合可能存在交集),计算每个集合的平均值,然后将所有平均值的均值作为估计值。

Bagging的基本流程:

首先随机取出一个样本放入采样集合中,再把这个样本放回初始数据集,重复K次采样,最终可获得一个大小为K的样本集合。

同样的方法,也可以采样出T个含K个样本的采样集合,然后基于每个采样集合训练出一个基学习器,再将这些基学习器进行结合。

回归问题的预测:通过预测取平均值来进行。

分类问题的预测:通过对预测取多数票预测来进行。

Bagging方法之所以有效,是因为每个模型都是在略微不同的训练数据集上拟合完成的,这又使得每个基模型之间存在略微的差异,使每个基模型拥有略微不同的训练能力。

Bagging同样是一种降低方差的技术,因此它在不剪枝决策树、神经网络等易受样本扰动的学习器上效果更加明显。在实际的使用中,加入列采样的Bagging技术对高维小样本往往有神奇的效果。

Bagging套袋法演示

import numpy as np
from sklearn.neighbors import KNeighborsClassifier #KNN集成
from sklearn.ensemble import BaggingClassifier
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier

X,y=datasets.load_wine(return_X_y=True)
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state =1024)

knn=KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train,y_train)
score = knn.score(X_test,y_test)
print('单一的KNN算法,预测准确率是:',score)

bag = BaggingClassifier(base_estimator=KNeighborsClassifier(),
                        n_estimators=100,
                        max_samples=0.8,#随机抽样
                        max_features=0.8)
bag.fit(X_train,y_train)
score2=bag.score(X_test,y_test)
print('100个KNN构建了集成算法,预测准确率是:',score2)

2决策树

clf = DecisionTreeClassifier()
clf.fit(X_train,y_train)
print('单决策树,得分是',clf.score(X_test,y_test))

#相当于随机森林
bag = BaggingClassifier(base_estimator=DecisionTreeClassifier(),n_estimators=100,
                        max_samples=0.1,
                        max_features=0.5)
bag.fit(X_train,y_train)
print('决策树集成算法,得分是:',bag.score(X_test,y_test))

from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(max_samples=0.9,max_features=0.5)
clf.fit(X_train,y_train)
print('原生的集成算法随机森林,得分是:',clf.score(X_test,y_test))

2GBDT梯度提升回归树应用

天池平台工业蒸汽量预测数据

全部特征数据

from sklearn.ensemble import GradientBoostingRegressor
import numpy as np
import pandas as pd
#加载数据
data_train = pd.read_csv('zhengqi_train.txt',sep='\t')
data_test = pd.read_csv('zhengqi_test.txt',sep='\t')
X_train = data_train.iloc[:,:-1]
y_train = data_train['target']
X_test=data_test

#GBDT模型训练预测
gbdt = GradientBoostingRegressor()
gbdt.fit(X_train,y_train)
y_pred = gbdt.predict(X_test)
np.savetxt('GBDT_full_feature_result.txt',y_pred)
部分特征数据
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.linear_model import ElasticNet
import numpy as np
import pandas as pd
#加载数据
data_train = pd.read_csv('zhengqi_train.txt',sep='\t')
data_test = pd.read_csv('zhengqi_test.txt',sep='\t')
X_train = data_train.iloc[:,:-1]
y_train = data_train['target']
X_test=data_test

#先使用ElaticNet模型进行数据筛选
model = ElasticNet(alpha = 0.1,l1_ratio=0.05)
model.fit(X_train,y_train)
#条件过滤,将系数是0的剔除
cood=model.coef_!=0
X_train = X_train.iloc[:,cood]
X_test = X_test.iloc[:,cood]
print('删除数据后,形状是:',X_train.shape)

#GBDT模型训练数据

gbdt = GradientBoostingRegressor()
gbdt.fit(X_train,y_train)
y_pred = gbdt.predict(X_test)
np.savetxt('GBDT_full_feature_result.txt',y_pred)
归一化
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.preprocessing import StandardScaler#归一化
import numpy as np
import pandas as pd
#加载数据
data_train = pd.read_csv('zhengqi_train.txt',sep='\t')
data_test = pd.read_csv('zhengqi_test.txt',sep='\t')


X_train = data_train.iloc[:,:-1]
y_train = data_train['target']
X_test=data_test

#对数据进行归一化
ss = StandardScaler()
X_train = ss.fit_transform(X_train)
X_test = ss.transform(X_test)

#GOBDT模型训练预测

gbdt = GradientBoostingRegressor()
gbdt.fit(X_train,y_train)
y_pred = gbdt.predict(X_test)
np.savetxt('GBDT_full_feature_result.txt',y_pred)

梯度提升回归树原理

import numpy as np
from sklearn.ensemble import GradientBoostingRegressor
import matplotlib.pyplot as plt
from sklearn import tree
import graphviz

###实际问题年龄预测,回归问题
#简单的数据,算法原理,无论简单数据,还是复杂数据都一样
#属性一表示花俏,属性二表示上网时间
X = np.array([[600,0.8],[800,1.2],[1500,10],[2500,3]])
y = np.array([14,16,24,26])

#loss=ls最小二乘法
learning_rate = 0.1
gbdt = GradientBoostingRegressor(n_estimators=3,loss='squared_error',#最小二乘法
                                 learning_rate=0.1)#learning_rate学习率
gbdt .fit(X,y)#训练
y_=gbdt.predict(X)#预测
y_
array([18.374, 18.916, 21.084, 21.626])

可视化第一棵树

nd = np.random.randint(0,10,size=(2,3))
nd

gbdt[0][0]

#gbdt是一个二维的数组
dot_data = tree.export_graphviz(gbdt[0,0],filled=True,rounded=True)
graphviz.Source(dot_data)

#回归问题,初始值
F0=y.mean()
residual_0 = y-F0
residual_0

#mse可以使用真实减去真实值的平均值,计算
((y - y.mean())**2).mean()

第二棵树可视化
#gbdt是一个二维的数组
dot_data = tree.export_graphviz(gbdt[1,0],filled=True,rounded=True)
graphviz.Source(dot_data)

residual_1 = residual_0-learning_rate*residual_0
residual_1

((residual_1 - residual_1.mean())**2).mean()
21.060000000000002
第三棵树可视化
#gbdt是一个二维的数组
dot_data = tree.export_graphviz(gbdt[2,0],filled=True,rounded=True)
graphviz.Source(dot_data)

residual_2=residual_1-learning_rate*residual_1
residual_2

#最后一棵树的残差
residual_3 = residual_2-learning_rate*residual_2
residual_3

y_=gbdt.predict(X)#预测
y_
array([18.374, 18.916, 21.084, 21.626])
#预测值=实际值-残差
y_pred = y-residual_3
y_pred

最佳裂分条件计算

dot_data = tree.export_graphviz(gbdt[0,0],filled=True,rounded=True)
graphviz.Source(dot_data)

第一棵树最佳裂分条件计算
lower_mse = ((y-y.mean())**2).mean()

best_split = {}

for index in range(2):#数据x是两个属性
    for i in range(3):#数据量是4个,索引分裂时候,3份
        t = X[:,index].copy()
        t.sort()#排序
        split = t[i:i+2].mean()
        cond = X[:,index]<=split   #满足分裂条件的数据
        y_left = y[cond]
        y_right = y[~cond]
        mse_left = ((y_left - y_left.mean())**2).mean()
        mse_right = ((y_right - y_right.mean())**2).mean()
        
        #求整体的均方误差
        p = cond.sum()/cond.size
        mse = mse_left+mse_right * (1-p)
        print('第%d列,裂分条件是%0.2f,均方误差是%0.2f' %(index,split,mse))
        
        if mse<lower_mse:
            best_split.clear()
            best_split['第%d列'] = split
            lower_mse = mse
        elif mse ==lower_mse:#说明存在相同的最佳裂分条件
            best_split['第%d列'%(index)]=split
print('---------------------',best_split)
            
        

第二棵树的最佳裂分条件
residual = y-y.mean()
residual = residual-learning_rate*residual
residual

lower_mse = ((residual - residual.mean())**2).mean()
lower_mse
21.060000000000002
dot_data = tree.export_graphviz(gbdt[1,0],filled = True,rounded=True)
graphviz.Source(dot_data)

lower_mse = ((residual-residual.mean())**2).mean()
best_split = {}

for index in range(2):#数据x是两个属性
    for i in range(3):#数据量是4个,索引分裂时候,3份
        t = X[:,index].copy()
        t.sort()#排序
        split = t[i:i+2].mean()
        cond = X[:,index]<=split   #满足分裂条件的数据
        y_left = residual[cond]
        y_right = residual[~cond]
        
        mse_left = ((y_left - y_left.mean())**2).mean()
        mse_right = ((y_right - y_right.mean())**2).mean()
        
        #求整体的均方误差
        p = cond.sum()/cond.size
        mse = mse_left+mse_right * (1-p)
        print('第%d列,裂分条件是%0.2f,均方误差是%0.2f' %(index,split,mse))
        
        if mse<lower_mse:
            best_split.clear()
            best_split['第%d列'] = split
            lower_mse = mse
        elif mse ==lower_mse:#说明存在相同的最佳裂分条件
            best_split['第%d列'%(index)]=split
print('---------------------',best_split)
            
        

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值