达观杯文本智能处理(5)

本文深入解析LightGBM模型的两大创新点:基于Histogram的决策树算法与Leaf-wise生长策略,对比XGBoost,强调其高效性、低内存消耗及高准确性。并通过实战案例,演示如何使用LightGBM进行多分类任务,包括数据预处理、模型训练、验证集评估及预测结果输出。

一、LightGBM模型

1、XGBoost缺点

每轮迭代时,都需要遍历整个训练数据多次。如果把整个训练数据装进内存则会限制训练数据的大小;如果不装进内存,反复地读写训练数据又会消耗非常大的时间。
预排序方法(pre-sorted):首先,空间消耗大。这样的算法需要保存数据的特征值,还保存了特征排序的结果(例如排序后的索引,为了后续快速的计算分割点),这里需要消耗训练数据两倍的内存。其次时间上也有较大的开销,在遍历每一个分割点的时候,都需要进行分裂增益的计算,消耗的代价大。
对cache优化不友好。在预排序后,特征对梯度的访问是一种随机访问,并且不同的特征访问的顺序不一样,无法对cache进行优化。同时,在每一层长树的时候,需要随机访问一个行索引到叶子索引的数组,并且不同特征访问的顺序也不一样,也会造成较大的cache miss。

2、LightGBM简介

LightGBM模型是一种boosting框架,包含两个关键点:light即轻量级,GBM 梯度提升机。它可以说是分布式的,高效的,有以下优势:

更快的训练效率
低内存使用
更高的准确率
支持并行化学习
可处理大规模数据

3、LightGBM的特点

基于Histogram的决策树算法
带深度限制的Leaf-wise的叶子生长策略
直方图做差加速
直接支持类别特征(Categorical Feature)
Cache命中率优化
基于直方图的稀疏特征优化
多线程优化

(1)Histogram算法
基本思想:先把连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图。遍历数据时,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。

(2)带深度限制的Leaf-wise的叶子生长策略
Level-wise过一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上Level-wise是一种低效算法,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销,因为实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。

Leaf-wise则是一种更为高效的策略:每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度。

Leaf-wise的缺点:可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度限制,在保证高效率的同时防止过拟合。

二、LightGBM参数

LightGBM参数包括:核心参数,学习控制参数,IO参数,目标参数,度量参数,网络参数,GPU参数,模型参数,这里常修改的便是核心参数,学习控制参数,度量参数等。

所有的参数含义,参考:http://lightgbm.apachecn.org/cn/latest/Parameters.html

调参过程:

num_leaves
LightGBM使用的是leaf-wise的算法,因此在调节树的复杂程度时,使用的是num_leaves而不是max_depth。

大致换算关系:numleaves=2(maxdepth)

样本分布非平衡数据集:可以param[‘is_unbalance’]=’true’

Bagging参数:bagging_fraction+bagging_freq(必须同时设置)、feature_fraction

min_data_in_leaf、min_sum_hessian_in_leaf

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import f1_score
import time
import pickle
import lightgbm as LGB
from sklearn.externals import joblib

t_start = time.time()
print("------------------程序开始---------------------")
"""=====================================================================================================================
0 自定义验证集的评价函数
"""
print("0 自定义验证集的评价函数")
def f1_score_vali(preds, data_vali):
    labels = data_vali.get_label()
    preds = np.argmax(preds.reshape(19, -1), axis=0)
    score_vali = f1_score(y_true=labels, y_pred=preds, average='macro')
    return 'f1_score', score_vali, True
"""=====================================================================================================================
1 读取数据,并转换到LGB的标准数据格式
"""
print("1 读取数据,并转换到LGB的标准数据格式")
data_fp = open('data_w_tfidf.pkl' , 'rb')
x_train, y_train, x_test = pickle.load(data_fp)
data_fp.close()
"""=====================================================================================================================
2 划分训练集和验证集,验证集比例为test_size
"""
print("划分训练集和验证集,验证集比例为test_size")
x_train, x_vali, y_train, y_vali = train_test_split(x_train, y_train, test_size=0.1, random_state=0)
d_train = LGB.Dataset(data=x_train, label=y_train)
d_vali = LGB.Dataset(data=x_vali, label=y_vali
"""=====================================================================================================================
3 训练LGB分类器
"""
print("3 训练LGB分类器")
params = {
    'boosting': 'gbdt',
    'application': 'multiclassova',
    'num_class': 19,
    'learning_rate': 0.1,
    'num_leaves': 31,
    'max_depth': -1,
    'lambda_l1': 0,
    'lambda_l2': 0.5,
    'bagging_fraction': 1.0,

}

bst = LGB.train(params, d_train, num_boost_round=800, valid_sets=d_vali, feval=f1_score_vali,
                early_stopping_rounds=None,
                verbose_eval=True)
joblib.dump(bst,"LGB_data_w_tfidf.m")
"""=====================================================================================================================
4 对测试集进行预测;将预测结果转换为官方标准格式;并将结果保存至本地
"""
print("4 对测试集进行预测;将预测结果转换为官方标准格式;并将结果保存至本地")
y_proba = bst.predict(x_test)
y_test = np.argmax(y_proba, axis=1) + 1

df_result = pd.DataFrame(data={'id': range(5000), 'class': y_test.tolist()})
df_proba = pd.DataFrame(data={'id': range(5000), 'proba': y_proba.tolist()})

df_result.to_csv('LGB_data_w_tfidf_result.csv', index=False)
df_proba.to_csv('LGB_data_w_tfidf_proba.csv', index=False)
t_end = time.time()
print("训练结束,耗时:{}min".format((t_end - t_start) / 60))

在这里插入图片描述
在这里插入图片描述
参考:https://blog.youkuaiyun.com/weixin_43314778/article/details/89289303
https://blog.youkuaiyun.com/ljfwz153076024/article/details/89075945
https://blog.youkuaiyun.com/u012736685/article/details/89289139

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值