锂离子电池生产参数调控及生产温度预测挑战赛笔记

题目背景及思路

锂离子电池生产参数调控及生产温度预测挑战赛是2023 iFLYTEK A.I.开发者大赛中的一个子竞赛。

原题的链接为2023 iFLYTEK A.I.开发者大赛-讯飞开放平台 (xfyun.cn)​​​​​​

赛题实质上为回归任务,通过电炉空间温度推测产品内部温度,设计烧结过程的温度场和浓度场的最优控制律:

  • 任务输入:电炉对应17个温区的实际生产数据,分别是电炉上部17组加热棒设定温度T1-1~T1-17,电炉下部17组加热棒设定温度T2-1~T2-17,底部17组进气口的设定进气流量V1-V17;

  • 任务输出:电炉对应17个温区上部空间和下部空间17个测温点的测量温度值。

可使用机器学习模型解决本项目。

1.Baseline

Datawhale举办的2023年暑期AI夏令营提供了本次比赛的baseline。详见AI夏令营 - 飞书云文档 (feishu.cn)

1.1导入所需的库

示例代码

import pandas as pd    #读取和处理csv文件的数据
import lightgbm as lgb    #机器学习模型LightGBM
from sklearn.metrics import mean_absolute_error    #从sklearn.metrics导入回归问题的评价指标平均绝对误差(MAE)的计算函数
from sklearn.model_selection import train_test_split    #拆分训练集与验证集的工具
from tqdm import tqdm    #显示循环的进度条工具

pandas

Pandas是一个Python数据处理库,用于处理和分析结构化数据,提供了灵活的数据结构和功能强大的工具,简化了数据清洗、预处理和分析的过程。它支持数据的导入、清洗、转换、聚合、统计计算和数据可视化。

lightgbm

LightGBM是一个高效的机器学习库,用于梯度提升树模型(Gradient Boosting Decision Tree)。它的设计目标是在大规模数据集上实现高性能,具有较快的训练速度和较低的内存占用。LightGBM广泛用于分类、回归和排序等机器学习任务,尤其适用于处理高维稀疏数据和大规模数据集。

sklearn

Scikit-learn(sklearn)是一个强大的Python机器学习库,用于构建、训练和评估各种机器学习模型。它提供了丰富的算法和工具,用于分类、回归、聚类、降维等任务。Scikit-learn还包含数据预处理、特征工程、模型选择和评估等功能,适用于解决数据挖掘、数据分析和预测建模等多种数据科学问题。 

sklearn.metrics

sklearn.metrics是Scikit-learn库中的一个模块,用于评估机器学习模型的性能和准确度。它提供了一系列常用的性能指标,如MAE、准确率、召回率、F1-score等,用于评估分类和回归模型的预测效果。该模块还支持绘制ROC曲线、学习曲线和混淆矩阵等工具,有助于进行模型选择和调优。

sklearn.model_selection

sklearn.model_selection是Scikit-learn库中的一个模块,用于模型选择和评估的工具集合。它提供了交叉验证、参数调优、数据集划分等功能,帮助用户选择最佳的机器学习模型和参数组合,防止过拟合,并提高模型的泛化能力。这个模块在训练机器学习模型时起到了至关重要的作用,帮助用户更好地优化模型性能和可靠性。

tqdm

tqdm用于在循环迭代过程中添加进度条,方便用户实时了解代码的执行进度。它适用于各种循环结构,如for循环和while循环,以及其他迭代操作,使得处理大规模数据或耗时任务时可以直观地查看任务的完成情况。tqdm的简单接口和实用功能使其成为了数据处理、训练模型等任务中常用的进度条工具。

1.2数据准备

示例代码

train_dataset = pd.read_csv("./data/train.csv") # 原始训练数据。
test_dataset = pd.read_csv("./data/test.csv") # 原始测试数据(用于提交)。

