Evo 2 の内部表現をスパースオートエンコーダで読む¶

第 1 部 — ゲノムトラックと立体構造への読み出し¶

Evo 2 は, 次の塩基の予測を事前学習タスクとしてゲノム配列で訓練されたゲノム言語モデルです. その計算の途中で, 1 塩基につき 4096 次元のベクトルを作ります. これを埋め込み (embedding) と呼びます. $N$ 塩基を通せば $N$ 行 × 4096 列の行列になり, その行がゲノム座標に対応します.

ただし, この 4096 個の数値をそのまま眺めても, 各次元が配列のどのような性質を捉えているのかは読み取れません. 1 つの性質が多数の列にまたがって表現され, 逆に 1 つの列が複数の性質に関わっているためだと考えられます. このうち後者を多義性と呼びます. 読みにくいのは次元ごとに切り分けたときの話で, 埋め込み全体では PCA で意味的なクラスタが見えますし, 変異効果予測などの下流タスクにも使えます.

スパースオートエンコーダ (Sparse Auto-Encoder, SAE) は, この 4096 次元ベクトルを, 32768 本のベクトルからなる辞書の線形結合として表し直します. 辞書の要素数が次元数より多い過完備な構成をとり, 係数のほとんどが 0 になるように学習されています. 過完備であれば 1 本のベクトルが複数の性質を兼ねる必要がなくなるので, 1 本が 1 つの性質に対応することを期待できます. この 32768 本を特徴 (feature), その係数を活性 (activation) と呼び, 活性が 0 でないことを発火といいます. もとは信号処理や神経科学のスパースコーディングにある手法で, LLM の解釈可能性研究のなかで発展し, ゲノム言語モデルにも同じように使えます.

本ハンズオンでは, Evo 2 の埋め込みを SAE にかけて特徴を取り出します. 前半で SAE を動かし, 後半でその特徴をゲノムと立体構造の上に読み出します. 題材には Evo 2 論文 Fig. 4 の大腸菌の解析を使います.

Evo 2 論文 Fig. 4

Brixi et al. Nature 2026, Fig. 4a-d より. CC BY-NC-ND 4.0

節との対応は次の通りです.

節 題材 内容
04 Fig. 4c ORF・遺伝子間・tRNA・rRNA に対応する特徴
05 Fig. 4d tRNA アレイと tufB, rpoB-rpoC, および立体構造
06 Fig. 4b プロファージと CRISPR スペーサー
07 — 任意の座位を自分で見る

特徴の探し方は 第 2 部, 対応がどこまで確かかは 第 3 部 で扱い, 補足は 付録 にまとめています.

対象は大腸菌 Escherichia coli K-12 MG1655 (NC_000913.3) の 4,162,560-4,193,280, 30,720 bp です. rrnB リボソーム RNA オペロン, tRNA アレイとその隣の tufB, rpoB-rpoC を含みます. 論文 Fig. 4c が示す 100 kb (4,130,000-4,230,000) の内側にあり, Fig. 4d の 2 つの座位 (4,175,250-4,177,250 と 4,181,000-4,189,650) をどちらも含みます.

01. 準備¶


ライブラリと, このハンズオン用のパッケージ evo2_sae (GitHub) を入れます. evo2_sae には配布データの取得, ゲノムトラックの描画, 立体構造の描画がまとまっています. データは Hugging Face Hub にあります. evo2_sae.setup に渡した場所から落とし, data/ に残します. 活性行列は全ゲノムぶんあるので, 必要な範囲を都度取り出します.

ファイル サイズ 内容
region_emb.pt 252 MB Evo 2 の埋め込み. 大腸菌ゲノムの 30,720 塩基ぶん
ecoli.bed 0.2 MB ゲノム全体の遺伝子座標
proteins.json と PDB 6 件 2.9 MB 7 つのタンパク質の座標, DSSP, 立体構造
ecoli_values.f16 ほか 2 本 2.4 GB SAE の活性行列
In [1]:
# Colab には torch と huggingface_hub が入っている. 手元で動かす場合は別途入れる
%pip install -q git+https://github.com/GenAIBio/evo2-sae-handson

