【Datawhale夏令营】任务二学习笔记

news2024/11/15 13:53:11

目录

一:python语法回顾

1.1  print()

1.2  列表与字典

1.3自定义函数与return

1.4火车类(面向对象) 

实例化总结:

二:LightGBM 代码精读

2.1导入库

2.2数据准备与参数设置

 2.3时间特征函数

  2.4优化

 2.5训练与预测

三:优化讲解

3.1:

3.2优化建议:


一:python语法回顾

1.1  print()

  1. 每一个print()会默认换行,若不想换行则:print("",end=""),默认end="\t"

  2. 单行注释 使用“#”开头,只能写在一行中~

1.2  列表与字典

  1. 列表是一种序列,他是可变的:容器的唯一作用就是打包、解包、内容传递】

  2. 列表定义:p2s = []

  3. 字典是键值对的集合

  4. 定义一个集合:Dw_set = set() 用add()函数将诗句插入集合中

  5. 定义一个字典:dw_dict = {"d":"Data","w":"whale"} # key:value 键:值;

  6. 字典可以利用键去查询对应的值

  7. 字典的更新:dw_dict["w"] = "whale"

1.3自定义函数与return

     回调函数(callback)

1.4火车类(面向对象) 

  1. 发车函数里,有一个"_"意思是不赋值给任何变量,是一个黑洞

实例化总结:

 

二:LightGBM 代码精读

2.1导入库

!pip install -U lightgbm
!unzip data/data227148/data.zip
#特别适合处理大规模数据集。
#当处理大规模数据集、需要高效训练和预测速度,并且希望获得较好的性能时,LightGBM通常是一个不错的选择。


# 导入所需的库
import pandas as pd # 读取和处理csv文件的数据
#用于处理数据的工具,常用于数据加载、数据清洗和数据预处理。

import lightgbm as lgb # 机器学习模型 LightGBM
#构建梯度提升树模型,是一种高效的机器学习算法。

from sklearn.metrics import mean_absolute_error # 评分 MAE 的计算函数
#从sklearn.metrics模块中导入评分函数
#平均绝对误差(MAE),是用于回归问题的一个评价指标。

from sklearn.model_selection import train_test_split # 拆分训练集与验证集工具
#用于将数据集拆分为训练集和验证集,以便进行模型训练和评估。

#sklearn.model_selection:对机器学习模型进行参数调优、数据集拆分、交叉验证和性能评估等任务。
#train_test_split函数:将数据集划分为训练集和测试集,并且可以灵活地设置拆分比例和随机种子。


from tqdm import tqdm # 显示循环的进度条工具
#循环过程中显示进度条,方便查看代码执行进度。

2.2数据准备与参数设置

# 数据准备
train_dataset = pd.read_csv("C:\\Users\\86198\\OneDrive\\桌面\\train.csv") # 原始训练数据。
test_dataset = pd.read_csv("C:\\Users\\86198\\OneDrive\\桌面\\test.csv") # 原始测试数据(用于提交)。

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

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

# 模型参数设置
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通常会输出一些训练过程的信息,通过回调函数可以避免输出这些信息,使得训练过程更简洁。

 2.3时间特征函数

# 时间特征函数   特征提取
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 无法处理这个特征,它已体现在其他特征中,故丢弃。


  2.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

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

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


test_features = time_feature(test_dataset)  # 处理测试集的时间特征,无需 pred_labels。

 2.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)
    # 调用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)  # 处理验证集的时间特征。
    # valid_features = enhancement(valid_features_raw)
    # 调用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  # 将测试集预测数据存入最终提交数据中。

submit.to_csv(r"C:\Users\86198\OneDrive\桌面\submit_result.csv", index=False)  # 保存最后的预测结果到 submit_result.csv

# 保存文件并查看结果
submit.to_csv(r"C:\Users\86198\OneDrive\桌面\submit_result.csv", index=False) # 保存最后的预测结果到 submit_result.csv。
print(MAE_scores) # 查看各项的 MAE 值。

三:优化讲解

3.1:

具体地,我们可以尝试提取更多特征改善最终结果,这也是数据挖掘比赛中的主要优化方向,很多情况下决定着最终的成绩。

这里主要构建了交叉特征、历史平移特征、差分特征、和窗口统计特征;每种特征都是有理可据的,具体说明如下:

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

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

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

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

3.2优化建议:

1、过拟合现象