submit = pd.DataFrame() # 定义提交的最终数据。
submit["序号"] = test_dataset["序号"] # 对齐测试数据的序号,保持与原始测试数据的一致性。

MAE_scores = dict() # 定义评分项。

print(train_dataset[:3][:]) # 查看训练集的前三行

运行结果

   序号              时间        流量1        流量2        流量3     流量4        流量5  \
0   1  2022/11/6 9:08  35.668999  36.146000  25.558001  26.195  25.670000   
1   2  2022/11/6 9:09  35.995998  36.347000  25.382000  26.348  26.131001   
2   3  2022/11/6 9:11  35.340000  36.311001  25.469999  26.093  25.639000   

      流量6        流量7     流量8  ...  下部温度8  下部温度9  下部温度10  下部温度11  下部温度12  \
0  15.702  16.690001  15.991  ...    827    827     827     827     827   
1  15.523  16.825001  15.871  ...    827    827     827     827     827   
2  15.564  15.564000  15.947  ...    827    827     827     827     827   

   下部温度13  下部温度14  下部温度15  下部温度16  下部温度17  
0     827     827     827     827     750  
1     827     827     827     827     750  
2     827     827     827     827     750  

[3 rows x 87 columns]

因为本项目要求我们对上部的17个温度和下部的17个温度进行预测,所以训练集的最后34列是需要预测的目标变量,除去“序号”一列后的其他变量则是特征变量。

1.3模型参数设置

示例代码

pred_labels = list(train_dataset.columns[-34:]) #训练数据集的最后34列是需要预测的目标变量。
train_set, valid_set = train_test_split(train_dataset, test_size=0.2) # 拆分数据集,

# 设定 LightGBM 训练参,查阅参数意义:https://lightgbm.readthedocs.io/en/latest/Parameters.html
lgb_params = {
        'boosting_type': 'gbdt',     #使用的提升方法,使用梯度提升决策树gbdt。
        'objective': 'regression',   #优化目标,这里设置为'regression',表示使用回归任务进行优化。
        'metric': 'mae',             #评估指标,使用MAE,表示使用平均绝对误差作为评估指标。
        'min_child_weight': 5,       #子节点中样本权重的最小和,用于控制过拟合。
        'num_leaves': 2 ** 5,        #每棵树上的叶子节点数,影响模型的复杂度。
        'lambda_l2': 10,             #L2正则化项的权重,用于控制模型的复杂度。
        'feature_fraction': 0.8,     #随机选择特征的比例,用于防止过拟合。
        'bagging_fraction': 0.8,     #随机选择数据的比例,用于防止过拟合。
        'bagging_freq': 4,           # 随机选择数据的频率,用于防止过拟合。
        'learning_rate': 0.05,       #学习率,控制每次迭代的步长。
        'seed': 2023,                #随机种子,用于产生随机性,保持结果的可重复性。
        'nthread' : 16,              #并行线程数,用于加速模型训练。
        'verbose' : -1,              #控制训练日志输出,-1表示禁用输出。
    }
    #调整参数是优化模型性能的重要手段

no_info = lgb.callback.log_evaluation(period=-1) # 回调函数no_info:禁用训练日志输出。
#LightGBM通常会输出一些训练过程的信息,通过回调函数可以避免输出这些信息,使得训练过程更简洁。

1.4时间特征提取

示例代码

# 定义时间特征函数
def time_feature(data: pd.DataFrame, pred_labels: list = None) -> pd.DataFrame:
    """提取数据中的时间特征。

    输入:
        data: Pandas.DataFrame
            需要提取时间特征的数据。

        pred_labels: list, 默认值: None
            需要预测的标签的列表。如果是测试集,不需要填入。

    输出: data: Pandas.DataFrame
            提取时间特征后的数据。
    """
    # 接收数据集DataFrame和可选参数pred_labels,返回处理后的DataFrame

    data = data.copy()  # 复制数据,避免后续影响原始数据。
    data = data.drop(columns=["序号"])  # 去掉”序号“特征。

    data["时间"] = pd.to_datetime(data["时间"])  # 将”时间“特征的文本内容转换为 Pandas 可处理的格式。
    data["month"] = data["时间"].dt.month  # 添加新特征“month”,代表”当前月份“。
    data["day"] = data["时间"].dt.day  # 添加新特征“day”,代表”当前日期“。
    data["hour"] = data["时间"].dt.hour  # 添加新特征“hour”,代表”当前小时“。
    data["minute"] = data["时间"].dt.minute  # 添加新特征“minute”,代表”当前分钟“。
    data["weekofyear"] = data["时间"].dt.isocalendar().week.astype(int)  # 添加新特征“weekofyear”,代表”当年第几周“,
    # 并转换成 int整数类型,否则 LightGBM 无法处理。
    data["dayofyear"] = data["时间"].dt.dayofyear  # 添加新特征“dayofyear”,代表”当年第几日“。
    data["dayofweek"] = data["时间"].dt.dayofweek  # 添加新特征“dayofweek”,代表”当周第几日“。
    data["is_weekend"] = data["时间"].dt.dayofweek // 6  # 添加新特征“is_weekend”,代表”是否是周末“,1 代表是周末,0 代表不是周末。

    data = data.drop(columns=["时间"])  # LightGBM 无法处理这个特征,它已体现在其他特征中,故丢弃。

    if pred_labels:  # 如果提供了 pred_labels 参数,则执行该代码块。
        data = data.drop(columns=[*pred_labels])  # 去掉所有待预测的标签。在模型训练时不使用这些标签。

    return data  # 返回最后处理的数据。


test_features = time_feature(test_dataset)  # 处理测试集的时间特征,无需 pred_labels。
test_features.head(5) # 打印前五行

运行结果

流量1流量2流量3流量4流量5流量6流量7流量8流量9流量10...下部温度设定16下部温度设定17monthdayhourminuteweekofyeardayofyearday of weekis_weekend
024.22200024.07000028.88900025.26499926.8279994.35421.78424.32300016.72100118.652000...8377503141596020
124.13800023.97400128.79800025.51700027.1089994.37721.88624.38400116.70999918.600000...8377503142096020
224.15200024.00600128.82799925.11400026.7199994.29321.61124.09900116.59199918.471001...8377503142696020
324.10899923.97400128.78300125.11400027.0470014.35421.85724.33799916.67799918.561001...8377503143196020
424.35000024.21500029.14699925.41600025.4160004.37721.90024.44400016.77599918.704000...8377503143696020

5 rows × 59 columns

1.5训练与预测

示例代码

# 从所有待预测特征中依次取出标签进行训练与预测。
for pred_label in tqdm(pred_labels):
    #print("当前的pred_label是:", pred_label)
    train_features = time_feature(train_set, pred_labels=pred_labels)  # 处理训练集的时间特征。
    # 调用time_feature函数处理训练集train_set的时间特征,并将处理后的训练集数据赋值给train_features

    train_labels = train_set[pred_label]  # 训练集的标签数据。
    #print("当前的train_labels是:", train_labels)
    # 获取当前特征标签pred_label在训练集中的真实值,并赋值给train_labels。

    train_data = lgb.Dataset(train_features, label=train_labels)  # 将训练集转换为 LightGBM 可处理的类型。
    # 将train_features和train_labels转换为LightGBM可处理的数据类型,创建训练数据集train_data。

    valid_features = time_feature(valid_set, pred_labels=pred_labels)  # 处理验证集的时间特征。
    # 调用time_feature函数处理验证集valid_set的时间特征,并将处理后的验证集数据赋值给valid_features。

    valid_labels = valid_set[pred_label]  # 验证集的标签数据。
    #print("当前的valid_labels是:", valid_labels)
    # 获取当前特征标签pred_label在验证集中的真实值,并赋值给valid_labels。

    valid_data = lgb.Dataset(valid_features, label=valid_labels)  # 将验证集转换为 LightGBM 可处理的类型。

    # 训练模型,参数依次为:导入模型设定参数、导入训练集、设定模型迭代次数(5000)、导入验证集、禁止输出日志
    model = lgb.train(lgb_params, train_data, 5000, valid_sets=valid_data, callbacks=[no_info])

    valid_pred = model.predict(valid_features, num_iteration=model.best_iteration)  # 选择效果最好的模型进行验证集预测。
    test_pred = model.predict(test_features, num_iteration=model.best_iteration)  # 选择效果最好的模型进行测试集预测。
    MAE_score = mean_absolute_error(valid_pred, valid_labels)  # 计算验证集预测数据与真实数据的 MAE。
    MAE_scores[pred_label] = MAE_score  # 将对应标签的 MAE 值 存入评分项中。

    submit[pred_label] = test_pred  # 将测试集预测数据存入最终提交数据中。

    print(MAE_scores) # 查看各项的MAE值
    print(sum(MAE_scores.values())) # 查看MAE总和

 运行结果

