【Kaggle】练习赛《洪水数据集的回归预测》(下)

文章讲述了如何通过针对特征相似且相关性低的洪水数据集,采用深度学习的MLP模型并结合统计量特征工程,实现R2分数从0.846提升至0.86887的过程,强调了改变传统特征选择方法的重要性。
摘要由CSDN通过智能技术生成

前言

上篇《洪水数据集的回归预测》(上) 介绍了该数据集非常特殊之处,各特征都非常类似,没有特别之处,各特征之间的相关系数几乎为零。同时,各类模型不敏感,最理想的模型居然是线性回归,决定系数 R 2 R^2 R2,也只有 0.846。对这样的一个问题,我们如何突破呢?

方向一

既然线性模型效果相对于其他模型算是较好的,因此我们选择深度学习的MLP【多层感知器(multilayer Perceptron)】模型进行尝试,核心代码如下,

数据归一化

sc = preprocessing.StandardScaler()
X_scaled=sc.fit_transform(X) 
X_valid_scaled = sc.transform(X_valid)
test_scaled = sc.transform(test)
建模
model = Sequential() 
model.add(Dense(64, kernel_initializer = 'normal', activation = 'relu',
input_shape = (20,))) 
model.add(Dense(64, activation = 'relu'))
model.add(Dense(32, activation = 'relu'))
model.add(Dense(1))

第一个版本,中间层只有 64 一层

编译
model.compile(
   loss = 'mse', 
   optimizer = RMSprop(learning_rate=0.0005),  
   metrics =  ['mean_absolute_error']
)

这里选择 RMSprop 做为优化器,我尝试过用 Adam 效果差不多,同样,这里的学习率也可以做适当的调整。

训练
history = model.fit(
   X_scaled, y,    
   batch_size=128, 
   epochs = 500, 
   verbose = 1, 
   validation_split = 0.2, 
   callbacks = [EarlyStopping(monitor = 'val_loss', patience = 20)]
)

6988/6988 ━━━━━━━━━━━━━━━━━━━━ 13s 2ms/step - loss: 3.5157e-04 - mean_absolute_error: 0.0147 - val_loss: 3.5295e-04 - val_mean_absolute_error: 0.0146
Epoch 147/500
6988/6988 ━━━━━━━━━━━━━━━━━━━━ 13s 2ms/step - loss: 3.5114e-04 - mean_absolute_error: 0.0147 - val_loss: 3.6086e-04 - val_mean_absolute_error: 0.0145

第一版本,训练数据和验证数据分别 用train_test_split方式来进行训练
采用早停的方式来终止训练,这里共训练了147次,MSE 可以达到0.0145~0.0146之前

LOSS 结果
plt.plot(history.epoch,history.history.get('loss'),label="loss")
plt.xlabel("epoch")
plt.ylabel("MSE")
plt.legend()

在这里插入图片描述

查看验证结果
y_valid_pred = model.predict(X_valid_scaled)
r2_score(y_valid,y_valid_pred)

0.8628182472445698

0.8628,这个结果大大的超过了预期,第一个版本成绩为0.859,因此就选用了这个标题了,现在所展示的是第二个版本,具体详见 完整代码

以下是我当天提交结果

在这里插入图片描述

正当以为找到方案一,调整模型层数和相关参数提升模型效果时,很快发现又出称瓶颈(0.8645),不得不需要找到另外的突破的方式。

方案二

在上篇留了一个坑 ,也在总结 写到"如果直接用上述的数据建模的话, R 2 R^2 R2 的上限不太可能会突破0.85",尽管方案一突破了0.85 ,来到了0.86 这个区别,难道不能上0.87 那个区间吗。因此,我们突破常规思路,必须从数据集入手,有效的进行特征工具(FE),提升这些特征的有效性。

上文提到那些特征没有特色,具体普遍性,而机器学习在寻找特征的基本思想就是找出与别人不一校样的东西,如果一组数据没有波动,也不能称之为特征,因此,需要我们找出不一样的波动的东西,顺着这个思路,我们把以上原有特征的统计量给找出来,看看能发现什么。

