DataWhale夏令营(机器学习方向)—————— 电力需求预测

说明: 这里再百度的 Codelab 上面运行的话会很慢,我在Deepln 上面运行的。虽然它是个跑深度学习的平台。

一、对于数据简单的了解

需要导入的库:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import lightgbm as lgb
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline
from sklearn.metrics import mean_squared_error
sns.set(style='white', context='notebook', palette='deep')

操作的代码:

# 获取 df 中的一些基本信息
def get_cols_info(df):
    print(f"df 数据集中有 {df.shape[0]} 个样本值。")
    for col in df.columns:
        print(f"{col} 中有 {df[col].nunique()} 个不同值, 有 {df[col].isnull().sum()} 个缺失值。")

# 获取 trian 中的基本信息
get_cols_info(train)

print(" ----------\|/----------")
# 获取 test 中的基本信息
get_cols_info(test)

运行结果如下:

 可以看到,train 和 test 的 id 这一列都 5832 个不同值,那我们应该是根据每个 id 在训练集给定的结果去预测测试集中的结果。

二、对于特征 type 的简单探索

type 代表的房屋类型,根据常识可知不同的房屋类型对于电力的消耗肯定是不同的。     

2.1 对于 type 的简单统计操作:

操作代码:

train['type'].value_counts()

 运行结果:

这里我们统计的是不同的房屋类型在训练集中的数目。使用的是 pandas 中的 ```value_counts()```函数。

2.2, 对于 type 的更进一步探索

操作代码:

### 查看不同房屋类型对应的 target 的一些属性
agg_results = train.groupby('type')['target'].agg(
    mean='mean',
    max='max',
    min='min',
    std='std',
    count='size'
)
# 显示结果
agg_results

运行结果:

这里我们统计了不同类型房屋对应的 target 的值对应的均值、最大值、最小值、方差和总数。可以看到不同房屋对应的的 target 均值不同,有的最大值和最小值相差还比较大,这里可以理解,毕竟每种 type 可能对应着很多不同的 id。

三、特征工程

3.1 根据 task2 对应的教程进行

3.1.1 首先将训练集测试集合并:  

# 合并训练集和测试集
data = pd.concat([train, test], axis=0, ignore_index=True)
data = data.sort_values(['id', 'dt'], ascending=False).reset_index(drop=True)

3.1.2 

# 历史平移
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

3.2. 这里简单进行拓展

3.2.1 做一些统计特征:

window_columns = [f"last{i}_target" for i in range(10, 16)]  # 选择过去6个时间步

# 计算均值
data[f"win3_mean_target"] = data[window_columns].mean(axis=1)

# 计算最大值
data['win3_max_target'] = data[window_columns].max(axis=1)

# 计算最小值
data['win3_min_target'] = data[window_columns].min(axis=1)

# 计算标准差
data['win3_std_target'] = data[window_columns].std(axis=1)

# 计算中位数
data['win3_median_target'] = data[window_columns].median(axis=1)

3.2.2 计算滚动窗口均值和指数加权均值特征

def calculate_features(data):
    result = data.copy()

    batch_ids = data['id'].unique()

    for batch_id in batch_ids:
        # 按ID筛选数据
        chunk = data[data['id'] == batch_id].copy()

        # 计算滚动窗口均值和指数加权均值
        chunk[f"win10_mean_target"] = chunk['target'].rolling(10).mean().shift(10)
        chunk[f"ewm10_target"] = chunk['target'].ewm(span=13).mean().shift(10)

        # 更新原始 DataFrame
        result.loc[result['id'] == batch_id, [f"win10_mean_target", f"ewm10_target"]] = chunk[[f"win10_mean_target", f"ewm10_target"]]

    return result

这里:

        1. win10_mean_target: target 列的滚动窗口(窗口大小为10)的均值,并向前移动10个位置。           

        2. ewm10_target: target 列的指数加权移动平均值(跨度为13),并向前移动10个位置。  

这一步也可以多尝试不同的窗口大小。这一步是很费时间的,运行时间比较长,目前正在想有什么办法能够减少计算的时间。

四、 划分数据集并且使用 Lightgbm 训练

4.1 划分数据集

操作代码:

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']]

4.2 使用 Lightgbm 训练

操作代码:

import lightgbm as lgb
from sklearn.metrics import mean_squared_error
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': 8,
        'learning_rate': 0.05,
        'seed': 2024,
        'nthread' : -1,
        'verbose' : -1,
        'n_jobs': 64,
        'early_stopping_rounds': 500,
    }
    # 训练模型
    model = lgb.train(lgb_params, train_matrix, 25000, valid_sets=[train_matrix, valid_matrix], 
                      categorical_feature=[])
    # 验证集和测试集结果预测
    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, train1, test1, train_cols)

# 保存结果文件到本地
test['target'] = lgb_test
test[['id','dt','target']].to_csv('submit1.csv', index=None)

      这里我稍微改了几个参数,而且这一步训练模型,在百度的 Codelab 上面训练的好久都没训练出来,我在 Deepln 上面训练的,训练了大概8分钟左右就完成了,结果我忘了保存训练参数了,直接就拿 submit1.csv 提交了。

这是提交的成绩:

五、改进于反思的地方

1. 对于特征工程这一部分,还需要去了解更多的关于时间序列方面的别的做法,而且得益于 Lightgbm 我没有去处理缺失值,下面可以试着填充缺失值。   

2. 对于模型,还可以去尝试 Xgboost、catboost。使用深度学习的方法去预测,这里我持否定的态度,因为每个 id 下对应的 dt 最多才有496 个。

3. 还需要去了解更多模型的细节,以及如何知道模型训练的程度和 tqdm 库的使用。

完结。

 

 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值