100%|██████████████████████████████████████████████████████████████████████████████████| 34/34 [04:59<00:00,  8.82s/it]
{'上部温度1': 3.0007354204561403, '上部温度2': 2.8769845360473867, '上部温度3': 2.1331975731835926, '上部温度4': 1.496321896163088, '上部温度5': 1.7414880068987442, '上部温度6': 1.6522228703240565, '上部温度7': 1.062672203970032, '上部温度8': 0.15500730578287003, '上部温度9': 0.08802446117671768, '上部温度10': 0.0799846388226232, '上部温度11': 0.10613279409730655, '上部温度12': 0.11317730155973206, '上部温度13': 0.12038375264220602, '上部温度14': 0.16357750552491948, '上部温度15': 0.2736541311741262, '上部温度16': 0.35155734632815766, '上部温度17': 0.8035987916809865, '下部温度1': 2.244238251563849, '下部温度2': 1.3729720288294205, '下部温度3': 0.7246732497275274, '下部温度4': 0.42613780618053937, '下部温度5': 0.7370350707972151, '下部温度6': 0.5115162092478198, '下部温度7': 0.3022968269132582, '下部温度8': 0.09583816784017218, '下部温度9': 16.569409135821726, '下部温度10': 0.08869039580783693, '下部温度11': 0.14689112119248152, '下部温度12': 0.15972231603079792, '下部温度13': 0.15577821738687878, '下部温度14': 0.14749604309107325, '下部温度15': 0.232563376644599, '下部温度16': 0.30401002849671765, '下部温度17': 0.3687768162154011}
40.80676559762

1.6保存文件

示例代码

submit.to_csv("submit_result.csv", index=False)  # 保存最后的预测结果到 submit_result.csv,可以自定义路径,如果按照本行代码,则该文件保存在同目录的文件夹中,文件名为submit_result.csv.

2.模型优化

2.1优化思路

笔者采用的baseline的优化思路具体有以下几个方面:

  1. 改变test_size的值
  2. 设定表现更好的LightGBM参数
  3. 改变模型迭代次数
  4. 提取更多特征
  5. 选取其他的boosting_type如Dart和随机森林(RF)

可以通过观察改变以上三类参数的值各项MAE的值大致判断模型的优劣,一般来说,MAE越小,模型的拟合优度越高。但由于赛事主办方提供的训练数据集和最终用于评分的数据集不同,训练过程中会产生过拟合导致更小的MAE值却跑出更差的分数。因此MAE对于我们建立的模型优劣程度的评估有一定局限性。

 为了确定合适的超参数,可以采用贝叶斯优化的方法。

贝叶斯优化是一种用于全局优化的概率建模和优化方法。它在寻找目标函数的最优解时,通过不断地选择具有较高可能性的参数值来指导搜索过程,从而高效地找到全局最优解或接近最优解的点。

2.2导入所需的库

示例代码

from skopt import gp_minimize
from skopt.space import Real, Categorical, Integer

scikit-optimize(skopt)

scikit-optimize(skopt)是一个用于进行贝叶斯优化的python库。它可以帮助解决复杂问题的参数调优、超参数优化和全局最优化任务。通过高效的贝叶斯优化算法,skopt能够在黑盒函数或不可导的情况下寻找全局最优解,并加速模型优化过程。

skopt.space

skopt中的skopt.space模块用于定义参数搜索空间。它提供了一组工具,使用户可以定义和管理参数的搜索范围、类型和分布。通过space模块,可以轻松地创建参数空间,并将其用于贝叶斯优化或其他优化算法,以在指定范围内搜索最优参数配置。

2.3定义参数搜索空间

此处我们从LightGBM的参数中选取五个参数进行优化。

示例代码

hyperparameter_space = [
    Integer(1, 100, name='min_child_weight'),
    Integer(10, 200, name='num_leaves'),
    Real(0.1, 1.0, prior='log-uniform', name='feature_fraction'),
    Real(0.1, 1.0, prior='log-uniform', name='bagging_fraction'),
    Real(0.01, 0.02, prior='log-uniform', name='learning_rate')
]
  1. Real: Real类用于定义实数类型的参数。通过指定参数的最小值和最大值,可以定义一个连续的参数空间。这样的参数可以是任意实数值,可以用于优化连续型的超参数,例如学习率、正则化参数等。当使用log-uniform分布时,参数在搜索空间内将按照对数均匀分布进行采样。对数均匀分布使得在参数较大范围内能够更加均匀地进行搜索,避免了在线性尺度上过于稀疏或密集的采样。

  2. Categorical: Categorical类用于定义离散类型的参数。通过指定参数的取值列表,可以定义一个离散的参数空间。这样的参数只能从预定义的取值中进行选择,适用于优化分类变量或多选一的超参数。

  3. Integer: Integer类用于定义整数类型的参数。通过指定参数的最小值和最大值,可以定义一个整数范围的参数空间。这样的参数只能在整数范围内取值,适用于优化整数型的超参数,例如决策树的最大深度、神经网络的隐藏层数等。

2.4定义目标函数与回调函数

def objective_function(hyperparameters): # 以超参数作为函数变量
    
    min_child_weight = hyperparameters[0]
    num_leaves = hyperparameters[1]
    feature_fraction = hyperparameters[2]
    bagging_fraction = hyperparameters[3]
    learning_rate = hyperparameters[4]    # 超参数空间中的参数
    
    lgb_params = {
    'boosting_type':'gbdt',
    'objective':'regression',
    'metric':'mae',
    'min_child_weight':min_child_weight, # 赋值
    'num_leaves':num_leaves, # 赋值
    'lambda_12':10,
    'feature_fraction':feature_fraction, # 赋值
    'bagging_fraction':bagging_fraction, # 赋值
    'bagging_freq':4,
    'learning_rate':learning_rate, # 赋值
    'seed':2023,
    'nthread':16,
    'verbose':-1,
    }

    no_info = lgb.callback.log_evaluation(period=-1)
    
    test_features = time_feature(test_dataset)
    # 训练过程与baseline一致
    for pred_label in tqdm(pred_labels):
        train_features = time_feature(train_set,pred_labels=pred_labels)
        train_labels = train_set[pred_label]
        train_data = lgb.Dataset(train_features,label=train_labels)
    
        valid_features = time_feature(valid_set,pred_labels=pred_labels)
        valid_labels = valid_set[pred_label]
        valid_data = lgb.Dataset(valid_features,label=valid_labels)
    
        model = lgb.train(lgb_params,train_data,5000,valid_sets=valid_data,callbacks=[no_info])
    
        valid_pred = model.predict(valid_features,num_iteration=model.best_iteration)
        test_pred = model.predict(test_features, num_iteration=model.best_iteration)
        MAE_score = mean_absolute_error(valid_pred,valid_labels)
        MAE_scores[pred_label] = MAE_score
    
        submit[pred_label] = test_pred
        
    return sum(MAE_scores.values()) # 对象函数的返回值应当是评价指标,据此对超参数逐步优化