选择统计量分析
# 求出相关的统计量,并删除原特征
def cleaning(dataset):
    features = dataset.columns.tolist()
    dataset['mean_features'] = 0.1*dataset[features].mean(axis=1)
    dataset['std_features'] = dataset[features].std(axis=1)
    dataset['max_features'] = dataset[features].max(axis=1)
    dataset['min_features'] = dataset[features].min(axis=1)
    dataset['median_features'] = 0.1*dataset[features].median(axis=1)
    # just keep the descriptive statistics
    dataset = dataset.drop(features, axis=1)

    return dataset
# 将原始数据和训练数据合并
dataset = pd.concat([original_data, train_data.drop('id', axis=1)], ignore_index=True)
X = dataset
X = X.drop(["FloodProbability"], axis=1)
X = cleaning(X)
y = dataset["FloodProbability"]
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats

# Plot scatter plots and regression lines for each feature in separate plots
for i, col in enumerate(X.columns):
    plt.figure(figsize=(6, 4))  # Create a new figure for each feature
    
    # Scatter plot and regression line
    sns.regplot(x=X[col], y=y, color='darkturquoise', 
                line_kws={'color': 'red'}, 
                scatter_kws={'alpha': 0.5})  # Set alpha for dot transparency
    
    # Calculate linear regression
    slope, intercept, r_value, p_value, std_err = stats.linregress(X[col], y)
    
    # Add title including the regression coefficients
    plt.title(f'{col} vs Target\nSlope: {slope:.2f}, Intercept: {intercept:.2f}')
    
    # Setting labels
    plt.xlabel(col)
    plt.ylabel('Target')
    
    plt.show()

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们惊奇的发现,这些统计量与目标值【FloodProbability】居有具较强的相关性。
以此为起点,我们以上述统计量为特征,进行建模分析。
以下没有优化的结果如下

模型原始特征 R 2 R^2 R2统计量特征的 R 2 R^2 R2
LinearRegression0.8454600.84561
Lasso-5.51093-5.51093
Ridge0.8454600.84561
ElasticNet-5.51093-5.51093
SVR0.696670.78454
RandomForestRegressor0.653940.86045
XGBRegressor0.809420.869125
LGBMRegressor0.7671980.869094
CatBoostRegressor0.846690.869264
DL-MLP0.8628180.865859

以上表数据均为验证集的结果,未进行提交的成绩。

为了取得更好的成绩,我们将最好的三个模型进行融合。

xgb_pred = xgb.predict(test_t)
lgb_pred = lgb.predict(test_t)
cat_pred = cat.predict(test_t)
sample['FloodProbability'] = (xgb_pred+lgb_pred+cat_pred)/3
sample.to_csv("submit_melt.csv",index=None)

详见 notebook

最终,提交到竞赛中得到 0.86887的成绩,截止发稿,最好成绩为0.86932。
在这里插入图片描述

到这里暂告一段落,要想继续提升我们的成绩,还是有一定的空间,有几个方向供小伙伴参考

  • 上述的三个模型都是采用默认参数的方式,都可以进行 optuna 进行优化,参照我的几篇文章,如《肥胖风险的多类别预测》的 Optuna 进行微调部分。
  • 在融合方式中可以用不同权重进行优化。
  • 模型训练时可以用5折交叉验证来提升模型的泛化能力。

总结

  1. 写这篇文章的初衷,是为了一种思维的突破,改变原先常规的特征基础,选用统计量作为特征,这是我在以往所没有碰到过的,基于这一点,拿来分享给大家。
  2. 这种方法其实是有条件的,并非所有的题目都可以这样,只有当这些特征具有以下特点是,如所有特征具有共同的特性,并其相关性为零,特征量不太少,用一般的树形模型没法提升时。
  3. 每个数据集基于特征都有一个理论上限,如果已接近这个天花板时,就需要改变原先的特征,像本题,是一种完全改变的方式,除此之外,有扩展,PCA等方式。
    以上这些观点是我自己的感受和体会,并非一定正确,如有不想法和建议,欢迎评论。
  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值