import numpy as np
import pandas as pd
import torch
import matplotlib.pyplot as plt

import evo2_sae
evo2_sae.setup("https://huggingface.co/datasets/suzuki-2001/evo2-sae-handson/resolve/main")

02. Evo 2 の埋め込みを見る¶


region_emb.pt には, Evo 2 (7B) の blocks.26 から取り出した埋め込みが入っています. 1 塩基が 1 行, 各行が 4096 列です. いくつかの次元をゲノム座標に沿って表示し, この行列が密で読み取りにくいことを確かめます.

In [2]:
d = torch.load(evo2_sae.download("region_emb.pt"), map_location="cpu")
x = d["emb"].float()
start, end = d["start"], d["end"]
chrom = d["accession"]

# まずは埋め込みのテンソルを見てみる
print(d.keys())
print(d["emb"])
print(f"{tuple(x.shape)}")
print(f"{chrom}:{start:,}-{end:,}")
print(f"Model: {d['model']}, Layer: {d['layer']}")
downloading region_emb.pt
dict_keys(['emb', 'accession', 'start', 'end', 'model', 'layer'])
tensor([[-0.2266, -0.3711,  0.1055,  ...,  0.2617,  0.1768, -0.2188],
        [ 0.6250, -0.0342, -0.3398,  ..., -1.1875,  0.9062, -0.4277],
        [ 0.1543, -0.5703, -0.1611,  ..., -0.3242,  0.1680, -0.1445],
        ...,
        [ 0.3516,  0.1260, -0.7734,  ..., -0.1494, -0.4551, -0.1846],
        [-0.1147,  0.4258, -0.5664,  ..., -0.6094, -0.4414, -0.4707],
        [-0.5078, -0.5117, -0.0923,  ..., -0.0117,  0.3301,  0.4023]],
       dtype=torch.bfloat16)
(30720, 4096)
NC_000913.3:4,162,560-4,193,280
Model: evo2_7b, Layer: blocks.26

4096 次元の値がどう分布しているかを, ヒストグラムで見ます.

In [3]:
value = x.flatten().numpy()

fig, ax = plt.subplots(figsize=(6.2, 3.4))
ax.set_facecolor("#f7f7f7")
ax.hist(value, bins=300, range=(-1.5, 1.5), color="#334155")
ax.set_title("Evo 2 blocks.26", fontsize=11)
ax.set_xlabel("Value")
ax.set_ylabel("Count")
for spine in ax.spines.values():
    spine.set(linewidth=1.4, color="black")
plt.show()
No description has been provided for this image

1 列を取り出せば, ゲノム座標に沿った数値列が得られます. これをゲノムトラックとして表示します. CoolBox は bedGraph をトラックとして描画するため, 座標と値が対応していれば任意の数値列を表示できます.

アノテーションは ecoli.bed から読みます. 大腸菌ゲノム全体を対象とし, RefSeq の CDS・tRNA・rRNA に加えて, CRISPR アレイのリピートとスペーサー, プロファージを含みます.

In [4]:
#@markdown 表示する次元. コンマ区切りで 5 本まで指定できる (0 から 4095)
dims = "0, 100, 2000, 4000"  #@param {type:"string"}

chosen = [int(i) for i in dims.split(",")][:5]

counts = {}
for r in evo2_sae.overlapping(0, 5_000_000):
    counts[r["kind"]] = counts.get(r["kind"], 0) + 1
print("ecoli.bed  " + ",".join(f"{k} {n}" for k, n in sorted(counts.items())))

embedding = evo2_sae.Region.from_matrix(chrom, start, x)
embedding.show(
    [(i, "#334155", f"embedding dim {i}") for i in chosen],
    floor=False,
)
downloading ecoli.bed
ecoli.bed  ORF 4340,prophage 6,rRNA 22,repeat 20,spacer 18,tRNA 86
Out[4]:
No description has been provided for this image

どの列も細かく変動し, 周期的な起伏やピークがあります. ただしその変動は下のアノテーションと対応せず, 遺伝子の境界も rRNA オペロンも, どの列からも読み取れません. ここで見たのは 4096 次元のうち数本なので, 対応する次元があるかどうかは分かりません.