# 定义打印每一次迭代后的超参数和评价指标的函数
def print_status(hyperparameter):
    print(hyperparameter)
    print(f"Current MAE Score: {sum(MAE_scores.values())}")

2.5优化过程与优化结果

示例代码

# 调用最小化目标函数的gp_minimize函数,参数依次为目标函数,超参数空间,优化迭代的总次数,随机数种子,回调函数。
result = gp_minimize(objective_function, hyperparameter_space, n_calls=20, random_state=42,callback=print_status)
# 打印使目标函数的返回值(在本项目中即为评价指标)最小的超参数和评价指标
best_hyperparameters = result.x
best_evaluation_metric = result.fun

print(best_hyperparameters)
print(best_evaluation_metric)

以上代码实现了LightGBM中的五个超参数的优化,实际上可以根据需求添加test_size,模型迭代次数和LightGBM的其余超参数等更多的超参数进行优化。

对于模型迭代次数的确定,还可以通过打印训练过程中的loss随迭代次数的变化曲线选取合适的模型迭代次数,或者在LightGBM的参数中设置early_stopping_rounds参数。early_stopping_rounds是一个用于梯度提升树的防止过拟合的参数,它可以提前停止模型的训练,从而防止模型在训练集上过度拟合,并在验证集上找到较好的泛化性能。

2.6提取更多特征

在baseline中,只提取了时间特征,实际上,我们还可以提取更多的特征。通过提取更多特征,可以为模型提供更多的信息和细节,帮助模型更好地捕捉数据中的模式和关联,从而提高模型的性能和预测准确度。考虑提取以下几个特征:

(1)交叉特征:主要提取流量、上部温度设定、下部温度设定之间的关系;

(2)历史平移特征:通过历史平移获取上个阶段的信息;

(3)差分特征:可以帮助获取相邻阶段的增长差异,描述数据的涨减变化情况。在此基础上还可以构建相邻数据比值变化、二阶差分等;

(4)窗口统计特征:窗口统计可以构建不同的窗口大小,然后基于窗口范围进统计均值、最大值、最小值、中位数、方差的信息,可以反映最近阶段数据的变化情况。

示例代码

# 交叉特征
for i in range(1,18):
    train[f'流量{i}/上部温度设定{i}'] = train[f'流量{i}'] / train[f'上部温度设定{i}']
    test[f'流量{i}/上部温度设定{i}'] = test[f'流量{i}'] / test[f'上部温度设定{i}']
    
    train[f'流量{i}/下部温度设定{i}'] = train[f'流量{i}'] / train[f'下部温度设定{i}']
    test[f'流量{i}/下部温度设定{i}'] = test[f'流量{i}'] / test[f'下部温度设定{i}']
    
    train[f'上部温度设定{i}/下部温度设定{i}'] = train[f'上部温度设定{i}'] / train[f'下部温度设定{i}']
    test[f'上部温度设定{i}/下部温度设定{i}'] = test[f'上部温度设定{i}'] / test[f'下部温度设定{i}']
    
# 历史平移
for i in range(1,18):
    train[f'last1_流量{i}'] = train[f'流量{i}'].shift(1)
    train[f'last1_上部温度设定{i}'] = train[f'上部温度设定{i}'].shift(1)
    train[f'last1_下部温度设定{i}'] = train[f'下部温度设定{i}'].shift(1)
    
    test[f'last1_流量{i}'] = test[f'流量{i}'].shift(1)
    test[f'last1_上部温度设定{i}'] = test[f'上部温度设定{i}'].shift(1)
    test[f'last1_下部温度设定{i}'] = test[f'下部温度设定{i}'].shift(1)

