返回列表

#16th Place Journey Writeup - No Magik

462. Google Brain - Ventilator Pressure Prediction | ventilator-pressure-prediction

开始: 2021-09-22 结束: 2021-11-03 临床决策支持 数据算法赛
第16名参赛历程分享 - No Magik

第16名参赛历程分享 - No Magik

作者:عثمان (Grandmaster)
比赛:Ventilator Pressure Prediction
排名:16th Place

虽然我喜欢技术性的文章,但我一直发现了解人们的思维方式更有益。如果我能像他们一样思考,也许将来我就能模仿他们。所以在这里,我将按照承诺分享我的参赛历程。虽然这需要更多时间,我想鼓励我的 Kaggle 伙伴们也考虑以这种方式组织他们的文章……为了我个人的利益 =P。

当我的朋友 @adityaecdrid 邀请我参加这场比赛时,我和 @gunesevitan 正在 RSNA 比赛中苦战。虽然这个问题领域感觉很棒(帮助人们生存!),这吸引了我,但我的心最初更倾向于 NFL 头盔映射比赛,因为我觉得我会在那里学到更多。此外,在做数据科学咨询时,我实际上在现实中见过该问题的变体。回想起来,纵观该比赛的多篇获胜方案,包括批量配准、透视变换和自定义训练的目标检测模型,我坚持在这里可能是明智的,因为两周的时间不足以让我在那个领域具有竞争力。尽管我确实相信我会在 DS/工程理解上有所进步……

RSNA 分割模型的训练花费了大量时间,所以在它们训练的同时,我开始探索这个比赛的数据集。

我注意到的第一件事是呼气阶段中 u_in 的一致性(硬编码)。因为我打算将其建模为 seq2seq 问题,输入 A -> 不同的变量对我来说没有太大意义,所以我选择完全切断 u_out=1 的数据(2/3 的数据)并仅在吸气阶段进行训练,这大大加快了迭代时间。很久以后,在查看了论坛上的一些 EDA 后,我添加了一些工程化的呼气特征,例如模式等:

EDA Image

图片由 @patrick0302 提供

在查看了一些公共内核后,我确定了一个 4 层 BiLSTM 网络。我在架构上花了很多时间,可能比我应该花的还要多。更改归一化的顺序、归一化的类型、激活的类型、节点的大小、不同的池化操作等。

class CustomModel(nn.Module):
    def __init__(self, num_inputs):
        super().__init__()

        self.pos_embed = nn.Parameter(torch.zeros((1,CFG.CHOP,3)))
        self.mode_embed = nn.Embedding(2, 2)
        
        self.gdrop = GaussianDropout()
        self.lstm1 = nn.LSTM(num_inputs+3+2, 700, batch_first=True, bidirectional=True)
        self.lstm2 = nn.LSTM(700 * 2, 512, batch_first=True, bidirectional=True)
        self.lstm3 = nn.LSTM(512 * 2, 256, batch_first=True, bidirectional=True)
        self.lstm4 = nn.LSTM(256 * 2, 128, batch_first=True, bidirectional=True)
        
        self.pressure = nn.Sequential(
            nn.LayerNorm(256),
            nn.SELU(),
            nn.Linear(256, 256),
            GeM(p_trainable=True),
            ScaleLayer(),
        )

        self.delta_pressure = nn.Sequential(
            nn.LayerNorm(256*2),
            nn.SELU(),
            nn.Linear(256*2, 256),
            nn.AdaptiveAvgPool1d(1),
        )
        
        self.delta_delta_pressure = nn.Sequential(
            nn.LayerNorm(512*2),
            nn.SELU(),
            nn.Linear(512*2, 256),
            nn.AdaptiveAvgPool1d(1),
        )
        
        for n, m in self.named_modules():
            if isinstance(m, nn.LSTM):
                print(f'init {m}')
                nn.init.xavier_normal_(m.weight_ih_l0)
                nn.init.orthogonal_(m.weight_hh_l0)
                nn.init.xavier_normal_(m.weight_ih_l0_reverse)
                nn.init.orthogonal_(m.weight_hh_l0_reverse)

        nn.init.xavier_normal_(self.pressure[-3].weight)
        nn.init.xavier_normal_(self.delta_pressure[-2].weight)
        nn.init.xavier_normal_(self.delta_delta_pressure[-2].weight)

    def forward(self, cont_seq_x, emb_x):
        seq_emb = torch.cat((
            cont_seq_x,
            self.pos_embed.expand(cont_seq_x.shape[0],CFG.CHOP,3),
            self.mode_embed(emb_x[:,[0]]).expand(cont_seq_x.shape[0],CFG.CHOP
同比赛其他方案