485. NBME - Score Clinical Patient Notes | nbme-score-clinical-patient-notes
首先,我要感谢竞赛主办方举办了这场有趣的比赛。也要感谢我伟大的队友 @zzy990106,我们在过去的一个月里共同讨论并努力探索新方法。同时感谢社区提供的优秀 Notebooks 和讨论。
我们使用了基于 这个优秀 Notebook 的基线模型。
我们使用了以下模型:
在使用基线进行训练之前,这些模型都在未标记数据上进行了预训练,这同时提升了交叉验证分数 (+~0.005) 和 公榜 分数。
伪标签 (PL) 是基于上述模型的集成生成的。为了避免 CV 泄漏,我们使用单折 (single fold) 来生成 PL。详情请参阅 这里。
在训练过程中,我们在每个 epoch 随机抽取 10万条 PL 数据并与训练数据结合。
在进行错误案例分析时,我们发现了如下不匹配的情况:
j 在预测中丢失了。这种情况只发生在单词不以空格开头的时候。因此我们修改了后处理代码:
def get_results_with_text(char_probs, texts, th=0.5):
results = []
for char_prob, text in zip(char_probs, texts):
result = np.where(char_prob >= th)[0] + 1
result = [list(g) for _, g in itertools.groupby(result, key=lambda n, c=itertools.count(): n - next(c))]
tmp_result = []
for r in result:
# print(r)
min_r = min(r)
max_r = max(r)
if min_r > 0 and text[min_r - 1] != ' ':
# print(text[min_r])
min_r -= 1
tmp_result.append(f"{min_r} {max_r}")
tmp_result = ";".join(tmp_result)
results.append(tmp_result)
# result = [f"{min(r)} {max(r)}" for r in result]
# result = ";".join(result)
# results.append(result)
# break
temp = []
for pred in results:
if len(pred)>0 and pred[0:2] == '1 ':
pred = '0' + pred[1:]
# print(pred)
temp.append(pred)
results = temp
return results
这可以同时提升 CV (+0.001~0.002) 和 LB (+0.001)。
在比赛的最后阶段,我们认为所使用的基线模型没有考虑到同一 case num 下 features 之间的关系。经过讨论,@zzy990106 提出我们可以使用多分类。因此,我们编写了一个带有 143 个分类头 (143个特征) 的新流程。
对于这个新流程,我们将每个 pn_num 文本视为一个样本。因为我们有额外的 PL 数据(约 40000 个样本),所以可以让模型训练得更好。否则,训练数据集仅包含 1000 个样本