在代码运行的时候可以将callbacks=[no_info]去除,以查看模型运行的日志,运行结束后也可以利用代码print(MAE_scores)来打印出最终的损失,观察不难看出,模型会在一定时间后进入过拟合,因此可以尝试以一些措施来缓解这种现象。

  • 利用lightgbm自带的early_stopping_rounds参数。
  • 采用多折验证的方式扩大数据量,使得模型泛化能力增强。

2、 参数设定

此次基线没有做精确的调参处理,因此可以调参的范围还是挺大的,常用的搜索参数策略有两种:

  • 网格搜索(Grid Search):这是一种传统的参数调整方法,它会测试指定参数的所有可能组合来找出最佳参数。但是,当参数空间较大时,这种方法可能会消耗大量计算资源和时间。

  • 随机搜索(Random Search):与网格搜索相比,随机搜索不会测试所有的参数组合,而是在参数空间中随机选择一定数量的参数组合进行测试。尽管随机搜索可能无法找到最优的参数组合,但在计算资源有限的情况下,它是一个有效的选择。

3、 模型设定

我们此次基线采用的是LightGBM,我们也可以试试XGBoost, Adaboost, Catboost等等传统的模型,并且也可以使用深度学习的方法构建循环神经网络来处理此次任务,因为本质是一个时序任务,在采用机器学习的同时也可以保存模型的参数配置,尝试进行模型集成的训练。

4、 特征

在特征选择方面,目前给出的特征仅仅是单独对时间处理,与对流量\上\下\部温度设定进行处理,并未结合时间与其他特征的关系,可以尝试自己构建合理的新特征。

5、 后处理

对已经给出的csv文件仍然可以分析其趋势,抓住评估的关键来调整文件内容使得结果更加精确。

6、 迭代步数 目前设置的迭代步数为200轮,其实这对于某些预测数据来说是不够的,可以尝试自己增大迭代步数

baseline进行修改优化后并跑通,结果可观如下:

调整参数后: 

参考文章:

datawhale暑期夏令营:datawhale开源项目

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

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

相关文章

Verilog | Round_Robin_Arbiter

重写了权重轮询仲裁,添加lock输入信号,表示请求方收到了仲裁许可,在对应的lock拉低之前,仲裁器不可以开启新的仲裁。 Generics Generic nameTypeValueDescriptionN4 Ports Port nameDirectionTypeDescriptionclkinputrst_ninp…

MSP432自主开发笔记4:DS3115舵机的0~180全角度驱动

芯片使用:MSP432P401R. 今日学习一款全角度15KG大扭力舵机的驱动,最近电赛学习任务紧,更新一篇比较水的文章: 文章提供原理解释,全部代码,整体工程: 目录 舵机驱动原理: 这是舵机DS3115MG:…

Python怎么实现贪婪排名算法

目录 什么是贪婪排名算法 贪婪排名算法的优点 贪婪排名算法的应用 Python怎么实现贪婪排名算法 总结 什么是贪婪排名算法 贪婪排名算法是一种常见的排序算法,在许多优化问题中得到广泛应用。它的主要思想是通过每次选择当前看起来最优的选择,逐步构…

嵌入式:QT Day3

一、完成闹钟的实现 首页: 启动后: 点击停止后: 二、思维导图

Ansible的应用

Ansible简介 Ansible是一个基于Python开发的配置管理和应用部署工具,现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点,Pubbet和Saltstack能实现的功能,Ansible基本上都可以实现。 Ansible能批量配置、部署、管理上千台主机…

4. 方法(函数)

文章目录 4.1. 什么是方法的返回值?返回值在类的方法里的作用是什么?4.2. 为什么 Java 中只有值传递? 4.1. 什么是方法的返回值?返回值在类的方法里的作用是什么? 方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提…

MessageBox弹出框中加入DatePicker日期选择器

效果&#xff1a; 代码片段 重点是open函数中&#xff0c;使用了h函数来写dom。关于h函数的解释可见一下博文点击跳转博文&#xff1a;解析h函数 在element-ui的官方文档中&#xff0c;对这种方式有清晰的解释。点击跳转官网可见 <template><div><el-button t…

appium介绍

移动自动化测试工具appium。appium目前在移动UI自动化测试领域占有重要地位&#xff0c;不仅支持Android和IOS两大平台&#xff0c;还支持多种编程&#xff0c;因而得到广泛的应用。 移动应用类型 移动应用类型主要分为以下几类 Native App&#xff1a;原生应用。Mobile Web…

