データ分析メモ

主にデータ分析のことについて書きます。

NBME - Score Clinical Patient Notes 振り返り

はじめに

2022年参加した分析コンペの記録 第3弾です.
今回は銀メダル獲得することができました(Private 39th)

NBME - Score Clinical Patient Notes とは

NBME - Score Clinical Patient Notes | Kaggle

NBMEが主催したコンペで、解くべきタスクは「患者の問診メモから症例に関する重要な要素を抽出する」 ことでした.
標準化された患者(特定の臨床例を描写するように予め特訓を受けた人)の問診メモに対し,
「家族の病歴」や「動悸・息切れ」などの症例にあたる箇所の文字列でのindexを予測します.

例えば 患者の問診メモ.
17 y/o M , Dillon Cleveland comes with c/o of palpitaions. Palpitaions are sudden onset ond have been occuring for the last 3-4 months. He has had 1-2 episodes of palpitaions every month. The last episode was accompanied by breathlessness and constricting pressure over chest which releived on its own. No aggravating or relieving factors. No h/o fever, pedal edema, cough, hemoptysis. no h/o of dyspnoea, orthopnoea. no h/o weight loss, tremors. PMH; not allergic to any medications. no known allergies. No similar episode in hte past. Psh; no history Family h/o; Mother has thyroid condition, father had acute MI last year. Social drinker . Sexaully active with girlfriend sincea a year. No h/o STD.

症例の特徴
Family-history-of-MI-OR-Family-history-of-myocardial-infarction

が与えられた場合に、予測するのは
17 y/o M , Dillon Cleveland comes with c/o of palpitaions. Palpitaions are sudden onset ond have been occuring for the last 3-4 months. He has had 1-2 episodes of palpitaions every month. The last episode was accompanied by breathlessness and constricting pressure over chest which releived on its own. No aggravating or relieving factors. No h/o fever, pedal edema, cough, hemoptysis. no h/o of dyspnoea, orthopnoea. no h/o weight loss, tremors. PMH; not allergic to any medications. no known allergies. No similar episode in hte past. Psh; no history Family h/o; Mother has thyroid condition, father had acute MI last year. Social drinker . Sexaully active with girlfriend sincea a year. No h/o STD.
になります. (正確には該当箇所が先頭文字から xx番目~yy番目 のindexでF1 Scoreが評価指標)

私は、英語のリスニング問題みたいな設定だなと思っていました.
最初に設問である症例の特徴を読んでから問診メモを読むと、正解箇所がとてもよく理解できました.
与えられていたデータは下記の通りです.
患者メモ: 42,146件
症例: 143例
1人の患者メモに複数の症例が入っていますので、全体としては612,602件の患者メモと症例がセットになったデータが与えられていました.
ただし、その中で正解キーワードが与えられているのは14,300件ほどしかなく、testデータも20,000件が対象となっていたようです.
つまり与えられているデータのほとんどがラベルがつけられていない状態であり、このデータをうまく活用することが肝であるように思いました.
上位解法でもラベルが与えられていないデータを活用し全体の精度を上げるように工夫されている人が多く、
kaggleでよく使われるPseudo-Labelingがうまく作用したと思います.

また、人がアノテーションをしているため与えられているラベルでも揺れが大きかったです.
具体的には had, hasなどの動詞が抜けていたり、アノテータによってつける箇所がバラバラでしたが
どのアノテータがつけたかなどの情報はないため, 全てを正解させることができないようなデータでした.

コンペ期間中はCVとLBが綺麗に相関しており、その辺りは非常に取り組みやすかったです.
ただしコンペ終盤で複数modelのensembleをしてからはCVが上昇してもLBは思ったほど伸びず
この辺りにアノテーションの揺れなどが絡んでいるかもと考えていました.

やったこと

Solution図

コンペ序盤~中盤

序盤から、nakamaさんによる強強ベースラインが公開されていましたのでそちらを基に改良を加える方針で取り組んでいました.
NBMEコンペの前に行われていたNLP系のコンペ Feedback PrizeからDeBERTa-v3系のモデルが使われ始め、NBMEでもDeBERTa-v3-Largeのモデルを主流に取り組むことにしました.
これまではNLPであれば、RoBERTaが初手で試すモデルとして有力でしたが潮流が少し変わったように思います.

序盤はDeBERTa-v3-BaseやDeBERTa-v3-Large, RoBERTa-Largeなどの新旧強いとされているモデルで,
HeadのカスタムやLabel Smoothingなど分類問題で良く使う手法を広く試していました.

この時点で作成したモデルのCVの結果はこちらです。

BackBone CV LB
DeBERTa-Base 0.8629 0.864
DeBERTa-Large 0.8755 0.879
DeBERTa-v3-Base 0.8590 0.861
DeBERTa-v3-Large 0.8810 0.883
DeBERTa-Base x LSTM 0.8611 0.864
DeBERTa-Base x Conv1D 0.8654 0.864
DeBERTa-Base x Layer Concat 0.8617 -
DeBERTa-Base x Multi Sample Dropout 0.8648 0.865
DeBERTa-Base x Label Smoothing Loss 0.8614 -
DeBERTa-Base x Layer Freeze 0.8689 0.866
RoBERTa-Large 0.8714 0.873

