#AI夏令营 #Datawhale
Datawhale第二期的“机器学习”方向是基于讯飞开放平台“电力需求预测挑战赛”开展的实践学习,本帖将记录一个AI小白在7天夏令营内外学习中所见所学所为,欢迎大家交流讨论。
TASK1
第一个任务就是根据Datawhale的给的文档跑通Baseline。在飞书上他们把每一步的步骤都列出来了,跟着做就好。
文档在这里 link1.
照着做完后就得到了自己的第一个分数。
TASK2
第二个任务是使用进阶的机器学习模型lightgbm解决本次问题,以达到更好的预测效果。
一般的使用机器学习模型解决问题的主要步骤为探索性数据分析、数据预处理、提取特征、切分训练集与验证集、训练模型、预测结果。
官方文档link2.有讲的LightGBM等一些概念我不再赘述,我主要就第二次进阶的机器学习代码做注释
在此之前,我先讲一些准备工作:因为task1是在飞桨上跑的,感觉还挺好用,就沿用了。针对初学者,可以到飞桨的官方帮助文档link3.了解一下基本的使用方法,比如下载第三方库就是新建一个单元格如下图运行。
代码和解释部分
# 首先就是导入一些七七八八的需要用到的库
import numpy as np
import pandas as pd
import lightgbm as lgb
import tqdm
import sys
import os
import gc
import argparse
import warnings
warnings.filterwarnings('ignore')
#以下几行和Datawhale文档有区别是因为lightgbm版本的原因,可以参考下这篇文章
#https://blog.csdn.net/weixin_51723388/article/details/124578560
from lightgbm import log_evaluation, early_stopping
callbacks = [log_evaluation(period=100), early_stopping(stopping_rounds=30)]
from sklearn.metrics import mean_squared_log_error, mean_absolute_error, mean_squared_error
# 读取训练集和测试集
train = pd.read_csv('./data/data283931/train.csv')
test = pd.read_csv('./data/data283931/test.csv')
# 合并训练数据和测试数据,并进行排序
data = pd.concat([test, train], axis=0, ignore_index=True)
data = data.sort_values(['id','dt'], ascending=False).reset_index(drop=True)
# 历史平移
for i in range(10,30):
data[f'last{i}_target'] = data.groupby(['id'])['target'].shift(i)
# 窗口统计
data[f'win3_mean_target'] = (data['last10_target'] + data['last11_target'] + data['last12_target']) / 3
# 进行数据切分
train = data[data.target.notnull()].reset_index(drop=True)
test = data[data.target.isnull()].reset_index(drop=True)
# 确定输入特征
train_cols = [f for f in data.columns if f not in ['id','target']]
# 模型训练与测试集预测
def time_model(lgb, train_df, test_df, cols):
# 训练集和验证集切分
trn_x, trn_y = train_df[train_df.dt>=31][cols], train_df[train_df.dt>=31]['target']
val_x, val_y = train_df[train_df.dt<=30][cols], train_df[train_df.dt<=30]['target']
# 构建模型输入数据
train_matrix = lgb.Dataset(trn_x, label=trn_y)
valid_matrix = lgb.Dataset(val_x, label=val_y)
# lightgbm参数
lgb_params = {
'boosting_type': 'gbdt',
'objective': 'regression',
'metric': 'mse',
'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': 2024,
'nthread' : 16,
'verbose' : -1,
}
# 训练模型
# model = lgb.train(lgb_params, train_matrix, 50000, valid_sets=[train_matrix, valid_matrix],
# categorical_feature=[], verbose_eval=500, early_stopping_rounds=500)
model = lgb.train(lgb_params, train_matrix, 50000, valid_sets=[train_matrix, valid_matrix],
categorical_feature=[], callbacks=callbacks) #这里改了Datawhale文档的参数,版本问题
# 验证集和测试集结果预测
val_pred = model.predict(val_x, num_iteration=model.best_iteration)
test_pred = model.predict(test_df[cols], num_iteration=model.best_iteration)
# 离线分数评估
score = mean_squared_error(val_pred, val_y)
print(score)
return val_pred, test_pred
lgb_oof, lgb_test = time_model(lgb, train, test, train_cols)
# 保存结果文件到本地
test['target'] = lgb_test
test[['id','dt','target']].to_csv('submit.csv', index=None)
实际上,我没有去深究这份代码具体怎么写,只是复制,粘贴,对着报错查资料,改参数,周而复始,最后跑通。我曾经学过1学期的python,用得很少,忘得很快,比较熟悉的是C,会对着算法题写一堆的代码。但捡起python,我却有了不一样的感受,它在很多地方不用我们重复造轮子,挺好的(懒得写了()
贴出新的分数
TASK3
最新给的代码是涉及深度学习的,直接放飞桨跑会报错,因为飞桨默认用paddlepaddle框架,而Datawhale给的baseline好像是tensorflow(存疑?)
因为之前水了都是在paddlepaddle(飞桨)上直接跑,这次得重新配置。
首先在比赛官网把数据集下下来
解压然后拖到pycharm创建的一个项目里
然后开始去anaconda powshell下第三方库,用pycharm运行,哪里报错就下什么
提醒一点,就是那个sklearn得下scikit-learn,代码不用改
最后贴上代码
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import LSTM, Dense, RepeatVector, TimeDistributed
from keras.optimizers import Adam
train = pd.read_csv('./数据集/train.csv')
test = pd.read_csv('./数据集/test.csv')
# 数据预处理
def preprocess_data(df, look_back=100):
# 将数据按照id进行分组
grouped = df.groupby('id')
datasets = {}
for id, group in grouped:
datasets[id] = group.values
# 准备训练数据集
X, Y = [], []
for id, data in datasets.items():
for i in range(10, 15): # 每个id构建5个序列
a = data[i:(i + look_back), 3]
a = np.append(a, np.array([0] * (100 - len(a))))
X.append(a[::-1])
Y.append(data[i - 10:i, 3][::-1])
# 准备测试数据集
OOT = []
for id, data in datasets.items():
a = data[:100, 3]
a = np.append(a, np.array([0] * (100 - len(a))))
OOT.append(a[::-1])
return np.array(X, dtype=np.float64), np.array(Y, dtype=np.float64), np.array(OOT, dtype=np.float64)
# 定义模型
def build_model(look_back, n_features, n_output):
model = Sequential()
model.add(LSTM(50, input_shape=(look_back, n_features)))
model.add(RepeatVector(n_output))
model.add(LSTM(50, return_sequences=True))
model.add(TimeDistributed(Dense(1)))
model.compile(loss='mean_squared_error', optimizer=Adam(0.001))
return model
# 构建和训练模型
look_back = 100 # 序列长度
n_features = 1 # 假设每个时间点只有一个特征
n_output = 10 # 预测未来10个时间单位的值
# 预处理数据
X, Y, OOT = preprocess_data(train, look_back=look_back)
# 构建模型
model = build_model(look_back, n_features, n_output)
# 训练模型
model.fit(X, Y, epochs=75, batch_size=64, verbose=1)
# 进行预测
predicted_values = model.predict(OOT)
print(predicted_values.shape)
print(OOT.shape)
# 由于最后一个维度是1,我们可以直接去掉它(使用 squeeze 方法或者索引)
predicted_values_squeezed = predicted_values.squeeze(axis=-1) # 现在形状是 (5832, 10)
# 将每个 (10,) 数组展平成一个单独的数组,并将它们连接起来
flattened_predictions = predicted_values_squeezed.flatten()
test['target'] = flattened_predictions
test[['id','dt','target']].to_csv('submit6.csv', index=None)
咳咳,虽然用了新的深度学习的方法,但结果有些不如人意,调了好几次参数都没有好分数,可能是我最后写的展开不太合理(?)
Epochs(训练轮次):
epochs决定了整个训练数据集将被遍历多少次。增加epochs可以提高模型的训练程度,但也可能导致过拟合。
如果模型在训练集上的表现持续提升,但在验证集上的表现开始下降,这可能是一个过拟合的信号,此时应减少epochs。
Batch Size(批大小):
batch_size决定了每次更新权重时使用的样本数量。较小的batch_size可以增加模型的训练速度和泛化能力,但也可能导致训练不稳定。
较大的batch_size可以减少训练过程中的噪声,但可能会消耗更多的内存,并可能导致模型泛化能力下降。
作为蒟蒻只会调这俩,就我试的这六次中,epochs=10,batch_size=64是最低的;epochs=75,batch_size=64是最高的。()()()