Android性能优化之游戏收敛线程,减少OOM发生(epic 检测线程调用/booster减少常驻线程超时销毁)

先来了解下一个空白app的进程中线程数量&#xff1a; 分析迷你世界中app线程之前&#xff0c;先来了解下空白app &#xff0c;中线程情况&#xff1a; 一个空白app的线程大概是27个&#xff1a; 一个空白的的app&#xff0c;包含FinalizerDaemon线程、FinalizerWatchd线程、R…

GitHub Copilot:让开发编程变得像说话一样简单

引用&#xff1a; 人类天生就梦想、创造、创新。但今天&#xff0c;我们花太多时间被繁重的工作所消耗&#xff0c;花在消耗我们时间、创造力和精力的任务上。为了重新连接我们工作的灵魂&#xff0c;我们不仅需要一种更好的方式来做同样的事情&#xff0c;更需要一种全新的工…

“从世界第一黑客到顶级安全咨询专家” 凯文·米特尼克去世

一、人物简介 凯文米特尼克&#xff08;英语&#xff1a;Kevin David Mitnick&#xff0c;1963年8月6日—2023年7月16日&#xff09;&#xff0c;是美国计算机安全顾问&#xff0c;作家和黑客。他拥有“世界头号黑客”&#xff0c;“世界上最著名的黑客”、“地狱黑客”、“头号…

SPI通信

文章目录 SPI通信简介硬件电路移位示意图SPI时序基本单元1.起始条件2.终止条件模式1模式0模式2模式3 SPI时序 SPI通信简介 四根通信线&#xff1a; SCK"串行时钟线 MOSI:主机输出从机输入 MISO:主机输入从机输出 SS:从机选择 通信方式&#xff1a;同步&#xff0c;全双工…

向量数据库Milvus的四个版本

目录 MilvusLite版 单机版 分布式版 Milvus Cloud版 Milvus是一个功能强大的向量数据库管理系统,提供了多种版本,以满足不同用户的需求。以下是关于Milvus四个版本的具体介绍。 MilvusLite版 MilvusLite版是Milvus的轻量级版本,适合于小规模数据集和高性能计算场景。…

使用for循环输出左上三角、右上三角、左下三角、右下三角、上下三角

1、输出如下图形&#xff1a; #include<stdio.h> int main() {/*输出图形 666666666666666*/for(int i1;i<5;i){for(int j1;j<i;j){putchar(6);}printf("\n"); } return 0; } 2、输出如下图形&#xff1a; #include<stdio.h> int main() {/*输出图…

合作客户销售数据可视化分析

以一个案例进行实际分析&#xff1a; 数据来源&#xff1a;【地区数据分析】 以此数据来制作报表。 技巧一&#xff1a;词云图 以城市名称来显示合同金额的分布&#xff0c;合同金额越大&#xff0c;则城市文字显示越大。 2 2 2 2 2 2

【MySQL数据库备份】

目录 一、概述 二、数据备份的重要性 1. 数据保护 2. 灾难恢复 3. 数据完整性 4. 合规性要求 三、造成数据丢失的原因 1. 硬件故障 2. 人为错误 3. 黑客攻击 4. 自然灾害 5. 软件故障 四、备份类型 1.物理与逻辑角度 1.1 概念 1.2 物理备份 1.2.1 冷备份 1.2…

php-golang-jsonrpc2.0 rpc-codec/jsonrpc2和tivoka/tivoka实践

golang代码&#xff1a; package main import ( "context" "net" "net/rpc" "github.com/powerman/rpc-codec/jsonrpc2" ) type App struct{} type Res struct { Code int json:"code" Msg string json:"msg&quo…

kafka集群

目录 broker ZooKeeper consumer group&#xff08;消费者组&#xff09; 分区&#xff08;Partitions&#xff09; 副本&#xff08;Replicas&#xff09; 主题&#xff08;Topic&#xff09; 偏移量&#xff08;offset&#xff09; broker 一个kafka进程就是一个broker…

C++ 名字空间namespace

在C中支持三种域&#xff1a;局部域、名字空间域和类域。 名字空间域是随标准C而引入的。它相当于一个更加灵活的文件域&#xff08;全局域&#xff09;&#xff0c;可以用花括号把文件的一部分括起来&#xff0c;并以关键字namespace开头给它起一个名字&#xff1a; namespac…

多线程与高并发(17)——多线程总结(很全)

总结并复习了一下之前写的多线程的知识&#xff0c;见下图。 不够清楚可私信或者processOn。