実験を素早く行えることから、DeBERTa-Baseを中心に効果ありそうかどうかの見極めを行っていました.
RoBERTaはcharacterレベルの予測をするとtokenizerの都合上indexがズレるという指摘もあり,
trim_offsets=False で使用していました.

ただ、この時LBで上位チームは0.890近くのスコアを出しており何か学習方法やデータでやり方を大きく変えないと追いつけないと感じていました.

コンペ中盤~終盤

LBで上位を走っていたtheoさんのtrain.logの情報から、trainデータだけではなくannotationがされていないデータも使っていることが判明しました.
Pseudo Labelingによってannotationがされていないデータに対して、学習したモデルでの予測ラベルを擬似的に使用し学習する方針へとシフトすることに.
ただし、他のFoldの影響が入らないように Fold1で学習したモデルで全てのデータを予測し、
Fold1のtrainデータ + Fold1で学習したモデルで予測したデータ を作成し学習することにしました.
この学習方法により、DeBERTa-v3-Largeで CV 0.8810 -> 0.8859 へと大幅に向上させることが出来ました.

また、LBのスコアもかなり密で詰まってたこともあり個々のSingle Modelでの精度向上が必要と感じ
MLM(Masked Language Modeling)による事前学習も実施しました.

このPseudo LabelingとMLMによって、RoBERTa-Largeでも十分精度を伸ばすことができ
CV 0.8714 -> 0.8852 へと上がりEnsembleでも使用できそうなモデルを育てるところまで至りました.

今回はこのMLMとPseudoがかなり効いていましたが,それはデータの性質が大きく影響すると考えています.
患者メモに書かれている内容や構造が似ていることや、trainだけで学習したデータでも十分精度が高く得られることから
上手くハマったと思いますが、今後他のNLP系タスクであってもとりあえずMLMは試すと思います.

私はRoBERTa-LargeでCV 0.8852を出して喜んでいましたが、その間にチームメンバーの方が同様の方法で強強Single Modelを具備されていました.

BackBone CV
DeBERTa-v3-Large 0.8904
DeBERTa-v3-Large 0.8926
RoBERTa-Large 0.8903

あとはこれをEnsembleしていくことで精度向上を図っていましたが、この時点で CV 0.89253 LB 0.889 で 0.890の壁にぶち当たっていました.

後処理

Ensembleを進めることによってCVとLBが徐々に乖離し始め, このままでは最終subも選ぶのも難しく
またOOFで当たっていないデータに着目すると Tokenizerが上手く単語を切れてないケースに対応できていないことが分かりましたので
ルールベースの後処理によって外れているケースへの対応を考え始めました.

tokenizerによって先頭文字が抜けるパターンというのは、下記のようなケースです.

本来は, mom has thyroid が正解なのですが、momの先頭のmとその前の文字:との間にスペースがなく
単語が不自然に切られているケースで一文字分取りこぼしています.

同様のケースとして、-ThyroidのTが抜けるパターンもありました.

これに対し、我々のチームで取り組んでいたのは

  • 正規表現パターンで患者のメモを分割して単語化
  • 予測した文章が単語途中から始まってる場合は、単語先頭まで補完

という手法です.

この後処理によって CV 0.8881 -> 0.8899 LB 0.887 -> 0.889 へとSingle Modelで向上することができ、Ensembleで LB 0.890 へと伸びました.
ただしここからは色々後処理のルールベースを追加してもCVは上がるけどLBが下がるということが続き
CVとLBが相関していそうなデータだったので CV向上 LB向上 したルールを採用する方針にしました.

CV, LB両方にきくルールを見つけるため当たっていないデータは逐次見ながらルール作って取り組んだものの
最後まで両方に効果的なものは追加できず で終了しました.

ルールベースの後処理は, 非常に地道な作業ですがスコア管理もしやすいメリットがあるので
Deepでポンだけでなくpython実装力も同時に身につけていく必要があると改めて感じています.

最終日付近になり, subのバリエーションを増やしたいということで
全データを使ったmodelを加えました.

結果的にはこの全データ学習modelが最後追加されたことでLB 0.891を達成できたので取り組んで良かったと思います.

全データ学習はCV計算ができないので正直使い所が難しいですが、今回はPsuedo Labeling込みのデータで1epoch回すとおよそ収束することから
全データ学習モデルを加えるに至りました.

最終的なスコアは以下の通りです。

Model CV
DeBERTa-v3-Large 0.8904
DeBERTa-v3-Large 0.8926
DeBERTa-Large 0.8876
RoBERTa-Large 0.8903
DeBERTa-v3-Large all train

結果

Public 0.891 Private 0.891で39thでした.
スコアがかなり密なので, 順位はShakeするかと思いましたが無事Shake Upして銀メダル獲得できたので安堵しています.

所感

DeBERTa-v3-Largeがかなり強く、初手で試すモデルが変わるかもしれないと感じています.
MLM->Pseudo->後処理 と順々に精度が上がる取り組みを続けられ、最後までスコアを伸ばせたことは非常に良かったです.
上位に入った皆様の考えや試したことなども今後まとめていきたいと思います.
また、チームで参加してくれたメンバーにも非常に感謝しています.
これで銀メダルx2 銅メダルx3で、Masterまで金メダルという非常に大きなハードルを残すのみとなりましたが
引き続き精進していきます.