【打卡】Datawhale暑期实训ML赛事

news2024/11/18 6:04:10

文章目录

  • 赛题描述
    • 任务要求
    • 数据集介绍
    • 评估指标
  • 赛题分析
  • 基于LightGBM模型
  • Baseline详解
  • 改进baseline
    • 早停法
    • 添加特征

赛题描述

赛事地址:科大讯飞锂离子电池生产参数调控及生产温度预测挑战赛

任务要求

初赛任务:初赛提供了电炉17个温区的实际生产数据,分别是电炉上部17组加热棒设定温度T1-1 ~ T1-17,电炉下部17组加热棒设定温度T2-1~T2-17,底部17组进气口的设定进气流量V1-V17,选手需要根据提供的数据样本构建模型,预测电炉上下部空间17个测温点的测量温度值。

数据集介绍

初赛任务:初赛提供了电炉17个温区的实际生产数据,分别是电炉上部17组加热棒设定温度T1-1 ~ T1-17,电炉下部17组加热棒设定温度T2-1~T2-17,底部17组进气口的设定进气流量V1-V17,选手需要根据提供的数据样本构建模型,预测电炉上下部空间17个测温点的测量温度值。

评估指标

初赛考核办法采用测试集各行数据的加热棒上部温度设定值、加热棒下部温度设定值、进气流量3类数据作为输入,选手分别预测上部空间测量温度、下部空间测量温度。将选手预测的上部空间测量温度、下部空间测量温度与测试集数据的测量值进行比较。采用MAE平均绝对误差作为评价指标。

赛题分析

本次比赛为数据挖掘类型的比赛,聚焦于工业场景。本赛题实质上为回归任务,其中会涉及到时序预测相关的知识。

通过电炉空间温度推测产品内部温度,设计烧结过程的温度场和浓度场的最优控制律:

任务输入:电炉对应17个温区的实际生产数据,分别是电炉上部17组加热棒设定温度T1-1 ~ T1-17,电炉下部17组加热棒设定温度T2-1~T2-17,底部17组进气口的设定进气流量V1-V17;
任务输出:电炉对应17个温区上部空间和下部空间17个测温点的测量温度值。
值得注意的是预测目标为34个,所以需要我们进行34次模型训练和预测。

同时数据规模比较小,可以快速处理数据和搭建模型,对于机器要求8g内存即可。

本次为结构化赛题,包含电炉烧结每个时间段的流量、上下部设定温度,以及预测目标上下部测量温度值。

基于LightGBM模型

在处理这个问题时,我们主要考虑的是回归预测。一种常规的解决思路是运用机器学习技术,例如 LightGBM 或 XGBoost,或者借助深度学习方法进行实践。当我们选择自行搭建模型的路径时,我们将面临更为复杂的挑战,包括构建模型结构以及对数值数据进行标准化处理。

然而,一个简易的解决方案可能就在我们眼前,那就是直接使用现成的机器学习模型。这种方法具有明显的优势,其模型使用简单,数据预处理的需求也大大减少。

总的来说,我们需要经过以下步骤来解决本问题:

数据预处理
切分训练集与验证集
训练模型
生成最后的预测结果。
在实施这些步骤的过程中,我们需要根据模型的性质和数据的特点灵活调整,确保每一步的实施都能最大化模型的预测准确性,从而有效解决这个回归预测问题。

Baseline详解

导入需要的库:

import pandas as pd # 用于处理数据的工具
import lightgbm as lgb # 机器学习模型 LightGBM
from sklearn.metrics import mean_absolute_error # 评分 MAE 的计算函数
from sklearn.model_selection import train_test_split # 拆分训练集与验证集工具
from tqdm import tqdm # 显示循环的进度条工具

读取数据:

# 数据准备
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() # 定义评分项。

查看数据:

train_dataset.head()

在这里插入图片描述
在这里插入图片描述

test_dataset.head()

在这里插入图片描述
在这里插入图片描述
设置lgb参数:

# 参数设置
pred_labels = list(train_dataset.columns[-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', #使用的最小化指标
        'metric': '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为不打印,0为打
    }

no_info = lgb.callback.log_evaluation(period=-1) # 禁用训练日志输出。

进行特征工程,主要是时间文本转换为时间格式,生成年、日、小时、分钟等时间特征:

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

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

        pred_labels: list, 默认值: None
            需要预测的标签的列表。如果是测试集,不需要填入。
    
    输出: data: Pandas.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)

在这里插入图片描述

训练模型并进行预测:

# 从所有待预测特征中依次取出标签进行训练与预测。
for pred_label in tqdm(pred_labels):
    # print("当前的pred_label是:", pred_label)
    train_features = time_feature(train_set, pred_labels=pred_labels) # 处理训练集的时间特征。
    # train_features = enhancement(train_features_raw)
    train_labels = train_set[pred_label] # 训练集的标签数据。
    # print("当前的train_labels是:", train_labels)
    train_data = lgb.Dataset(train_features, label=train_labels) # 将训练集转换为 LightGBM 可处理的类型。

    valid_features = time_feature(valid_set, pred_labels=pred_labels) # 处理验证集的时间特征。
    # valid_features = enhancement(valid_features_raw)
    valid_labels = valid_set[pred_label] # 验证集的标签数据。
    # print("当前的valid_labels是:", 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 # 将测试集预测数据存入最终提交数据中。
     
submit.to_csv('submit_result.csv', index=False) # 保存最后的预测结果到 submit_result.csv

保存文件:

# 保存文件并查看结果
submit.to_csv('submit_result.csv', index=False) # 保存最后的预测结果到 submit_result.csv。
print(MAE_scores) # 查看各项的 MAE 值。

最后结果是7.94826。

改进baseline

早停法

由于模型有过拟合的风险,所以可以通过早停来让模型在一段时间不能得到提升后提前结束训练。lgb中可以通过添加参数来实现。

lgb_params = {
        'boosting_type': 'gbdt', #使用的提升方法,使用梯度提升决策树gbdt
        'objective': 'regression', #使用的最小化指标
        'metric': 'mae', #使用的评价指标
        'early_stopping_round':20, #早停,如果20轮没有提升就停止训练
        '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为不打印,0为打
    }

添加特征

尝试提取更多特征,这里尝试添加交叉特征、历史平移特征、差分特征、和窗口统计特征;每种特征都是有理可据的,具体说明如下:
(1)交叉特征:主要提取流量、上部温度设定、下部温度设定之间的关系;
(2)历史平移特征:通过历史平移获取上个阶段的信息;
(3)差分特征:可以帮助获取相邻阶段的增长差异,描述数据的涨减变化情况。在此基础上还可以构建相邻数据比值变化、二阶差分等;
(4)窗口统计特征:窗口统计可以构建不同的窗口大小,然后基于窗口范围进统计均值、最大值、最小值、中位数、方差的信息,可以反映最近阶段数据的变化情况。

在时间特征函数中添加:

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

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

    # 对平移后的空值进行填充 
    data = data.fillna(method='bfill')

这里要注意在平移之后第一个值会变成nan(因为没有前一个值),包括窗口统计的前3个值,因此需要用后填充的方式将其填充。

经过这两个操作后分数变为7.51948。
由于时间关系,暂时只做这两个改进,后续会进行更多探索。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/799990.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

字典树Trie

Trie树又称字典树,前缀树。是一种可以高效查询前缀字符串的树,典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。 它的优点是:利用字符串…

欧姆龙 NJ SNMP 协议的使用,用于监控PLC的网络状态

NJ SNMP 协议的使用 实验时间:2023.07.25 实验器材:NJ501-1300 实验目的:NJ SNMP 协议的使用 1. SNMP 协议介绍 ​ SNMP(Simple Network Management Protocol)是一种简单网络管理协议。它属于 TCP/IP 五层协议中的…

Cerbero Suite Advanced Crack

Cerbero Suite Advanced Crack 用于软件分类和文件分析的最先进的工具套件。分析多种文件格式,包括PE、Mach-O、ELF、Java、SWF、DEX、PDF、DOC、XLS、RTF、Zip等。 它提供自动分析、交互式分析、Carbon interactive Disassembler、字节码反汇编程序、带布局的十六进…

一篇文章搞定《EventBus详解》

一篇文章搞定《EventBus详解》 前言EventBus简述EventBus的使用EventBus源码解析初始化并构建实例EventBus.getDefault()EventBus.builder()EventBus初始化的重要成员 注册流程register方法SubscriberMethodFinder类findSubscriberMethods方法findUsingReflection方法&#xff…

掌握Python的X篇_10+11_if分支语句、else语句、elif语句