# 差分特征
for i in range(1,18):
    train[f'last1_diff_流量{i}'] = train[f'流量{i}'].diff(1)
    train[f'last1_diff_上部温度设定{i}'] = train[f'上部温度设定{i}'].diff(1)
    train[f'last1_diff_下部温度设定{i}'] = train[f'下部温度设定{i}'].diff(1)
    
    test[f'last1_diff_流量{i}'] = test[f'流量{i}'].diff(1)
    test[f'last1_diff_上部温度设定{i}'] = test[f'上部温度设定{i}'].diff(1)
    test[f'last1_diff_下部温度设定{i}'] = test[f'下部温度设定{i}'].diff(1)
    
# 窗口统计
for i in range(1,18):
    train[f'win3_mean_流量{i}'] = (train[f'流量{i}'].shift(1) + train[f'流量{i}'].shift(2) + train[f'流量{i}'].shift(3)) / 3
    train[f'win3_mean_上部温度设定{i}'] = (train[f'上部温度设定{i}'].shift(1) + train[f'上部温度设定{i}'].shift(2) + train[f'上部温度设定{i}'].shift(3)) / 3
    train[f'win3_mean_下部温度设定{i}'] = (train[f'下部温度设定{i}'].shift(1) + train[f'下部温度设定{i}'].shift(2) + train[f'下部温度设定{i}'].shift(3)) / 3
    
    test[f'win3_mean_流量{i}'] = (test[f'流量{i}'].shift(1) + test[f'流量{i}'].shift(2) + test[f'流量{i}'].shift(3)) / 3
    test[f'win3_mean_上部温度设定{i}'] = (test[f'上部温度设定{i}'].shift(1) + test[f'上部温度设定{i}'].shift(2) + test[f'上部温度设定{i}'].shift(3)) / 3
    test[f'win3_mean_下部温度设定{i}'] = (test[f'下部温度设定{i}'].shift(1) + test[f'下部温度设定{i}'].shift(2) + test[f'下部温度设定{i}'].shift(3)) / 3

 将这段代码插入baseline的time_feature函数中,feature函数即可提取时间特征、交叉特征、历史平移特征、差分特征和窗口统计特征。

笔者在本地jupyter lab实际运行提取更多特征的代码时,发现会出现性能警告:DataFrame对象内存碎片化。为了避免展示页面的冗余,导入warning库并忽略警告。

import warnings

warnings.filterwarnings("ignore")

2.7选用其他的boosting_type

LightGBM是一种高效的梯度提升框架,它是一种基于树的集成学习算法。在LightGBM中,有三种常用的Boosting类型,它们分别是:Gradient Boosting Decision Tree (GBDT)、Random Forest (RF) 和Dart。

  1. Gradient Boosting Decision Tree (GBDT): GBDT是LightGBM的默认Boosting类型,它是一种基于梯度提升的决策树。它的特点包括:

    • 顺序构建:GBDT是通过顺序构建决策树来逐步提升模型的预测能力。每个新树都是为了纠正前一轮树的预测误差而构建的。
    • 低方差高偏差:由于顺序构建,GBDT倾向于有较高的模型偏差,因此它在处理复杂数据时可能过拟合。
    • 较快的训练速度:相对于传统的GBDT,LightGBM的GBDT能够更快地进行训练,这得益于特殊的数据结构和采用直方图算法优化的方法。
  2. Random Forest (RF): RF在LightGBM中是通过设置boosting_type参数为"rf"来实现的。它是一种基于决策树的集成学习算法,它的特点包括:

    • 随机特征选择:RF在构建每棵树的过程中,对于每个节点的特征选择是随机的,这有助于减少模型的相关性,防止过拟合。
    • Bagging策略:RF采用Bagging策略,通过对训练集进行有放回的随机采样来训练每棵树,进一步增强模型的泛化能力。
    • 适用于高维数据:RF在处理高维数据时表现较好,且对于异常值和噪声具有较好的鲁棒性。
  3. Dart: Dart在LightGBM中是通过设置boosting_type参数为"dart"来实现的。它是一种基于Dropouts的Boosting算法,它的特点包括:

    • Dropouts正则化:Dart使用Dropouts正则化技术,类似于神经网络中的Dropout层,它可以随机丢弃一部分树和叶节点,有助于减少过拟合。
    • 低内存消耗:Dart通过仅保留一部分树来降低内存消耗,从而在处理大规模数据时表现出色。
    • 较慢的训练速度:由于Dropouts正则化和对部分树的保留,Dart的训练速度相对较慢。

