OpenADMET PXR Blind Challenge · 2026-04-01 → 07-01
Predicting PXR activation (pEC50) for 513 blinded compounds
Model report for OpenADMET PXR Challenge Track 1 (Activity) — N283T, final rank 4 of 95.
0. TL;DR
- OpenADMET PXR Challenge Track 1 (Activity) で 95 チーム中 4 位(Tier 1)。SMILES から PXR 誘導活性 (pEC50) を予測するタスクで、MAE は interim(AS1 + AS2)が 0.4059、最終の Phase 2(AS2)が 0.4113 でした。
- 勝負を決めたのは multi-fidelity transfer learning(Buterez et al. 2024 に基づく)という発想です。配布データには単一濃度で測った
log2fcの読み出しが補助データとして含まれており、pEC50 ラベルが 4,140 件なのに対して、log2fc は 10,875 化合物で測られています。その log2fc を予測した値が、単独で最強の特徴量になりました。 - その信号を中心に、9 メンバーの Caruana ensemble を組みました。メンバーは大きく 3 種類(tabular core、frozen embed、Boltz trunk)で、どれも TabPFN を readout head に使っています。
- アンサンブルから先で明確に効いたのは、affine calibration 1 つだけでした。Phase 1 終盤の tail gate と Phase 2 でやったことは、ほとんどがノイズか改悪です。どこで手を止めるかを見極められたことが、振り返れば良い判断のひとつでした。
1. The challenge
これは OpenADMET PXR Induction Challenge の Track 1 (Activity) に対するモデルレポートです。 チャレンジの背景・生物学的な文脈・ルール・スケジュールについては、公式のページを参照してください。
このレポートはモデリングの手法と結果に絞っています。探索的データ解析やチャレンジ自体の詳しい説明は範囲外とし、ここでは扱いません。
タスクの概要は Table 1 のとおりです。
| Item | Value | Notes |
|---|---|---|
| Target | pEC50 | higher is a stronger PXR inducer |
| Metric | MAE | regression task |
| Training set | 4,140 | labeled compounds |
| Analog Set 1 | 253 | unblinded at the start of Phase 2 |
| Analog Set 2 | 260 | blinded throughout |
| Test total | 513 | AS1 + AS2 |
2. Results
この課題のスコアは、主に 3 回出ています。live leaderboard は提出のたびに 更新されるので、あとから動かない結果と言えるのはこの 3 つです。
Phase 1 final AS1 (253)live LBrank 8
live leaderboard の最終スコア
Interim AS1 + AS2 (513)one-off LBrank 4 / 338
モデルは Phase 1 final と同じ
Phase 2 AS2 (260)no LBrank 4 / 95
最終順位 — AS1 のラベルは Phase 1 終了時に公開済み
順位を付けているのは MAE だけで、他の指標の順位は LB の値から数えたものです。
最終 LB の全体は、チャレンジの Hugging Face Space(Leaderboard タブ)で確認できます。主催者による記事は Phase 1 の結果とコンペ終了後のまとめです。
3. Strategy
戦略の土台にしたのは Buterez et al. の multi-fidelity 転移学習の論文です。 振り返ると、これにたどり着けたことが、この順位に届いた最大の理由のひとつでした。
The auxiliary data
最初は Train の pEC50 ラベルだけから特徴量とモデルを作っていました。しかし pEC50 のラベルは 4,140 件しかなく、精度はすぐ頭打ちになります。 一方で配布データには、単一濃度のレポーターアッセイ(8.25 µM と 33 µM の log2 fold-change、log2fc)が補助データとして含まれており、こちらは はるかに多くの化合物をカバーしています。この補助信号があること自体は分かっていたものの、 うまい使い方が分かりませんでした。擬似 pEC50 ラベルに変換するといった素朴なやり方は、 精度を下げるだけでした。
- 配布されるのは Train / Test / AUX data の 3 つ 揃っている項目はそれぞれ違う(Table 2)
- Test は SMILES のみ 実測値がないので Test で使える log2fc も存在しない
- log2fc は 2 濃度で測るので 1 化合物あたり 2 つの測定値
| Dataset | Compounds | SMILES | pEC50 | Emax | counter assay | log2fc 8.25 µM | log2fc 33 µM |
|---|---|---|---|---|---|---|---|
| Train | 4,140 | ✓ | ✓ | ✓ | 2,860 | 2,374 | 2,321 |
| Test | 513 | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| AUX data | 10,875 | ✓ | ✗ | ✗ | 2,359 | 10,752 | 9,527 |
Finding Buterez et al.
頭打ちを破るために、状況(pEC50 が乏しいこと、補助アッセイが潤沢にあること、擬似ラベル化が失敗していること)を そのまま書き出したリサーチ用プロンプトを Claude Code に作らせ、補助信号を活かす方法を尋ねました。 そのプロンプトを ChatGPT Deep Research にかけて出てきたのが Buterez et al. です。
What the paper compares
この論文が扱っているのは multi-fidelity な状況、つまり創薬スクリーニングの階層です。
論文の問いは、この安い側を、高い側の予測にどう活かすかです。その方法を 6 通り比較しています。
- 1生の LF ラベルを特徴量に足す10
- 2LF モデルが予測したラベルを足す3
- 3ハイブリッド — 学習は実測 推論は予測2
- 4LF モデルの embedding を足す10
- 5LF で事前学習して通常どおり fine-tune0
- 6LF で事前学習し readout だけ fine-tune26
右端の数字は、51 ケース中でその戦略が最良だった回数です。
論文の結論は、生ラベルを足すだけで MAE が 10〜40% 下がり、embedding はそれをさらに最大 10% 上回る、 というものです。
Adapting it
ここからが今回の話です。配布データは、論文が想定している設定にそのまま乗りました(Table 3)。
| Fidelity | 今回の対応物 | 件数 |
|---|---|---|
| high-fidelity | Train の pEC50 | 4,140 件 |
| low-fidelity | 単一濃度の log2fc | 10,875 化合物 |
論文と違うのは主に 2 点でした。
- 生ラベルが使えない — test に実測がないので 1と3は最初から選べない
- LF が桁違いに少ない — 論文は 100 万件以上 今回は 10,875 化合物
残るなかから採用したのが 2 と 4 です。
- 2予測値
log2fc_8p25_pred/log2fc_33_predを特徴量に足す - 4log2fc で事前学習した encoder の frozen embedding を渡す
そのうえで、論文には出てこない TabPFN を下流に置きました。Table 4 は、 encoder を同じ ChemProp (D-MPNN) に揃えて下流だけを入れ替えた比較です。
| Downstream | OOF MAE | Spearman |
|---|---|---|
| 4の embedding を TabPFN で読む | 0.437 | 0.807 |
| 6adaptive readout を学習(論文の一押し) | 0.482 | 0.758 |
| 5凍結せず直接 fine-tune | 0.507 | 0.755 |
凍結して下流を単純にするほど良くなりました。枠組みは論文のまま、下流だけ差し替えたことになります。
Predicted log2fc: the strongest feature
戦略 2 の中身です。単一濃度 log2fc を予測する ChemProp モデルを学習し、その予測値 2 列(8.25 µM と 33 µM)を 特徴量に足しました。本レポートではこれを pred log2fc と呼びます。 予測器の作り方は後述の ChemProp のメンバー説明で扱います。
Figure 1 の下段が pred log2fc です。上段の observed より pEC50 との連動が強く(r 0.75 / 0.80 対 0.72 / 0.50)、しかも observed はアッセイが走った化合物にしかありません。 予測に置き換えることで、被覆率の穴を埋めながら信号も滑らかになります。
Figure 2 で他の特徴量と並べても、pred log2fc の 2 列が先頭です。 記述子はどれも単独では弱く、モデルの中では pred log2fc の周りを固める文脈として働きます。
効いているのは精度だけではありません。pred log2fc は SMILES から計算できるので、 測定ラベルを一切持たない Test にも存在します。実測は Test では手に入らないので、 アッセイ由来の信号を採点対象の化合物まで届かせられるのは、予測した形だけです。
How far does pred log2fc alone get? post-challenge
信号の大きさを測るために、あえて単純なモデルをいくつか Train の pEC50 で学習し、 ブラインドが解除された Test(AS1 + AS2)で採点しました(Table 5)。比較先は、 RDKit 記述子一式に対するデフォルト設定の LightGBM です。
| Feature | Model | Dims | MAE | Spearman |
|---|---|---|---|---|
| pred 8.25 µM | linear | 1 | 0.609 | 0.782 |
| pred 33 µM | linear | 1 | 0.571 | 0.746 |
| pred log2fc (both) | linear | 2 | 0.572 | 0.725 |
| Boltz-2 affinity | linear | 1 | 0.747 | 0.602 |
| RDKit | LightGBM (untuned) | 217 | 0.570 | 0.677 |
| Phase 1 submission | ensemble | ~2,100 | 0.406 | 0.834 |
scripts/ablation_baselines.py)。最終行は物差しとして置いた Phase 1 の提出モデルです。pred log2fc は 1 列だけでも MAE 0.57〜0.61 に届き、2 列を素の線形回帰に通しただけで 217 次元の無調整 LightGBM に並びます(0.570)。順位相関ではむしろ上です(Spearman 0.72〜0.78 対 0.68)。いずれも Boltz-2 の affinity スコア(0.75)は明確に上回ります。 アッセイ由来の信号 1 本を予測しただけで、汎用記述子モデル 1 つ分の仕事をこなしているわけです。
4. The ensemble
最終的なシステムは 9 メンバーのアンサンブルです(Figure 3)。メンバー間で違うのは 特徴量の作り方だけで、大きく 3 種類に分かれます。
- tabular core — 記述子と pred log2fc を並べた 2,103 次元をそのまま渡す
- frozen embed — log2fc で事前学習した encoder を凍結し その embedding を渡す
- Boltz trunk — Boltz-2 の内部表現を渡す
- log2fc が入らない唯一の系統
readout head は全メンバー TabPFN で、 違うのはその手前だけです。
9 つのメンバーと、以降で使うエイリアスは Table 6 のとおりです。
| Alias | Encoder / features | Family | Strategy | OOF MAE | Weight |
|---|
CV 分割は UMAP クラスタ分割(Morgan FP + UMAP → KMeans)です。いくつか試したなかで public LB に最も近かったというだけで、 分割として優れているわけではありません。メンバーの統合には Caruana forward selection (Caruana et al., ICML 2004) を使いました。 提出したのはこのアンサンブルそのものではなく、出力に post-hoc な calibration と gate を重ねたものです(6. Calibration)。
How independent are the members? post-challenge
答えは「あまり独立ではない」です。全 36 ペアが 0.81〜0.98、平均 0.88(Figure 4)。 同じ log2fc を共有するメンバー同士が高いのは当然として、 log2fc をまったく持たない Boltz trunk ですら他と 0.81〜0.88 あります。 log2fc より強い手がかりが無く、使える情報がそもそも限られている、ということです。
ただしこれは test 予測どうしの相関で、Caruana が重みを決めた OOF の相関ではありません。 OOF で計算し直すと 0.90〜0.99、平均 0.93 になり、Boltz がやや低いという差も消えます。
それでもアンサンブルが効いている理由は、独立な視点を混ぜているからではなく buffer として働いているからです。重みの小さいメンバーを外すと系統シェアが 0.94 まで上がり、 public LB は 0.006 悪化しました。強いが相関の高いメンバー(とくに top500)が予測を支配するのを止めているわけです。 同時にこれは頭打ちの理由でもありました。新しいモデルを作っても高相関で弾かれるか、入れても悪化するターンが続き、 軸足を calibration と gate の工夫へ移すことになります。
5. The members
3 つの family を、エイリアスを使って順に開けていきます。単独 OOF MAE と重みは 4 章の表のとおりです。
5.1 Tabular core (tabular-full, tabular-top500)
重みが最も大きい 2 メンバーは、1 つの特徴量スタックを共有しています。 補完的なブロックを連結した、約 2,103 次元の tabular 行列です。
| Block | Dims | What it is |
|---|---|---|
| Mordred | 1,515 | 2D molecular descriptors |
| CheMeleon | 300 | ChemProp-MPNN foundation fingerprint |
| RDKit | 217 | standard RDKit descriptors |
| Boltz-2 tier-1 | 44 | pocket-level pLDDT / PAE / PDE re-aggregations |
| Boltz-2 tier-0 | 19 | pose, confidence, and affinity scalars |
| pose-Jazzy | 6 | H-bond / hydration on the Boltz pose |
| pred log2fc | 2 | the pred log2fc columns from Strategy (8.25 and 33 µM) |
CheMeleon
CheMeleon は単独では強くありません(CheMeleon だけを TabPFN で読むと MAE は約 0.512)。 それでもスタックに加えると明確に効き、同じ tabular core の MAE が 0.443 から 0.421 まで改善しました。
ただし、この 300 次元は実装ミスです。本来は CheMeleon 本体の 2,048 次元を使うつもりでしたが、 特徴量を作らせた Claude Code が、事前学習済みの 2,048 次元を未学習のままの 2048→300 射影に 通した値を保存していました。
コンペ後に 2,048 次元で検証したところ、正しく作っていても提出は良くなりませんでした。 単独では OOF が 0.5118 → 0.4983 と改善する一方 Test は 0.5099 → 0.5132 で、 スタックに混ぜた full でも悪化します。詳細は PR #233 を参照してください。
Boltz-2 features
Boltz-2 由来のブロックは 3 種類、合わせて 69 次元です(Table 8)。
| Block | Dims | What it is |
|---|---|---|
| tier-0 | 19 | Boltz が出力する affinity・結合確率・confidence のスカラー値 |
| tier-1 | 44 | トークン単位の confidence テンソル(pLDDT / PAE / PDE)を pocket や ligand 単位に再集約した統計量 |
| pose-Jazzy | 6 | Boltz の pose 上で計算したリガンドの水素結合・水和自由エネルギー(Jazzy) |
top-500 selection
TabPFN は入力の次元数に敏感なので、2,103 列をそのまま渡すのが最善とは限りません。 tabular-top500 は fold ごとに LightGBM gain で上位 500 列だけを選んで渡します(tabular-full はそのまま渡す方)。K を振ると 500〜600 で底を打ち(Figure 5)、 MAE が横ばいだったので Spearman が最良の 500 に決めました。
選択に LightGBM を使うと、解釈可能性も少し手に入ります。gain を見れば、何に依存していたかが分かるからです。 gain の約 4 分の 3 は 2 本の pred log2fc 列に集中し、残りが Mordred と CheMeleon に薄く広がっています(Figure 6)。 要するにこの選択器がやっているのは「pred log2fc の 2 列を残し、あとは記述子で空間を埋める」ことです。
個々の特徴量まで拡大すると、同じ話がもっと鮮明になります(Table 9)。pred log2fc の 2 列が大差をつけて 1 位と 2 位(gain の 52% と 22%)で、
それ以降は単独で 0.4% に届く特徴量すらありません。裾は CheMeleon の各次元と、
SLogP・qed・pose-Jazzy の水和項といった解釈しやすい記述子の混成です。
| Feature | Family | Gain share |
|---|---|---|
| log2fc_8p25_pred | pred log2fc | 51.6% |
| log2fc_33_pred | pred log2fc | 22.1% |
| chemeleon_067 | CheMeleon | 0.30% |
| chemeleon_006 | CheMeleon | 0.23% |
| chemeleon_175 | CheMeleon | 0.20% |
| chemeleon_131 | CheMeleon | 0.19% |
| SLogP | Mordred | 0.18% |
| sa | pose-Jazzy | 0.16% |
| chemeleon_002 | CheMeleon | 0.16% |
| qed | RDKit | 0.13% |
| dgtot | pose-Jazzy | 0.12% |
| chemeleon_240 | CheMeleon | 0.12% |
Why both?
単独性能はほぼ同じです(OOF 0.396 対 0.397)。問題は、選択の効果が OOF に限られていた疑いがあることです。 コンペ後に条件を揃えて比べると、top500 は OOF では 0.3968 と full の 0.4056 を上回る一方、 Test では 0.4327 対 0.4281 で逆転します (PR #233)。 fold ごとの選択そのものが OOF に効いてしまっている、と読むのが自然です。
当時そこまで分かっていたわけではありませんが、両方を抱えて Caruana が重みをほぼ均等に割ったこと(top500 が 0.309、full が 0.288)は、結果としてこのズレに対する保険になっていました。 実際、top500 側に寄せた入れ替え(id56)は OOF では最良に見えたのに、 public LB を 0.4071 から 0.4135 へ悪化させています。
公開された AS2 ラベルで重みを再最適化すると、同じことが数字で出ます(issue #222、Table 10)。 実際に使った 0.31 は AS2 最適の 0.33 に近い一方、OOF に合わせて最適化すると 0.84 まで膨らみ、 AS2 は 0.422 まで悪化します。
| Weighting | top500 weight | AS2 MAE |
|---|---|---|
| Our weights (as used) | 0.31 | 0.405 |
| Zero the top500 weight | 0.00 | 0.402 |
| Optimized on AS2 (oracle) | 0.33 | 0.399 |
| Optimized on OOF | 0.84 | 0.422 |
5.2 Frozen embeddings (ChemProp, KERMT, MoLFormer, GatedGCN, AttentiveFP)
この 5 つは、戦略 4 を backbone を替えて横展開したものです。 log2fc で事前学習した encoder を凍結し、取り出した固定長ベクトルを TabPFN に渡す(Adapting it)。encoder を pEC50 で fine-tune しないほうが良かったことは、 同じ節の Table 4 のとおりです。
ChemProp
ChemProp はこのレシピの原型で、embedding 系では最強のメンバーです。 しかも二重に効いています。同じ「log2fc を予測する ChemProp」が tabular core の pred log2fc 列を生み、その D-MPNN から取り出した 256 次元の frozen embedding が このメンバーになっているからです。同じ信号を、鋭い prediction と広がりのある representation の 2 通りで入れていることになります。
事前学習は、濃度ごとの回帰ヘッドを 2 つ持つマルチタスクです。13,136 化合物すべてを使い、 欠測はマスクします。ハイパーパラメータは Optuna で探索しますが、 目的関数は log2fc の損失ではなく下流の pEC50 OOF MAE です。
pred log2fc を鋭くしたのは seed averaging でした。複数シードで事前学習して予測を平均し、 5 → 10 シードで下流が改善(top500 の OOF MAE 0.399 → 0.397)、15 シードで頭打ちになったので止めています。
なお Table 4 の OOF は、frozen レシピの優位を過大に見せていました。 pEC50 で直接学習した ChemProp は OOF では約 0.53 と弱いのに、 Test では約 0.48 と、frozen embedding メンバーの 0.44 にかなり近づきます。 勝敗は変わりませんが、差は OOF が誇張していたわけです。
Foundation encoders: KERMT & MoLFormer
同じレシピを、より大きな事前学習済み backbone に適用したものです。
- KERMT — graph transformer
- log2fc で継続事前学習して 3,200 次元の embedding を取得 embedding 系では 2 番手(0.448 / 重み 0.111)
- MoLFormer — SMILES transformer(DeepChem MoLFormer-c3)
- log2fc に LoRA で事前学習し 凍結した 768 次元の [CLS] ベクトルを使用(0.475 / 重み 0.040)
同じレシピを通しても採用に至らなかった backbone もあります。ChemBERTa は OOF 0.53 前後、 UniMol-v2 は約 0.484 と残ったメンバーに迫る水準まで来ましたが、 どちらも Caruana の add-value 判定を通りませんでした。MoLFormer-XL を pEC50 に直接 fine-tune する路線も 0.529 と弱く、ここでも ChemProp と同じ結果です。
Extra GNNs: GatedGCN & AttentiveFP
同じ frozen レシピを、さらに 2 つの GNN backbone に適用したものです。いくつも試したなかで 成績が良かった 2 つ、というだけで、アーキテクチャ自体に意味はありません。 単独では弱く(0.474、0.484)、重みもごく小さい(0.017、0.002)です。
それでも残しているのは buffer だからです。約 0.02 の重みを削るとコア側で約 0.1 の増加に 増幅され、4 章のとおり LB が悪化します。重みが小さいことは、外して安全であることを意味しません。
5.3 Boltz trunk (Boltz-pocket, Boltz-allpairs)
この 2 つが使うのは Boltz-2 の trunk、つまり内部の学習済み representation で、予測構造は使いません。
当初は PXR(UniProt O75469、434 残基)を各リガンドと co-fold し、ポーズや affinity スコアから 活性を読むつもりでした。そちらは期待外れで、tabular core の弱い列として残るにとどまります(Table 7)。 そこで representation としての活用を考えました。
trunk の s と z を、化合物あたり 1,024 次元に
プーリングして TabPFN に渡します(Figure 7)。2 メンバーの違いは z に入れる範囲だけです。
- Boltz-pocket — 固定 13 残基の core pocket × リガンド原子
- Boltz-allpairs — 434 残基すべて × リガンド原子
s と z を 1,024 次元に落とすまで。s ブロック(768 次元)は 2 メンバーで共通です。
プーリングは 20 通り以上試しましたが、効いていたのは z のペア表現でした(Figure 8)。
128 次元の z だけで 0.490 と、全部入りの 0.486 に肉薄します。一方 s は 768 次元あっても 0.507。
リガンド単体の形より、残基とリガンド原子の関係が効いているわけで、
Boltz-2 自身の affinity module がペアを重視する設計とも符合します。
対して、どの残基で pool するかはほとんど効きません(pocket と allpairs で MAE の差は 0.001 以内、どちらも約 0.486)。
trunk の各次元には解釈可能な名前がないので、非線形な readout が効きます。 同じベクトルに対して TabPFN(0.486)が LightGBM と MLP(0.512、0.538)を上回りました。
一歩引くと、この 2 つは 9 メンバーで唯一 log2fc を持たないメンバーです。 他のすべてを支えている信号なしに約 0.486 まで届いたのは、素直にすごいと思います。 MoLFormer-XL を直接 fine-tune した路線が 0.529 止まりだったことと並べれば、なおさらです。
少なくともこの標的では、Boltz-2 は予測構造や affinity として使うより、 学習済みの representation として読むほうが価値がありました。 構造生成や長い diffusion を回さず trunk だけ取り出すなら軽く済むので、大きな化合物集合にも掛けられます。 ポーズを出す道具ではなく protein-aware な表現抽出器として使う、 という方向に可能性があるかもしれません。PXR 1 標的の結果なので、一般化を主張するのはまだ早いですが。
6. Calibration
発端は診断でした。Spearman・Kendall・R² は上位なのに、MAE と RAE だけが悪い。 どの化合物が強いかの並びは合っているのに、pEC50 のスケールと中心がずれている状態です。 メンバーを足すのではなく、出力を後から一次式で補正することにしました。
- 重みを作る — Morgan fingerprint で Train / Test を判別する分類器を作り
密度比 P(test|x) / (1 − P(test|x)) を化合物ごとの重みに
- [1/3, 3] へのクリップが必須 分類器が強すぎると少数の Test 似の化合物に引っ張られる
- 直線を引く — その重みで OOF 予測 4,140 件と正解ラベルから一次式をフィット(5-fold nested CV で検証)
- 傾きが正なので並び順は壊れず スケールと中心だけが動く
- Test に当てる — 同じ一次式を Test 予測にそのまま適用
- 使ったのは Test 化合物の構造だけで 正解ラベルは一切見ていない
How much did it buy? post-challenge
提出履歴の中では、calibration の効果とメンバー改善が混ざって見えます。そこで最終アンサンブル重みで raw と calibrated を同じ 1 回の実行から出し直しました(unblinded Test 513 件、Table 11)。
| Metric | Ensemble only | + calibration |
|---|
MAE は 0.4209 → 0.4077、bias は −0.056 → +0.002。 Spearman は 0.8370 のまま 1 つも動きません。単調変換なので当然ですが、 「順位は合っている」という診断に対する処方として筋が通っていることの確認でもあります。 AS1 が 0.4191 → 0.4076、AS2 が 0.4226 → 0.4078 と、どちらの分割でも同じ向きに効いています。
ただし全域で良くなるわけではありません。効いているのは主に高活性側です(Figure 9)。
予測の潰れも実際に広がっています。標準偏差は正解の 0.996 に対し、補正前 0.703、補正後 0.767。 強い化合物を低めに、弱い化合物を高めに出す癖が、一次式の分だけ戻った形です。
7. Gates
ここから先は研究ではなく競技の手さばきです。メンバーを差し替え、gate を足し、 提出して、下がったものを残す。public LB を見ながらの作業でした。 Phase 1 終盤の 11 提出が Figure 10 です。
最終提出の id55 は、補正済みアンサンブル(id51)に対して、 potent-46 に似た化合物だけを top500 メンバーの方向へ寄せたものです。
id55 = id51 + 0.35 * soft_gate(nn_tanimoto_to_potent46 >= 0.40)
* (seed10_top500 - ens_caruana_bag20)
- potent-46 — Test は強い誘導剤の analog set
- その帯の見本として Train から pEC50 ≥ 6 かつ counter assay に対する選択性 1.5 以上の 46 件を採用
- gate — Test 化合物ごとに potent-46 への Morgan 最近傍 Tanimoto を測り 近いものだけ開く
- 0.40 未満で 0 / 0.55 以上で 1 / その間は線形
- 硬い閾値だと境界で予測が跳ねる
- 寄せる量 — top500 メンバーと素のブレンドの差を 0.35 だけ加算
- 置き換えではないので gate が閉じている化合物は id51 のまま
id55 のあとも試しています(Optuna で調整したメンバー入れ替え id56、緩めた potent gate id57、 gate のランク版 id58・id59)が、どれも超えられず、まったく同じファイルを id60 として 出し直して Phase 1 を終えました。これが最終エントリです。
どれを足しても直らなかったのが tail です。pEC50 ≥ 6 の帯は系統的に低く出て、 その区間の bias は約 −0.8。平均方向へ 1 log 近く縮んでおり、大域的な calibration では届きません。 持ち上げも記述子 gate(log2fc、環数、ファミリーギャップ)も試しましたが、 public LB 上ではどれもノイズと区別がつきませんでした。Phase 1 で唯一そのまま残った課題です。
8. Phase 1 → Phase 2
Phase 1 は、LB に合わせに行くのをやめ、anchor をそのまま出し直して終えました。 当時は及び腰に見えましたが、ブラインドの最終採点は 95 中 4 位。 public LB に過剰適合しなかったことが、Phase 1 の良い判断のひとつでした。
Phase 2 は完全にブラインドで、手がかりになる public LB がありません。 答え合わせで見ると、加えた変更はすべて予測を悪い方向へ動かしていました(Figure 11)。
Phase 2 では、おもに次の 3 つの操作を行いました。
- AS1 ラベルでの再学習 — 公開された AS1 を学習データに足して top500 を学習し直し
その予測を anchor に 0.45 混合
- AS1 の追加はほとんどのメンバーで AS2 を改善せず 混ぜた分だけ誤差が入った
- 高活性 gate — 外部の ChEMBL と公開 PXR 活性から
pairrank のランキングモデルを作成(ペアで学習する Boltz-2 の affinity head に倣った設計)
- 検出は AUC 約 0.88 と良好
- どれを動かすかが分かっても どれだけ動かすかは分からない
- 幅を外した損が ランキングで稼いだ分を超えた
- 低活性側は外すリスクが大きいと判断して回避
- 結果として正解だった
ただし「動かさなければよかった」という話でもありません。提出しなかった候補
id55shape_t10top500_t40_soft_g35 は AS2 で 0.4056、
優勝の 0.4061 を下回っています。動かす値が多く、自前の preflight を通らなかったので見送りました。
並べると、動かさない id60 が 0.4075、大きく動かした id55shape が 0.4056、
その中間の id63 が 0.4123。一番悪いのは中途半端に足したものでした。
とはいえ LB がない以上、どちらに賭けるかを提出時点で見分ける手段はありません。
ブラインドの難しさはそこです。
コンペ後の完全な解答照合 (issue #222) では、 LB を一度も見ずに組んだ anchor-residual stacker がテスト全体で約 0.405 に着地し、 importance calibration 版アンサンブル(0.407)も Phase 2 の提出もすべて上回りました。 ある地点から先は、足した仕掛けが得よりも損を生んでいた、ということです。
9. Conclusion
SMILES から pEC50 を当てる課題では、最終的に 95 チーム中 4 位でした。 技術的に効いたのは 3 つ、そしてもう 1 つは、深追いしなかったことです。
- Transfer learning — 少ない Train を 多い log2fc で補う
- 生のラベルより 全件で使える pred log2fc のほうが強い
- 直接 fine-tune ではなく 凍結した encoder の embedding
- TabPFN as readout — 特徴量の作り方は違っても
9 メンバーすべて最後に読むのは TabPFN
- readout を固定したので 表現の良し悪しをそのまま比べられた
- Calibration — メンバーを足すより 出力を後から直すほうが効いた
- 補正は OOF の予測と真値で学習
- Test はラベルではなく構造だけを重み付けに使う
- Knowing when to stop — 動かすかどうかの判断そのもの
- Phase 1 は動かさなかったのが吉
- Phase 2 は動かしたのが裏目
個人的な話をすると、これは私にとって初めてのコンペで、95 中 4 位は始める前に期待していた以上の結果でした。 振り返って印象に残っていることが 2 つあります。1 つは、文献探索・coding・壁打ちのいずれでも AI Coding Agent と ChatGPT に大きく頼り、そのワークフローから多くを得たことです。 これについては別の記事できちんと書きたいと思っています。もう 1 つは、 この全体が個人の家庭用ゲーミング PC 1 台で、しかも 1 人で回っていたことです。 その環境で 95 チーム中の Tier 1 まで届いたのは、自分でも意外で、少し誇らしく思っています。
最後に、PXR Induction Challenge を運営してくださった OpenADMET チームに感謝します。 取り組みがいのある課題設計で、期間中の案内や対応も終始丁寧でした。 終了後にデータとブラインド解除済みのラベルまで公開していただけたおかげで、 本文の事後検証も答え合わせもできています。ありがとうございました。
Reproducibility and links
- このレポートの Markdown 版: MODEL_REPORT.md
- 発表スライド(HTML, 42 枚): スライド版
- 作業リポジトリ(コード / 特徴量パイプライン / 日々のログ): N283T/pxr-iduction-challenge
- Phase 1 の研究ログ: issue #100
- Phase 2 の研究ログ: issue #208
- コンペ後の AS2 答え合わせログ: issue #222
- チャレンジページ: openadmet/pxr-challenge
- データ: openadmet/pxr-challenge-train-test
- 同梱ソフトウェアのライセンス: レポート / スライド