ROSETTA Candidate Search (RCS)
脳領域名のテキスト入力から HOMBA 候補を返す RCS の「スコア」がどのように算出されるかを、
前処理から最終ランキングまで順を追って説明します。
実装は rcs/rosetta_candidate_generator.py(v0.3.1)に基づきます。
RCS は単一の入力テキスト(例: Subthalamic nucleus、Left basolateral amygdala (BLA)、LC)を
HOMBA オントロジーのエントリと照合し、適合度スコア付きで候補リストを返します。
スコアは 0〜1 の浮動小数点数です。出力時は min(score, 1.0) を
小数第 6 位で四捨五入します。
_score_candidate() を適用 → 暫定スコア prelim_scores
hierarchy_parent)
alias 展開 · abbrev 展開 · laterality 除去 · 修飾語が同時に働く複合例は、 クエリバリアント全件・バリアント別 fuzzy ヒット・候補リストなどの詳細データを 別ページに分離しています。
→ Left basolateral amygdala (BLA) — 処理フロー詳細
この例で確認できること:
homba_alias_rules.csv による amygdala↔amygdaloid complex 等の展開homba_abbrev_rules.csv による BLA → basolateral nuclear group of amygdalabla と abbrev 展開の判定差(modifier ×0.88)修飾語の加点・減点だけを短く追う例は §16 例 D、前処理の一般説明は §3 を参照してください。
normalize_text)& → and、/ → スペース' ` ´)を除去例: Broca's area → broca s area(所有格のアポストロフィは削除)
query_variants)1 つの入力から複数の検索用文字列を生成し、表記ゆれに対応します。生成は次の順序で行われ、最後に unique_preserve_order() で正規化キーの重複を除去します。
homba_alias_rules.csv を適用(単語置換・同義語追加)homba_abbrev_rules.csv を適用(略語展開 · クエリ側のみ)各段階のすべての中間文字列(重複含む)の実例は BLA walkthrough §2-2 を参照してください。
left / right / bilateral 等)を除去した形modifier_terms として別途保持)excluding / except / without 以降を除去した形homba_alias_rules.csv による同義語展開(クエリ側)homba_abbrev_rules.csv による略語展開(クエリ側のみ。例: lc → locus coeruleus)extract_modifier_terms)括弧内トークンと、homba_token_rules.csv で kind=modifier と定義された語を収集します。
これらは後述の修飾語一致率の計算に使われます。
tokenize)正規化後に空白分割し、kind=stopword の語を除去します(of、the、region 等)。
トークン Jaccard や BM25、fuzzy のインデックス絞り込みに使用します。
同一 HOMBA エントリが複数手法でヒットした場合、エントリは 1 つに統合され、
各手法のスコアは 最大値 が保持されます(_add_candidate)。
| 手法 | methods 値 | 概要 | 候補化条件 | 手法スコア |
|---|---|---|---|---|
| 完全一致 | exact |
正規化後のクエリバリアントと HOMBA 別名が完全一致 | 常に候補 | 1.0 |
| あいまい一致 | fuzzy |
文字列類似度(後述) | スコア ≥ 0.45 | 0.45 〜 1.0 |
| BM25 トークン検索 | bm25 |
トークン共起ベース(語順に頑健) | 正規化 BM25 > 0 | 0 〜 1(正規化後) |
| 階層親昇格 | hierarchy_parent |
兄弟候補から親を推論 | 子候補 2 件以上 | 後述(最大 0.97) |
generate() のデフォルト引数: top_k=10(返却件数)、per_method_k=40(各手法の上位候補数上限)。
全別名(約 9,000 件)に毎回フルスキャンしないため、起動時に以下のインデックスを構築します。
| インデックス | 用途 |
|---|---|
alias_map | 正規化別名 → HOMBA エントリ index(exact 用) |
alias_entries | 別名ごとのトークン列・頻度(fuzzy / BM25 用) |
token_to_entries | トークン → 別名 entry index の posting list |
_bm25_doc_freq | 各トークンの document frequency(df) |
rarest_limit=2)を選択例: Subthalamic nucleus では subthalamic(df≈3)と nucleus(df≈1,400)の積集合 ≈ 3 件のみ比較。
旧 UNION 方式だと ≈ 1,400 件になっていた。
| 手法 | トークン選択 | 集合演算 | フォールバック |
|---|---|---|---|
| fuzzy | レアな 2 トークン(3 トークン以上のとき) | INTERSECTION | 積集合が空 かつ 長さ > 5 → 全スキャン |
| bm25 | 全トークン | UNION | なし |
| exact | — | alias_map 直接参照 |
— |
string_similarity)正規化後の 2 文字列を比較します。完全一致なら 1.0。
similarity = max( containment_bonus, 0.35 × SequenceMatcher.ratio + 0.25 × bigram Dice + 0.20 × trigram Dice + 0.20 × token Jaccard )
| 成分 | 計算方法 | 重み |
|---|---|---|
| SequenceMatcher.ratio | Python difflib.SequenceMatcher の文字列類似比 |
0.35 |
| bigram Dice | 空白除去後の 2-gram 集合について 2|A∩B| / (|A|+|B|) |
0.25 |
| trigram Dice | 同上(3-gram) | 0.20 |
| token Jaccard | stopword 除去後トークン集合の |A∩B| / |A∪B| |
0.20 |
| containment_bonus | 一方が他方の部分文字列(長さ ≥ 4)のときmin(0.92, len(短)/len(長) + 0.25) |
max の別項 |
max() の候補として比較されます。
部分一致(例: 短いクエリが長い別名に含まれる)を拾うためのボーナスです。
エントリ内の複数別名それぞれに BM25 を計算し、最も高い別名のスコアをそのエントリの bm25 スコアとします。
| k1 | 1.5 — 語頻度の飽和度 |
| b | 0.75 — 文書長正規化の強さ |
| 正規化定数 | 4.0 — 生スコアを 0〜1 に圧縮 |
IDF(t) = log(1 + (N - df(t) + 0.5) / (df(t) + 0.5)) BM25_raw = Σ_t IDF(t) × (freq × (k1+1)) / (freq + k1 × (1 - b + b × doc_len / avg_len)) × query_count(t) BM25_norm = BM25_raw / (BM25_raw + 4.0)
N = 全別名エントリ数(alias_entries の件数)df(t) = トークン t を含む別名数avg_len = 別名の平均トークン長(起動時に計算)freq = 当該別名内のトークン出現回数query_count(t) = クエリ内のトークン出現回数_score_candidate)各候補について、クエリ全体と HOMBA 全別名の token Jaccard 最大値を token_score とします。
base = max( hierarchy_parent_score, // 未設定なら 0 exact_score, // 未設定なら 0 0.5 × fuzzy + 0.3 × bm25 + 0.2 × token_score, 0.75 × fuzzy + 0.25 × token_score )
exact が存在する場合: base = max(base, 0.96) — 完全一致候補の下限を引き上げStep C — 過細減点の順で適用します(次セクション参照)。
modifier_match_score = 抽出した修飾語のうち、候補別名テキスト(正規化・連結)に
含まれる割合(0〜1)。修飾語がない場合は 1.0(調整なし)。
| 条件 | 調整式 |
|---|---|
| 修飾語なし | 調整なし |
| 修飾語あり & 一致率 > 0 | base + 0.12 × modifier_match_score(上限 1.0) |
| 修飾語あり & 一致率 = 0 | base × 0.88(上限 0.88) |
修飾語 posterior, limb が抽出される。
候補別名に posterior limb が含まれれば一致率が上がり加点。
含まれない候補は最大 0.88 に抑えられる。
クエリに存在しない細分類語(inferior、lateral、core、shell、
molecular 等)が候補側の別名に含まれる場合、スコアを減点します。
exact マッチがないfuzzy または bm25 マッチがあるmodifier_terms)がないparent_id)がある候補別名の specificity 語 \ クエリの specificity 語 が空でない → final_score × 0.86 それ以外 → final_score × 1.0(減点なし)
specificity 語は homba_token_rules.csv の kind=modifier または kind=weak に該当するトークンです。
exact マッチで見つかった候補(クエリが別名を直接指している)hierarchy_parent のみで昇格した候補(昇格スコアが既に子の penalized score を反映)hierarchy_parent)
複数の子領域(兄弟)が同時に候補になったとき、共通の親エントリを追加します。
例: thalamus の複数サブリージョンが候補 → pulvinar of thalamus の親を昇格。
parent_id を持つ子候補が 2 件以上hierarchy_parent_score = min(max(子候補の prelim_scores) + 0.08, 0.97)
prelim_scores は第 1 パスで算出した過細減点込みの暫定スコアです。
生の fuzzy スコア(例: 0.89)だけで親を昇格させると、ペナルティ後 0.77 の子を
0.97 の親が上回る「過昇格」が起きるため、暫定スコアを参照します。
親昇格スコアと子の final score の間に循環依存があるため、2 段階で処理します。
1. exact / fuzzy / bm25 で候補収集(手法別最大スコアを保持) 2. 第1パス: 全候補に _score_candidate() → prelim_scores(specificity_penalty 込み) 3. prelim_scores で _promote_common_parents() → hierarchy_parent 候補を追加 4. 第2パス: 昇格後の全候補を再度 _score_candidate() で最終スコア化 5. ソート → top_k 件を返却
hierarchy_parent 候補にも、
合成式・修飾語調整・penalty ルールを適用して最終順位を確定するため。
2-pass の計算コストは fuzzy 比較に比べ小さい。
score 降順name 昇順(小文字化して比較)homba_id 昇順| フィールド | 説明 |
|---|---|
score | 最終マッチスコア(0〜1、6 桁丸め) |
methods | ヒットした手法(+ 区切り。例: bm25+fuzzy) |
matched_query | 照合に使われたクエリバリアント |
matched_alias | 一致した HOMBA 側別名 |
modifier_terms | 抽出修飾語(; 区切り) |
modifier_match_score | 修飾語一致率(0〜1) |
hierarchy_reason | 階層昇格理由(該当時のみ。例: common_parent_of_3_candidates) |
best_method_score | 単一手法の最高生スコア(内部デバッグ用に出力) |
rcs/review.py)
generate() の出力自体には含まれませんが、テスト・API 層では
add_review_flags() により以下のフラグが付与されます。
| フラグ | 条件 |
|---|---|
modifier_conflict |
修飾語あり かつ modifier_match_score < 1.0 |
high_confidence |
score ≥ 0.90(上記より優先度低) |
low_confidence |
score < 0.60 |
needs_review |
上記以外(0.60 ≤ score < 0.90) |
| パラメータ | 値 | 用途 |
|---|---|---|
| fuzzy 閾値 | 0.45 | これ未満は fuzzy 候補から除外 |
| fuzzy rarest_limit | 2 | INTERSECTION 用に選ぶレアトークン数 |
| fuzzy 全スキャン条件 | 積集合空 & バリアント長 > 5 | フォールバック |
| string_similarity 重み | 0.35 / 0.25 / 0.20 / 0.20 | Sequence / bigram / trigram / token Jaccard |
| containment_bonus 上限 | 0.92 | 部分文字列ボーナス(長さ ≥ 4) |
| containment 加算項 | + 0.25 | len(短)/len(長) に加算 |
| BM25 k1 | 1.5 | 語頻度飽和 |
| BM25 b | 0.75 | 文書長正規化 |
| BM25 正規化 | raw / (raw + 4.0) | 0〜1 圧縮 |
| 合成式 1 | 0.5·fuzzy + 0.3·bm25 + 0.2·token | base の候補 |
| 合成式 2 | 0.75·fuzzy + 0.25·token | base の候補 |
| exact 下限 | 0.96 | exact ヒット時の base フロア |
| 修飾語加点係数 | 0.12 | × modifier_match_score |
| 修飾語不一致倍率 | 0.88 | 一致率 0 のとき(上限 0.88) |
| specificity_penalty | 0.86 | 過細語が余分にあるときの乗算 |
| 親昇格ボーナス | + 0.08 | max(子 prelim_scores) に加算 |
| 親昇格上限 | 0.97 | hierarchy_parent_score のキャップ |
| per_method_k | 40(デフォルト) | 各手法の候補数上限 |
| top_k | 10(デフォルト) | 返却候補数 |
| スコア丸め | round(..., 6) | 出力精度 |
| high_confidence | ≥ 0.90 | レビューフラグ |
| low_confidence | < 0.60 | レビューフラグ |
Subthalamic nucleussubthalamic nucleusexact_score = 1.0exactsubthalamic nuc(略称・typo 想定)string_similarity ≈ 0.82 と仮定nucleus vs nuc で Jaccard 低下)needs_reviewthalamus、候補 inferior thalamusinferior(weak 語)がありクエリにない → × 0.86min(0.675 + 0.08, 0.97) = 0.755 で昇格候補にLeft basolateral amygdala (BLA)15 バリアント・alias/abbrev 展開・修飾語 bla の詳細フローは BLA walkthrough 詳細 を参照。
BLA → abbrev 展開で basolateral nuclear group of amygdala が多数のバリアントに追加amygdala → amygdaloid complex 等、alias_rules も複数バリアントを生成bla は別名文字列に含まれないため modifier_match_score = 0 → 全候補 ×0.88