586. Child Mind Institute - Detect Sleep States | child-mind-institute-detect-sleep-states
首先,衷心感谢儿童思维研究所睡眠状态检测竞赛的组织者。本次竞赛提供了处理长一维序列的宝贵机会,在数据科学的重要领域带来了独特而富有教育意义的体验。
我们的训练流程和模型基于@213tubo的优秀代码,可通过此页面访问。
我们训练了基于Unet的模型,采用五种不同的CNN骨干网络:ResNet101、MiT-B3、MiT-B5、ResNeXt101和ResNet152。模型使用两种不同的训练验证数据组合进行训练,每次分配约20%的训练集作为验证数据。
在每次模型训练中,我们改变种子值以增加多样性,从而提高交叉验证结果的可靠性并丰富提交集成。
对于输入数据分段,我们使用特定窗口大小,并将步长设为窗口大小的一半,创建重叠段进行推理。该方法有效利用了每个窗口的中心部分,减少了边缘段的误检测。
我们使用受加权框融合(WBF)启发的原创集成方法,算法步骤包括:
def ensemble_predictions(df_list: list, series_ids: list, step_threshold: int=50) -> pd.DataFrame:
grouped_list = [df.groupby(['event', 'series_id']) for df in df_list]
events = ["onset", "wakeup"]
ensemble_predictions = []
for series_id in series_ids:
for event in events:
sorted_group_list = []
for grouped in grouped_list:
if (event, series_id) in grouped.groups:
sorted_group_list.append(
grouped.get_group((event, series_id)).sort_values(by='score', ascending=False)
)
while any([not sorted_group.empty for sorted_group in sorted_group_list]):
specific_index = next(
(index for index, sorted_group in enumerate(sorted_group_list) if not sorted_group.empty), None
)
highest = sorted_group_list[specific_index].iloc[0]
ensemble_steps = [highest["step"]]
ensemble_probas = [highest["score"]]
probas_sum = highest["score"]
highest_step = highest['step']
for i, sorted_group in enumerate(sorted_group_list):
compared_prediction = sorted_group[
sorted_group['step'].sub(highest_step).abs() <= step_threshold
]
condition = sorted_group['step'].sub(highest_step).abs() > step_threshold
filtered_group = sorted_group[condition]
sorted_group_list[i] = filtered_group
if i != specific_index:
if not compared_prediction["score"].empty:
first_score = compared_prediction["score"].iloc[0]
first_step = compared_prediction["step"].iloc[0]
else:
first_score = 0
first_step = 0
ensemble_steps.append(first_step)
ensemble_probas.append(first_score)
probas_sum += first_score
ensemble_step = 0
if probas_sum != 0:
for s, p in zip(ensemble_steps, ensemble_probas):
ensemble_step += s * (p / probas_sum)
ensemble_predictions.append({
"series_id": series_id,
"step": int(ensemble_step),
"event": event,
"score": probas_sum / len(grouped_list)
})
ensemble_df = pd.DataFrame(ensemble_predictions)
ensemble_df['row_id'] = ensemble_df.index
return ensemble_df
对单模型和集成结果均实施了后处理步骤:
详细分数如下表所示:
| 编号 | 描述 | CV (Fold1) | Public LB | Private LB |
|---|---|---|---|---|
| (1) | ResNet101 (无重叠) | 0.756 | 0.722 | 0.748 |
| (2) | ResNet101 (重叠) | 0.77 | 0.732 | 0.778 |
| (3) | ResNet101 (重叠) + NMS | 0.773 | 未提交 | 未提交 |
| (4) | 5模型集成 (重叠, 同折) + NMS | 0.7844 | 0.753 | 0.790 |
| (5) | 5模型集成 (重叠, 同折) + NMS + 移除填充区间预测 | 0.7847 | 0.756 | 0.801 |
| (6) | 5模型集成 (重叠) 跨2折 + NMS | - | 0.749 | 0.792 |
| (7) | 5模型集成 (重叠) 跨2折 + NMS + 移除填充区间预测 | - | 0.753 | 0.802 |