返回列表

10th Place Solution

562. Predict Student Performance from Game Play | predict-student-performance-from-game-play

开始: 2023-02-06 结束: 2023-06-28 学习效果预测 数据算法赛
游戏学生表现预测第10名解决方案
比赛排名:第10名 | 最终得分:CV 0.70573 | Private LB 0.702 | Public LB 0.706

我尊重所有参赛者,你们在长期艰苦的战斗中表现出色,很高兴能与大家并肩作战。同时感谢我的队友(@tereka@deepkun1995@ryotak12@yurimaeda)的辛勤付出。

非常高兴这是我首次获得金牌!

解决方案概述

我们的解决方案没有特别之处:第一阶段使用1个神经网络、1个LightGBM和4个XGBoost模型(采用不同特征);第二阶段使用MLP和逻辑回归进行堆叠;第三阶段采用平均和阈值优化。

  • CV得分:0.70573
  • Public LB:0.706
  • Private LB:0.702
解决方案概览图

代码链接

模型详解

第一阶段:XGBoost(shu421部分)

我为每个level_group单独训练XGBoost模型。基础特征与公开代码相似,包括elapsed_time_diff和hover_duration的聚合特征及其他数值特征。此外,我还加入了前一个level_group的特征和预测概率作为当前level_group的输入特征。

使用numpy和numba实现特征工程(最初使用polars,后改用队友@yurimaeda的numba方案),提交时间从2小时大幅缩短至13分钟。采用5-StratifiedGroupKFold交叉验证策略。

  • CV得分:0.70111
  • Public LB:0.702
  • Private LB:0.699
XGBoost方案图

第二阶段:堆叠(Stacking)

为每个问题创建MLP和逻辑回归模型(共18个模型/类),每个模型输出维度为(n_samples, 1)。为避免过拟合,保持模型结构简单。

MLP实现代码:

class MLP(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super().__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.head = nn.Linear(hidden_size, output_size)
        self.dropout = nn.Dropout(0.2)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.relu(self.fc1(x))
        x = self.dropout(x)
        x = self.head(x)
        return x

第三阶段:阈值优化

对第二阶段两个模型的预测结果取平均值,并针对每个问题优化阈值:

import numpy as np
from sklearn.metrics import f1_score
from scipy.optimize import minimize

def f1_score_macro_for_thresholds(y_true, y_pred_prob, thresholds):
    y_pred_binary = (y_pred_prob > thresholds).astype(int)
    score = f1_score(y_true.flatten(), y_pred_binary.flatten(), average="macro")
    return score

def optimize_thresholds(y_true, y_pred_prob, method="Powell"):
    n_labels = y_pred_prob.shape[1]
    init_thresholds = np.full(n_labels, 0.6)

    objective = lambda thresholds: -f1_score_macro_for_thresholds(
        y_true, y_pred_prob, thresholds
    )
    result = minimize(
        objective, init_thresholds, bounds=[(0, 1)] * n_labels, method=method
    )

    return result.x

尝试多种优化方法后,Powell算法效果最佳,该方法使CV得分提升了0.008。

有效策略

  • 特征工程:
    • elapsed_time_diff和hover_duration的聚合特征至关重要
  • 阈值优化
  • 模型集成
  • LSTM + Transformer(ryota部分)
  • sort_frame技术

无效尝试

  • 1D CNN
  • Stacking(以下方法易过拟合):
    • CNN(1D/2D)
    • RNN
    • level_group预测
  • datetime聚合特征
  • 使用NN嵌入作为GBDT特征
  • 时间序列聚类(elapsed_time_diff)
  • 额外数据增强
同比赛其他方案