gbdt

示例代码

lgb_params = {
        'boosting_type': 'gbdt',     
        'objective': 'regression',
        'metric': 'mae',
        'min_child_weight': 5,
        'num_leaves': 2 ** 5,
        'lambda_l2': 10,
        'feature_fraction': 0.8,
        'bagging_fraction': 0.8,
        'bagging_freq': 4,
        'learning_rate': 0.05,
        'seed': 2023,
        'nthread' : 16,
        'verbose' : -1,
    }

rf

示例代码

lgb_params = {
    'boosting_type': 'rf',
    'objective': 'regression',
    'metric': 'mae',
    'min_child_weight': 5,
    'num_leaves': 2**5,
    'learning_rate': 0.05,
    'feature_fraction': 0.8,
    'bagging_fraction': 0.8,
    'bagging_freq':4,
    'min_data_in_leaf': 50, # 每个叶子节点最少包含的数据个数,用于控制模型的复杂性
    'num_trees': 200, # 随机森林中树的个数
    'max_depth': 10, # 每棵树的最大深度,用于防止过拟合
    'min_gain_to_split': 0.01, # 分裂节点所需的最小增益,用于控制树的生长
    'bagging_seed': 2023, # 随机种子,用于每轮迭代的随机抽样
    'feature_fraction_seed': 2023, # 随机种子,用于每轮迭代的特征抽样
    'random_state': 2023,
    'seed': 2023, # 随机种子,用于控制整个模型的随机性
    'nthread': 16,
    'verbose': -1,
    }

dart

示例代码

lgb_params = {
    'boosting_type': 'dart',
    'objective': 'regression',
    'metric': 'mae',
    'num_leaves': 2 ** 5,
    'lambda_l2': 10,
    'feature_fraction': 0.8,
    'bagging_fraction': 0.8,
    'bagging_freq': 4,
    'learning_rate': 0.05,
    'drop_rate': 0.1,  # 每轮迭代中要随机丢弃的树的比例
    'skip_drop': 0.5,  # 每个树的被留下来的概率
    'seed': 2023,
    'nthread': 16,
    'verbose': -1,
}

关于LightGBM训练参数的意义可进一步查阅Parameters — LightGBM 4.0.0.99 documentation

3.XGBoost与LightGBM

了解XGBoost的数学原理可移步陈天奇博士关于XGBoost的论文:https://arxiv.org/pdf/1603.02754.pdf

3.1XGBoost的优点及问题

优点:

  • 二阶泰勒展开提高了精度
  • 正则化方法更稳健
  • 借鉴了随机森林的方法,在其中引入了列抽样,降低过拟合
  • 稀疏自主感知
  • 对Cache使用进行了优化,数据块大小提高读写速度
  • 近似分枝(level-wise)支持并行化训练

问题:

  • 精确贪心算法需要反复迭代反复遍历,计算量和内存消耗都很大
  • level-wise策略增长可能带来很多不必要的叶子节点
  • 尽管Cache感知,但仍有大量Cache missing,造成页面调度时间过大

 3.2LightGBM的改进

主要优化点:

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

主要提出的方法

  • 直方图算法
  • 数据并行与特征并行
  • GOSS梯度采样
  • EFB方法
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值