03. SAE を通して特徴を読む¶


SAE には Goodfire が公開している チェックポイント を使います. Goodfire は AI の解釈可能性研究を専門とするアメリカの企業です. 創業者の一人 Tom McGrath は 2019 年から 2023 年まで Google DeepMind にいた研究者で, Goodfire の発表では DeepMind の解釈可能性チームを立ち上げた人とされています. 視覚概念の多様体を扱う Block-Sparse Featurizer (Fel et al. 2026) や, Evo 2 の埋め込みから変異効果を予測する EVEE (Pearce et al. 2026) の研究もこの企業が主導したものです. 公開されているチェックポイントは Evo 2 論文で使われたものです.

この SAE は, 4096 次元の埋め込みを 32768 個の係数に変換します. 重みは $4096 \times 32768$ の行列 $\mathbf{W}$ 1 枚で, 冒頭で述べた辞書とはその各列のことです.

In [5]:
from huggingface_hub import hf_hub_download

ckpt = hf_hub_download(
    "Goodfire/Evo-2-Layer-26-Mixed",
    "sae-layer26-mixed-expansion_8-k_64.pt"
)
sd = torch.load(ckpt, map_location="cpu")

W = sd["_orig_mod.W"].float()
b_enc = sd["_orig_mod.b_enc"].float()

print(f"W {tuple(W.shape)}   b_enc {tuple(b_enc.shape)}")
Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.
sae-layer26-mixed-expansion_8-k_64.pt: reconstructing file:   0%|          |  0.00B /  537MB            
sae-layer26-mixed-expansion_8-k_64.pt: downloading bytes:           |  0.00B            
W (4096, 32768)   b_enc (32768,)

エンコードは 2 段で, まず ReLU を通し, 次に BatchTopK で大きいものを残します. BatchTopK は, 通した $L$ 塩基ぶんの活性をまとめて並べ, 大きい順に $k \times L$ 個を残して残りを 0 にする操作です. 塩基ごとに $k$ 個ずつ取るのではないので, 1 塩基あたりの個数は平均 $k$ 個を保ったまま増減します. このチェックポイントは $k = 64$ で, ファイル名の k_64 がそれにあたります.

K = 64

def batch_topk(a, k):
    floor = torch.topk(a.flatten(), k * a.shape[0]).values.min()
    return torch.where(a >= floor, a, torch.zeros_like(a))

A = torch.relu(x @ W + b_enc)
Z = batch_topk(A, K)

30,720 塩基すべてを通すと A と Z が無料の Colab の RAM に収まりません. 同じ手順で計算した活性を配布してあるので, ここではそれを読み込みます.

In [6]:
region = evo2_sae.Region.from_genome(chrom, start, end)

1 塩基あたり 0 でないのは 64 個, 32768 列の 0.2% です. 4096 列すべてが値を持っていた埋め込みが, 少数の特徴に置き換わりました. 以降で使う特徴の番号もここで定義します.

まず, 論文が rRNA に対応する特徴として挙げている f/2812 をトラックに表示します.

In [7]:
# Evo 2 論文が挙げている特徴のインデックス
# Fig. 4c
F_ORF, F_INTERGENIC, F_TRNA, F_RRNA = 13606, 26069, 30262, 2812
F_HELIX, F_SHEET = 28741, 22326  # Fig. 4d
F_PROPHAGE = 19746  # Fig. 4b

# CRISPR のリピートに対応する特徴は論文に挙がっていないので, 第 2 部の探索で選んだ
F_REPEAT = 1261
In [8]:
region.show([(F_RRNA, "#059669", f"f/{F_RRNA}  rRNA")])
Out[8]:
No description has been provided for this image

rrnB オペロンの上で発火し, その外ではほぼ 0 です. アノテーションを与えずに学習した特徴の発火範囲が, リボソーム RNA 遺伝子とほぼ一致しています.

ただしこの例では, 表示する特徴の番号が論文から分かっていました. 番号が分かっていない場合は, 32768 個の中から rRNA に対応するものを探す必要があります. 探し方は第 2 部で扱います.

