https://d167yddq51j.feishu.cn/wiki/NYVQwUka7iledWkXdhUcKChDnmg
参考:@8群助教陈辅元
下面我们来梳理一下有关这个赛题的知识点吧。
先汇报一下最近的尝试情况,总结一下就是:
集成学习不一定比单个模型要强,这一点我们已经验证过了;
本次赛题单个boost模型不一定就比lgm好;
特征工程这次起到了非常大的作用;
数据探索性分析很重要。
结合陈助教的笔记,我猜测后续的提分思路是
1.时间序列模型+lgm提分;
2.继续做特征工程;
在本次学习中遇到困难的点:
1.lgm自动调参,有时本地跑很辛苦,跑很久出不了结果,这里的参数是参考了助教和别的学习者给的参数的。结果效果很好。
2.训练集和测试集的划分,这个地方很容易出错,我纯lgm得分是700多,但是加上特征工程就是230多了,真的效果很明显;
可以啦,我们上代码:
import pandas as pd
import lightgbm as lgb
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
# 1. 读取训练集和测试集
train = pd.read_csv(r'train.csv')
test = pd.read_csv(r'test.csv')
代码含义:读取数据。接下来的内容很重要:
# 合并训练数据和测试数据
data = pd.concat([train, test], axis=0).reset_index(drop=True)
data = data.sort_values(['id', 'dt'], ascending=False).reset_index(drop=True)
这段代码含义这样解释把,我们把训练集和测试集合并为一份数据进行处理。我们发现其实训练集和测试集给的特征不多,一般来说我们测试集要想根据训练集来进行学习,需要我们构造出一样的数据列,我才能预测啊。。。。
#这段代码放特征工程开始到结束的代码,我先讲解一下lgm的板块,特征工程最后讲。
我们讲lgm
# 进行数据切分
train = data[data.target.notnull()].reset_index(drop=True) # 筛选 'target' 列非空的行作为训练集
test = data[data.target.isnull()].reset_index(drop=True) # 筛选 'target' 列为空的行作为测试集
# 将id列作为索引
train.set_index('id', inplace=True)
test.set_index('id', inplace=True)
# 提取特征和目标变量
X_train = train.drop(['target'], axis=1)
y_train = train['target']
X_test = test.drop(['target'], axis=1)
# 检查形状
print(f"X_train shape: {X_train.shape}")
print(f"y_train shape: {y_train.shape}")
print(f"X_test shape: {X_test.shape}")
这段代码是为了防止代码报错,于是我们训练开始之前检查一下shape
# 创建LightGBM数据集
lgb_train = lgb.Dataset(X_train, label=y_train)
# 定义参数
params = {
'objective': 'regression',
'metric': 'mse',
'verbosity': -1,
'boosting_type': 'gbdt',
}
# 训练模型
num_round = 1000
bst = lgb.train(params, lgb_train, num_round)
# 在预测之前检查形状
if len(X_test.shape) == 1:
X_test = X_test.values.reshape(1, -1) # 如果是一维的,重塑为二维数组
# 现在进行预测
y_pred = bst.predict(X_test)
# 更新测试集的目标列
test['target'] = y_pred
# 重新设置索引并保存结果文件到本地
test.reset_index(inplace=True) # 重新设置索引,恢复 'id' 列
test[['id', 'dt', 'target']].to_csv(r'submit_lgb2.csv', index=False)
# 打印完成提示
print("预测结果已保存到 submit_lgb2.csv 文件中。")
这个地方可以调一下参数。
假如没有这个特征工程,那么我们的得分是700多
现在有了:
# 特征工程部分开始
# 历史平移
for i in range(10, 36):
data[f'target_shift{i}'] = data.groupby('id')['target'].shift(i)
# 历史平移 + 差分特征
for i in range(1, 4):
data[f'target_shift10_diff{i}'] = data.groupby('id')['target_shift10'].diff(i)
# 窗口统计
for win in [15, 30, 50, 70]:
data[f'target_win{win}_mean'] = data.groupby('id')['target'].rolling(window=win, min_periods=3, closed='left').mean().values
data[f'target_win{win}_max'] = data.groupby('id')['target'].rolling(window=win, min_periods=3, closed='left').max().values
data[f'target_win{win}_min'] = data.groupby('id')['target'].rolling(window=win, min_periods=3, closed='left').min().values
data[f'target_win{win}_std'] = data.groupby('id')['target'].rolling(window=win, min_periods=3, closed='left').std().values
# 历史平移 + 窗口统计
for win in [7, 14, 28, 35, 50, 70]:
data[f'target_shift10_win{win}_mean'] = data.groupby('id')['target_shift10'].rolling(window=win, min_periods=3, closed='left').mean().values
data[f'target_shift10_win{win}_max'] = data.groupby('id')['target_shift10'].rolling(window=win, min_periods=3, closed='left').max().values
data[f'target_shift10_win{win}_min'] = data.groupby('id')['target_shift10'].rolling(window=win, min_periods=3, closed='left').min().values
data[f'target_shift10_win{win}_sum'] = data.groupby('id')['target_shift10'].rolling(window=win, min_periods=3, closed='left').sum().values
data[f'target_shift10_win{win}_std'] = data.groupby('id')['target_shift10'].rolling(window=win, min_periods=3, closed='left').std().values
# 特征工程部分结束
GBDT
LightGBM
类别特征(Categorical Feature):字符串类型,如性别(男/女)。 物品类型:服饰、玩具和电子等。 数值特征(Numrical Feature):整型或浮点型,如用户活跃度或商品价格等。 Datawhale开源学习社区:
对于本次教程的改进建议: