集成学习——梯度提升法GDBT(机器学习)

目录

一、实验内容

二、实验过程

1、算法思想:

2、算法原理

3、算法分析

三、源程序代码

四、实验总结



集成学习——梯度提升法GDBT(机器学习)_第1张图片

一、实验内容


  1. 熟知集成学习方法的概念和基本算法思想;
  2. 掌握梯度提升法的算法原理;
  3. 掌握梯度提升法的设计及Python实现。

二、实验过程


1、算法思想:


        梯度提升决策树,是一种迭代决策树算法,主要用于回归,经过改进过也可用于实现分类任务。GBDT的实现思想是构建多棵决策树,并将所有决策树的输出结果进行综合,得到最终的结果。

2、算法原理


        GBDT算法的构建过程与分类决策树类似

        主要区别在于回归树节点的数据类型为连续型数据,每一个节点均有一个具体数值,此数值是该叶子节点上所有样本数值的平均值。

        同时,衡量每个节点的每个分支属性表现,不再使用熵,信息增益或Gini指标等纯度指标,而是通过最小化每个节点的损失函数值来进行表示每个节点的分裂。

3、算法分析


(1)初始化决策树,估计一个使损失函数最小化的常数构建一个只有根节点的树。

(2)不断提升迭代

1、计算当前模型中损失函数的负梯度值,作为残差的估计值。

2、估计回归树中叶子节点的区域,拟合残差的近似值;

3、利用线性搜索估计叶子节点区域的值,使损失函数极小化。

4、更新决策树。

 (3)经过若干轮的提升法迭代过程之后,输出最终的模型。

三、源程序代码


import numpy as np
from sklearn import datasets
import sys
 
class Gx:
    def __init__(self,feature,split,left,right):
        #一个分布 这个分布是以哪个feature 作为划分的 划分点 split是 这个分布的系数是coef
         self.feature=feature
         self.split= split
         self.left =left#小于切分点的值为多少
         self.right = right #大于切分点的值为多少
class GDBT:
    def __init__(self,Train,Test,e):
        self.Train=Train #训练集
        self.Test=Test #测试集
        self.feature_num = self.Train.shape[1] - 2  # 求特征个数 因为训练数据的最后一列是标签 所以特征数等于维度数减一
        self.label = self.Train.shape[1] - 2  # 标签所在列
        self.r = self.Train.shape[1] - 1  # 残差所在列
        self.Gx=[] #基分类器
        #self.M = M #迭代次数
        self.e=e # 阈值 在训练数据的损失函数值小于e时停止训练
        self.split = self.cal_split()
 
    def cal_split(self):
        # 因为数据的特征都是连续值 计算每一个特征的切分点 每两个数据的中点集合作为这个特征的切点集合
        split = {}
        for i in range(self.feature_num):
            split[i] = []  # 将某一个特征的所有切分点放到一个列表中
            d = self.Train[np.argsort(self.Train[:, i])]  # 以这个特征的大小来进行排序
            for j in range(d.shape[0] - 1):
                sp = (d[j][i] + d[j + 1][i]) / 2
                if sp not in split[i]:  # 可能有的切分点是重复的 这一步去重
                    split[i].append(sp)
        return split
 
    def cost(self, data): #求损失值
        X = data[:, self.r:self.r + 1]
        avg = np.sum(X) / X.shape[0]  # 平均值
        sum = 0
        for i in range(X.shape[0]):
            sum += (X[i][0] - avg) ** 2
        return sum,avg
 
    def update_r(self,G): #更新残差值
        feature=G.feature
        split=G.split
        left=G.left
        right=G.right
        for i in range(self.Train.shape[0]):
            if self.Train[i][feature]  <= split:
                self.Train[i][self.r]=self.Train[i][self.r]-left
            else:
                self.Train[i][self.r] = self.Train[i][self.r] - right
 
    def cal_best_split(self):
        min_cost=sys.maxsize
        min_split=0
        min_feature=0
        min_left=0
        min_right=0
        #选择最佳特征,以及最佳切分点
        for i in range(self.feature_num):  # 遍历所有特征取值
             for j in self.split[i]:#遍历每一个切分点
                 left = self.Train[(self.Train[:, i] <= j), :]
                 right = self.Train[(self.Train[:, i] > j), :]
                 cost1,avg1=self.cost(left)
                 cost2,avg2=self.cost(right)
                 # print(cost1)
                 # print(cost2)
                 # print("******")
                 if cost1+cost2 < min_cost:
                     min_cost= cost1+cost2
                     min_feature=i
                     min_split=j
                     min_left=avg1
                     min_right=avg2
        G=Gx(min_feature,min_split,min_left,min_right)
        self.update_r(G)
        self.Gx.append(G)
 
    def fit(self):
        L=sys.maxsize
        while L>self.e:
            self.cal_best_split()
            print("当前损失值:")
            L=self.cal_cost(self.Train)
            print(L)
            print("***************")
 
    def print_Gx(self):
        for gx in self.Gx:
            print("特征:")
            print(gx.feature)
            print("切分点")
            print(gx.split)
            print("左值")
            print(gx.left)
            print("右值")
            print(gx.right)
            print("******************************")
 
    def cal_cost(self,data):
        L=0#预测损失值
        for i in range(data.shape[0]):
            sum=0# 预测值
            for gx in self.Gx:
                feature=gx.feature
                split=gx.split
                left=gx.left
                right=gx.right
                if data[i][feature] <=split:
                    sum+=left
                else:
                    sum+=right
            L+=(data[i][self.label]-sum)**2
        return L
 
boston=datasets.load_boston()
data1=boston.data
print(data1.shape)
data2=boston.target
data2.resize([data2.shape[0],1])
data3=np.concatenate((data1,data2), axis=1)
data=np.concatenate((data3,data2), axis=1)
print(data.shape)
print(data)
train_size = int(len(data) * 0.7)#划分训练集与测试集
train = np.array(data[:train_size])
# # print(X_train.shape)
test=np.array(data[train_size:])
model=GDBT(train,test,100)
model.fit()

四、实验总结


        相比较单一算法,集成算法的效果更好。GBDT是一种boosting形式的集成算法,通断不断的优化残差值,最后达到一个非常好的效果

你可能感兴趣的:(机器学习,机器学习,集成学习,python)