04. ORF・遺伝子間・tRNA・rRNA に対応する特徴 (Fig. 4c)¶


論文の Fig. 4c は, ORF・遺伝子間・tRNA・rRNA の特徴を 100 kb の領域に並べたものです. 番号は論文が挙げているものを使います.

In [9]:
fig4c = [
    (F_RRNA, "#059669", f"f/{F_RRNA}  rRNA"),
    (F_TRNA, "#7c3aed", f"f/{F_TRNA}  tRNA"),
    (F_INTERGENIC, "#ea580c", f"f/{F_INTERGENIC}  intergenic"),
    (F_ORF, "#2563eb", f"f/{F_ORF}  ORF"),
]

region.show(fig4c)
Out[9]:
No description has been provided for this image
In [10]:
region.show(fig4c, 4_166_000, 4_172_500)
Out[10]:
No description has been provided for this image

rrnB オペロンを拡大すると, 16S (rrsB), 23S (rrlB), 5S (rrfB) の 3 遺伝子とその間のスペーサーが分かれて見えます. rRNA の特徴は 3 遺伝子すべてで, 遺伝子間の特徴はスペーサーで, tRNA の特徴はスペーサー内の gltT で発火します.

ここまでは配布した 30 kb の埋め込みを使ってきました. 全ゲノム 4.64 Mb ぶんの活性は行列にして配布してあり, Region.from_genome に座標を渡すと, 必要な範囲だけが取り出されます.

Fig. 4c の 4 つを, まだ見ていない領域で表示します. rrnA は別の rRNA オペロンです.

In [11]:
rrnA = evo2_sae.Region.from_genome(chrom, 4_035_000, 4_041_200)
rrnA.show(fig4c)
Out[11]:
No description has been provided for this image

先ほどまで見ていた領域から 120 kb 以上離れた場所でも, 同じ特徴が同じ性質に対応しています. 16S (rrsA) と 23S (rrlA) の上で rRNA の特徴が, その間のスペーサーで遺伝子間の特徴が, スペーサー内の tRNA 遺伝子 (ileT, alaT) で tRNA の特徴が発火します. 以降の節でもこれらの特徴を使っていきます.

05. tRNA とタンパク質の二次構造 (Fig. 4d)¶


論文の Fig. 4d は 2 つの座位を並べています. 左が tRNA アレイ (thrU, tyrU, glyT, thrT) と隣接する tufB, 右が RNA ポリメラーゼの $\beta$ 鎖と $\beta'$ 鎖にあたる rpoB-rpoC です. tufB は翻訳伸長因子 EF-Tu をコードします. 各座位について, ゲノムトラックと立体構造の両方が示されています.

ゲノムトラック¶

重ねる特徴は 3 つで, 論文は f/30262 を tRNA, f/28741 を $\alpha$ ヘリックス, f/22326 を $\beta$ シートに対応するものとして挙げています. 後の 2 つは二次構造に対応するので, コード領域の内部で構造に沿って発火が変化します.

In [12]:
fig4d = [
    (F_TRNA, "#1e3a8a", f"f/{F_TRNA}  tRNA"),
    (F_HELIX, "#2563eb", f"f/{F_HELIX}  alpha-helix"),
    (F_SHEET, "#f59e0b", f"f/{F_SHEET}  beta-sheet"),
]

region.show(fig4d, 4_175_250, 4_177_250)
Out[12]:
No description has been provided for this image

f/30262 は 4 つの tRNA 遺伝子の上でのみ発火し, tufB に入ると下がります. f/28741 と f/22326 は逆に, tufB のコード領域に入ってから変動し始めます. 入力は DNA 配列だけですが, tRNA 遺伝子とタンパク質コード領域はモデルの内部で分かれています.

In [13]:
region.show(fig4d, 4_181_000, 4_189_650)
Out[13]:
No description has been provided for this image

rpoB-rpoC では, 二次構造に対応する 2 つの特徴が細かく入れ替わります. いずれも $\alpha$ ヘリックスと $\beta$ シートが入り混じったタンパク質であり, その交替がトラックの変動に対応します. 座位ごとの最大活性を数値でも確かめます.

