(八)集成学习之GBDT与python代码实现

学习笔记参考:https://www.ccs.neu.edu/home/vip/teach/MLcourse/4_boosting/slides/gradient_boosting.pdf

全英文PPT,但是这是我挣扎几天后看过最通俗易懂的讲解了,打不开可以私聊我。

知识点:

  • Gradient Boosting Decision Tree:梯度提升决策树
  • 无论是回归还是分类,都是采用CART树
  • 策略:会用第K个CART树拟合前K-1个CART树留下的残差,从而不断缩小整个模型的误差
  • 但在在更一般的情况下,使用负梯度 better than 残差
  • 所以GBDT每轮的训练是在上一轮训练模型的负梯度值基础上训练的,即用负梯度近似模拟残差,这是GBDT的核心
  • 当Loss function 采用均方误差时,-\frac{\partial J}{\partial F(x_i)} = y_i-F(x_i),所以负梯度<=>残差
  • 损失函数采用均方误差的优缺点
    • 优点很容易用数学方法处理
    • 缺点对异常值不稳健异常值容易受到严厉惩罚,因为误差是平方的,它会努力将离群值合并到模型中,降低整体性能
  • 下表是采用不同损失函数计算出来的误差值,5为异常点,可以很明显看到均方误差对异常值不稳健,绝对损失函数和Huber损失函数数值更小,更具有鲁棒性。

(八)集成学习之GBDT与python代码实现_第1张图片

  • 使用负梯度代替残差的好处
    • 可以考虑使用均方误差以外的损失函数,均方误差对异常值不稳健
    • 所以负梯度存在的意义可以理解成损失函数可以往更丰富的场景下扩展
    • 并以相同的方式推导出相应的算法
  • 针对任意损失函数的算法流程

(八)集成学习之GBDT与python代码实现_第2张图片

  • 负梯度只能近似模拟残差为何还要使用负梯度:下图以huber损失函数为例进行说明:可以看到,当残差大于\delta后,采用负梯度拟合的huber对异常点不敏感!

(八)集成学习之GBDT与python代码实现_第3张图片

  • 和梯度下降法的关系:

  • F(x_i) := F(x_i) + h(x_i)

    F(x_i) := F(x_i) + y_i-F(x_i)

    F(x_i) := F(x_i) + 1\frac{\partial J}{\partial F(x_i)}

    \theta _j: = \theta_j - \rho \frac{\partial J}{\partial \theta_j}

    (八)集成学习之GBDT与python代码实现_第4张图片

GBDT与RF的区别:来自GBDT的原理、公式推导、Python实现、可视化和应用 - 知乎

python工具包实现

数据集:https://archive.ics.uci.edu/ml/machine-learning-databases/undocumented/connectionist-bench/sonar/

import csv
from sklearn.model_selection import train_test_split
#先导入我们需要的库
import numpy as np
import pandas as pd
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier #决策树

'''加载数据,一行行的存入列表'''
def loadCSV(filename):
    dataSet = []
    with open(filename, 'r') as file:
        csvReader = csv.reader(file)
        for line in csvReader:
            dataSet.append(line)
    return dataSet
dataSet = loadCSV('/Users/Downloads/sonar_all_data.csv')


'''处理数据,除了标签列,其他列都转换为float类型'''
def column_to_float(dataSet):
    featLen = len(dataSet[0]) - 1
    for data in dataSet:
        for column in range(featLen):
            data[column] = float(data[column].strip())
column_to_float(dataSet)


'''划分数据集7:3'''
X = []
Y = []
for i in dataSet:
    x= i[:-1]
    y = i[-1]
    Y.append(y)
    X.append(x)
X_train, X_test, y_train, y_test = train_test_split(X,Y, test_size=0.3)

clas = GradientBoostingClassifier(random_state=2020)#我们用的默认参数,如果数据比较复杂,需要调参
clas.fit(X_train,y_train)#训练模型
# clas.predict(X_train)#预测训练集
score_clas = clas.score(X_test,y_test)#预测测试集
# print("训练集准确率:%s"%clas.score(X_train,y_train)) #输出测试集准确度
print("GBDT准确率:%s"%score_clas)   #输出测试集准确度

输出:

GBDT准确率:0.8412698412698413

你可能感兴趣的:(数据挖掘学习笔记,python,数据挖掘,算法,机器学习)