文章目录 1. if关键字及语法2. 语句块的概念3. else语句4. elif语句 1. if关键字及语法 基本语法如下: if 条件表达式:条件为True时,要执行的语句举例: number int(input("Input an number")) if number > 5 :print("这…

【Spring框架】spring对象注入的三种方法

目录 1.属性注入问题:同类型的Bean存储到容器多个,获取时报错的问题;1.将属性的名字和Bean的名字对应上。2.使用AutoWiredQualifier来筛选bean对象; 属性注入优缺点 2.Setter注入Setter注入优缺点 3.构造方法注入(Spri…

Node.js 安装与版本管理(nvm 的使用)

安装 Node.js Node.js 诞生于 2009 年 5 月,截至今天(2022 年 3 月 26 号)的最新版本为 16.14.2 LTS 和 17.8.0 Current,可以去官网下载合适的版本。 其中,LTS(Long Term Support) 是长期维护…

MySQL基础扎实——主键与候选键

词义解释 主键(Primary Key)和候选键(Candidate Key)是关系型数据库中的术语,用于标识和唯一确定表中的记录。它们之间有以下区别: 唯一性:主键是表中的唯一标识,每个表只能有一个主…

环境保护数据传输系统监测环境指标

嵌入式实时操作系统(RTOS)是一种专门设计用于嵌入式系统的操作系统。它具有实时性能和低延迟的特点,能够满足对时间响应性要求较高的应用。本文介绍了一种具备Modbus Slave和Modbus Master功能的嵌入式实时操作系统设备,以及其扩展…

OpenGL Metal Shader 编程:ShaderToy 内置全局变量

OpenGL & Metal Shader 编程:ShaderToy 内置全局变量 前面发了一些关于 Shader 编程的文章,有读者反馈太碎片化了,希望这里能整理出来一个系列,方便系统的学习一下 Shader 编程。 由于主流的 Shader 编程网站,如…

Dart - 语法糖(持续更新)

文章目录 前言开发环境中间表示语法糖1. 操作符/运算符(?./??/??/../?../.../...?)2. 循环(for-in)3. 函数/方法(>)4. 关键字(await for) 最后 前言 通过将dill文件序列化…

【时间序列预测 2023 ICLR】TimesNet

【时间序列预测 2023 ICLR】TimesNet 论文题目:TIMESNET: TEMPORAL 2D-VARIATION MODELING FOR GENERAL TIME SERIES ANALYSIS 中文题目:TimesNet:用于一般时间序列分析的时态二维变异建模 论文链接:https://arxiv.org/abs/2210.02186 论文代…

大专同事一个人7天完成CRM系统开发,怪不得月薪3w

在当今的快节奏商业环境中,成功的关键是敏捷和高效。这使得开发自己的客户关系管理系统(CRM)成为许多企业的迫切需求。CRM有助于跟踪和优化销售线索,管理客户交互,并提高业务效率。但是,对于许多企业来说&a…

大学毕业后,我就去当了2个月外卖骑手,哭了一整晚

先简单介绍一下自己,我来自长沙,大学学的的物流管理专业,现在就职于一家互联网公司,从事软件测试工作。 我来自长沙县的一个偏远农村,家里兄弟姐妹多,父母无力负担我的学费,很多时候学费都是靠姐…

智慧工厂4G+蓝牙+UWB+RTK人员定位系统解决方案

人员定位在智慧工厂的应用正逐渐受到重视,通过使用现代化的技术和智能终端设备,工厂管理者能够实时定位和跟踪员工的位置,方便进行人员调度管理和监督人员的工作情况;人员遇到紧急情况,可通过定位设备一键报警求救&…

智慧消防:如何基于视频与智能分析技术搭建可视化风险预警平台?

一、背景分析 消防安全是一个重要的话题,涉及到每个人的生活和安全。每年都会发生大量的火灾,给人们带来极大的危害,摧毁了大量的财产,甚至造成了可怕的人员伤亡。而消防安全监督管理部门人员有限,消防安全监管缺乏有…

2.2 模型与材质基础

一、渲染管线与模型基础 1. 渲染管线 可编程阶段(蓝色区域): 1顶点着色器 2几何着色器 3片元着色器 2. 模型的实现原理 UV:在建模软件中,进行UV展开,UV会放在一个横向为U纵向为V,范围&#xff0…

TEE GP(Global Platform)功能认证实验室

TEE之GP(Global Platform)认证汇总 GP认证实验室主要面向功能认证、SE安全认证、TEE安全认证,对于TEE来说,则分为TEE功能认证和TEE安全认证。本文对功能认证相关实验室机构进行总结和介绍。 一、国内3家 二、国外3家 参考: GlobalPlatform …

回归预测 | MATLAB实现POA-CNN-BiLSTM鹈鹕算法优化卷积双向长短期记忆神经网络多输入单输出回归预测

回归预测 | MATLAB实现POA-CNN-BiLSTM鹈鹕算法优化卷积双向长短期记忆神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现POA-CNN-BiLSTM鹈鹕算法优化卷积双向长短期记忆神经网络多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLA…

安全杂记 - js中的this关键字

javascript里什么是this this是js中的一个关键字&#xff0c;它是函数在运行时生成的一个内部对象&#xff0c;是属性和方法。 this就是属性或方法“当前”所在的对象&#xff0c;也就是调用函数的那个对象 this的使用场合 1.函数调用 <script>var a100;function test…