In [14]:
span = {
    r["name"]: (r["start"] - start, r["end"] - start)
    for r in evo2_sae.overlapping(start, end)
}
loci = ["rrsB", "rrlB", "thrT", "tufB", "rpoB", "rpoC"]
paper = {
    F_RRNA: "rRNA",
    F_TRNA: "tRNA",
    F_HELIX: "alpha-helix",
    F_SHEET: "beta-sheet",
}

rows = []
for feature, label in paper.items():
    track = region.track(feature)
    row = {"特徴": f"f/{feature}", "対応": label}
    row.update({g: round(float(track[span[g][0]:span[g][1]].max()), 2) for g in loci})
    row["全域平均"] = round(float(track.mean()), 3)
    rows.append(row)
pd.DataFrame(rows)
Out[14]:
特徴 対応 rrsB rrlB thrT tufB rpoB rpoC 全域平均
0 f/2812 rRNA 5.09 6.79 0.0 1.18 0.66 1.18 0.524
1 f/30262 tRNA 1.17 0.92 2.4 0.00 0.00 0.00 0.008
2 f/28741 alpha-helix 0.00 0.66 0.6 1.60 3.79 2.74 0.035
3 f/22326 beta-sheet 0.00 0.00 0.0 3.19 3.37 3.59 0.052

立体構造に載せる¶

ここまでは活性をゲノム座標に沿って見てきました. 同じ活性を立体構造の上に配置すると, 二次構造の特徴がどの残基で発火しているかを見られます.

終止コドンを除けば, コドンと残基は 1 対 1 に対応します. 遺伝子が + 鎖にあり, 残基が $N$ 個あるとき, 残基 $i$ に対応するゲノム座標は

$$p_i(k) = \mathrm{start} + 3(i-1) + k, \qquad i = 1, 2, \dots, N, \quad k = 0, 1, 2$$

の 3 つです. 残基番号は 1 から始まるので, $3(i-1)$ が遺伝子の先頭から数えた塩基数にあたります. そこで, 残基ごとの活性をこの 3 塩基の平均として定義します.

$$a_i = \frac{1}{3}\sum_{k=0}^{2} z_f\!\left(p_i(k)\right)$$

対象のタンパク質は 7 つ用意しました. tufB・rpoB・rpoC が論文 Fig. 4d のもので, 残りは二次構造の組成が対照的なものです.

遺伝子 残基 H E 産物
tufB 394 24% 37% 翻訳伸長因子 EF-Tu
rpoB 1342 33% 25% RNA ポリメラーゼ $\beta$ 鎖
rpoC 1407 39% 19% RNA ポリメラーゼ $\beta'$ 鎖
pspA 222 91% 0% ファージショックタンパク質 A
ompG 301 1% 66% 外膜ポリン OmpG
crp 210 38% 30% cAMP 受容体タンパク質
groL 548 51% 18% シャペロニン GroEL

H と E は DSSP による割合です. pspA はほぼ全長がヘリックス, ompG はほぼ全長がシートで, 2 つの特徴を切り分ける対照になります. tufB・rpoB・rpoC は配布した 30 kb に含まれますが, 残る 4 つは外にあるので, 全ゲノムの活性行列から取り出します.

In [15]:
PROTEINS = evo2_sae.proteins()  # ORF の座標と DSSP

# region.residue_acts は, 遺伝子が配布した 30 kb の外にあれば全ゲノム行列から引く.
# 4 つぶんをここでまとめて取り出しておく
for gene in PROTEINS:
    region.residue_acts(gene, F_HELIX)
downloading proteins.json

残基ごとの値を PDB の B-factor 欄に書き込み, py3Dmol で色に変換します. B-factor を経由するのは, 多くの分子可視化ソフトがこの列での色分けに対応しているためです. 同じファイルは PyMOL や ChimeraX でも開けます.

塗る残基は発火の有無で決め, どちらかの特徴が発火した残基を値の大きいほうの色で塗ります. ヘリックスの特徴なら青, シートの特徴なら橙です. どちらも発火しなければ灰色のままです. BatchTopK の段階で小さい値が 0 になっているので, ここで閾値を決める必要はありません.

In [16]:
region.show_complex("tufB", F_HELIX, F_SHEET)
downloading eftu_trna.pdb

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

EF-Tu が二次構造に沿って塗り分けられました. N 末端側の GTP 結合ドメインはヘリックスが多く, C 末端側の 2 つのドメインは $\beta$ バレルであるためシートが優勢で, 紫の鎖が tRNA です. この構造は, AlphaFold が予測した大腸菌 EF-Tu を三元複合体 1B23 のタンパク質鎖に重ね合わせ, 結晶構造側の tRNA (大腸菌 Cys-tRNA) を残して組み立てたものです.

In [17]:
region.show_complex("rpoB-rpoC", F_HELIX, F_SHEET)
downloading rpoBC.pdb

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

大腸菌 RNA ポリメラーゼのクライオ電顕構造 6C9Y から取り出した $\beta$ 鎖と $\beta'$ 鎖です. ゲノム上では rpoB-rpoC は隣接する 8 kb の連続配列ですが, そこから読み出した 2 つの特徴は, 立体構造の上ではヘリックス領域とシート領域に分かれて分布します.

残る 4 つは下のセルで選べます. Colab ではプルダウンになり, それ以外の環境では値を書き換えて実行します.

In [18]:
protein = "crp"  #@param ["pspA","ompG","crp","groL"]

region.show_complex(protein, F_HELIX, F_SHEET)
downloading crp.pdb

3Dmol.js failed to load for some reason. Please check your browser console for error messages.

塗られる残基は全体の 2 割から 4 割です. 残りは灰色で, その位置ではどちらの特徴も上位 64 個に入らなかったことを示します.

06. プロファージと CRISPR スペーサー (Fig. 4b)¶


論文 Fig. 4b は, 外来由来の配列に対応する特徴 f/19746 を 3 つの見方で示しています. ゲノム全体での分布と, プロファージ CPZ-55, および CRISPR アレイの拡大です. プロファージは, 細菌の染色体に組み込まれたファージ由来の配列です.

In [19]:
cpz55 = evo2_sae.Region.from_genome(chrom, 2_552_000, 2_572_000)
cpz55.show([(F_PROPHAGE, "#dc2626", f"f/{F_PROPHAGE}  prophage")])
Out[19]:
No description has been provided for this image

f/19746 はプロファージの区間で発火します. 区間に入って数百 bp 進んだ最初の遺伝子 intZ の内部で上がり始め, 区間を出て数百 bp で 0 に戻ります. その先の宿主由来の eut 遺伝子群では 0 です.

同じ特徴は CRISPR アレイのスペーサーでも発火します. このゲノムには 2 つのアレイがあり, 大きいほうは 29 bp のリピート 13 個と 32 bp 前後のスペーサー 12 個が交互に並んでいます. スペーサーは過去に侵入したファージなどの外来 DNA から取り込まれた断片で, リピートのほうは宿主由来です.

リピートの上では別の特徴が発火します. 論文に番号は挙がっていないので f/1261 を使い, f/19746 と並べて表示します.

In [20]:
crispr = evo2_sae.Region.from_genome(chrom, 2_872_000, 2_890_000)
crispr.show(
    [
        (F_PROPHAGE, "#dc2626", f"f/{F_PROPHAGE}  spacer"),
        (F_REPEAT, "#334155", f"f/{F_REPEAT}  repeat"),
    ],
    2_877_800, 2_878_550,
)
Out[20]:
No description has been provided for this image

スペーサーとリピートで, 2 本の特徴が互い違いに発火します.

In [21]:
def mean_on(feature, kind):
    track = crispr.track(feature)
    mask = np.zeros(len(crispr), bool)
    for r in evo2_sae.overlapping(crispr.start, crispr.end, kind):
        begin = max(r["start"], crispr.start) - crispr.start
        end = min(r["end"], crispr.end) - crispr.start
        mask[begin:end] = True
    return track[mask].mean()

rows = []
for feature in (F_PROPHAGE, F_REPEAT):
    row = {"特徴": f"f/{feature}"}
    row.update({
        kind: round(mean_on(feature, kind), 3)
        for kind in ("spacer", "repeat", "ORF")
    })
    row["全体"] = round(float(crispr.track(feature).mean()), 3)
    rows.append(row)
pd.DataFrame(rows)
Out[21]:
特徴 spacer repeat ORF 全体
0 f/19746 1.111 0.000 0.0 0.026
1 f/1261 0.032 3.424 0.0 0.074

どちらの特徴も, 対応する側で 2 桁近く高く, もう一方では下がります. 周囲の ORF では cas 遺伝子も含めて 0 です. 同じ場所にあり長さも近い 30 bp 前後の断片が, 特徴の上では分かれます.

07. 自由に探索する¶


座位の例をいくつか用意しました. locus で場所を選ぶと, その範囲を取り出して Fig. 4c の 4 つとプロファージの特徴を重ねます.

In [22]:
LOCI = {
    "lac operon": (360_800, 367_900),
    "rrnH operon": (223_300, 229_400),
    "e14 prophage": (1_193_000, 1_216_000),
    "CPZ-55": (2_552_000, 2_572_000),
    "CRISPR array": (2_877_700, 2_878_650),
    "groL": (4_370_600, 4_373_100),
}

locus = "CPZ-55"  #@param ["lac operon","rrnH operon","e14 prophage","CPZ-55","CRISPR array","groL"]

columns = fig4c + [(F_PROPHAGE, "#dc2626", f"f/{F_PROPHAGE}  prophage")]

lo, hi = LOCI[locus]

field = evo2_sae.Region.from_genome(chrom, lo, hi)
field.show(columns)
Out[22]:
No description has been provided for this image

表示する範囲は, 取り出した範囲とは別に指定できます. show に座標を渡すとその部分だけを表示し, 表示には手元にある活性を使います.

In [23]:
zoom_from = 2_556_000  #@param {type:"integer"}
zoom_to = 2_560_000  #@param {type:"integer"}

lo = max(zoom_from, field.start)
hi = min(zoom_to, field.end)
if lo >= hi:  # 上のセルで選んだ領域と重ならないので, 領域全体を表示する
    lo, hi = field.start, field.end

field.show(columns, lo, hi)
Out[23]:
No description has been provided for this image

メニューに無い場所や, まだ見ていない特徴も同じ書き方で指定できます. 座標は 0 から 4,641,652, 特徴のインデックスは 0 から 32767 の範囲です.

In [24]:
#@markdown 任意の座標と特徴のインデックス
start_bp = 4_035_000  #@param {type:"integer"}
end_bp = 4_041_200  #@param {type:"integer"}
feature = 2812  #@param {type:"integer"}

evo2_sae.Region.from_genome(chrom, start_bp, end_bp).show(
    [(feature, "#111827", f"f/{feature}")],
)
Out[24]:
No description has been provided for this image

参考文献¶


Brixi G, Durrant MG, Ku J, Naghipourfar M, Poli M, Sun G, et al. Genome modelling and design across all domains of life with Evo 2. Nature 2026. doi:10.1038/s41586-026-10176-5

Cunningham H, Ewart A, Riggs L, Huben R, Sharkey L. Sparse autoencoders find highly interpretable features in language models. arXiv 2023. doi:10.48550/arXiv.2309.08600

Xu W, Zhong Q, Lin D, Zuo Y, Dai J, Li G, Cao G. CoolBox: a flexible toolkit for visual analysis of genomics data. BMC Bioinformatics 2021. doi:10.1186/s12859-021-04408-w

Wang X, Kim Y, Ma Q, Hong SH, Pokusaeva K, Sturino JM, Wood TK. Cryptic prophages help bacteria cope with adverse environments. Nature Communications 2010. doi:10.1038/ncomms1146

Fel T, Kowal M, Jacobs M, Hazra D, Bhalla U, Sharkey L, et al. Structuring sparsity: block-sparse featurizers capture visual concept manifolds. arXiv 2026. doi:10.48550/arXiv.2606.25234

Pearce MT, Dooms T, Yamamoto R, Ayanian S, Ryu AJ, Meehl J, et al. Interpretable variant effect prediction from genomic foundation model representations. bioRxiv 2026. doi:10.64898/2026.04.10.717844