ラプラスの法則とChIP-seq(超詳細版)- ゼロを恐れるな、そして実験の力
🎯 まず、この講義で何を学ぶのか
最終ゴール:
- なぜゼロ確率が危険なのか、その深い理由を理解する
- 18世紀の天才ラプラスの知恵を学ぶ
- アルゴリズムの限界を認識し、実験技術(ChIP-seq)で突破する方法を知る
でも、ちょっと待ってください。そもそも..。
🤔 ステップ0:なぜゼロがそんなに問題なの?
ランダム化アルゴリズムの致命的な弱点
前回のギブスサンプラーで起きたこと:
確率が0のk-mer → 絶対に選ばれない
↓
でも、それが正解かもしれない
↓
正解にたどり着けない!
例えるなら:
宝くじで「0枚買う」
→ 当たる確率は0
→ 永遠に当たらない
現実世界での問題
観察:コインを10回投げて、全部表だった
結論:裏が出る確率は0?
いいえ!
→ たまたま10回連続で表だっただけ
→ もっと投げれば裏も出るはず
→ サンプルサイズが小さすぎる
📖 ステップ1:ラプラスという天才の登場
1-1. ピエール=シモン・ラプラスとは
18-19世紀フランスの数学者・物理学者
業績:
- 確率論の体系化
- 天体力学(太陽系の安定性を証明)
- ラプラス変換(工学で超重要)
性格:
「宇宙のすべては計算できる」と信じた究極の決定論者
でも確率論も大好き(矛盾?いいえ、深い理解)
1-2. ラプラスの有名な問題
問題:
「太陽は過去5000年間、毎日昇ってきた。
明日も太陽が昇る確率は?」
普通の答え:
「100%でしょ?」
ラプラスの答え:
「1 - 1/1,826,214 ≈ 99.99995%」
えっ?100%じゃない?
1-3. なぜ100%じゃないの?
ラプラスの考え:
「絶対」なんてない
↓
明日、隕石が地球に衝突するかも
太陽が爆発するかも
物理法則が変わるかも
↓
可能性は限りなく低いが、ゼロではない
🎲 ステップ2:ラプラスの継承の法則
2-1. 問題設定
# 実験:成功か失敗かの試行をn回繰り返す
# 結果:s回成功した
# 質問:次の試行が成功する確率は?
# 普通の答え(頻度主義)
probability_frequentist = s / n
# 例:コイン10回投げて7回表
# → 表の確率 = 7/10 = 0.7
# でも問題が...
# もしs=0だったら?
# → 確率0 → 二度と成功しない?
2-2. ラプラスの解決策
# ラプラスの答え(ベイズ主義)
probability_laplace = (s + 1) / (n + 2)
# なぜ+1と+2?
2-3. 「見えない観測」という発想
ラプラスの主張:
実験を始める前から、我々は知っている
↓
「成功も失敗も、どちらも可能」
↓
これは暗黙の知識 = 事前知識
↓
まるで「見えない観測」が2回ある
(成功1回、失敗1回)
だから:
実際の観測:n回(s回成功)
+
見えない観測:2回(成功1回、失敗1回)
=
合計:n+2回(s+1回成功)
💡 ステップ3:具体例で理解を深める
3-1. コイン投げの例
def calculate_probability(successes, trials):
"""
次の試行が成功する確率を計算
"""
# 頻度主義的アプローチ
if trials == 0:
freq_prob = "未定義"
else:
freq_prob = successes / trials
# ラプラスのアプローチ
laplace_prob = (successes + 1) / (trials + 2)
return freq_prob, laplace_prob
# ケース1:まだ投げていない
s, n = 0, 0
freq, lap = calculate_probability(s, n)
print(f"0回中0回成功")
print(f"頻度主義:{freq}") # 未定義(0/0)
print(f"ラプラス:{lap}") # 0.5(事前確率)
# ケース2:1回投げて失敗
s, n = 0, 1
freq, lap = calculate_probability(s, n)
print(f"1回中0回成功")
print(f"頻度主義:{freq}") # 0(永遠に失敗?)
print(f"ラプラス:{lap}") # 0.33(まだチャンスあり)
# ケース3:100回投げて70回成功
s, n = 70, 100
freq, lap = calculate_probability(s, n)
print(f"100回中70回成功")
print(f"頻度主義:{freq}") # 0.70
print(f"ラプラス:{lap}") # 0.696(ほぼ同じ)
3-2. サンプルサイズの影響
import matplotlib.pyplot as plt
def plot_convergence():
"""
サンプルサイズが増えると両者が収束
"""
true_prob = 0.6 # 真の確率
sample_sizes = range(1, 1000)
freq_probs = []
laplace_probs = []
for n in sample_sizes:
# 真の確率で成功数を計算
s = int(n * true_prob)
freq_probs.append(s / n)
laplace_probs.append((s + 1) / (n + 2))
# グラフ化
# サンプルが少ない時:大きな差
# サンプルが多い時:ほぼ同じ
🧬 ステップ4:DNAモチーフ探索への応用
4-1. カウント行列での問題
# 元のカウント行列
count_matrix = {
# 位置1 位置2 位置3 位置4
'A': [3, 0, 2, 1],
'C': [0, 2, 0, 2],
'G': [1, 1, 2, 0],
'T': [0, 1, 0, 1]
}
# 問題:0が多い!
# → 確率0のパターンが多数
# → 探索空間が狭まる
4-2. 擬似カウント(Pseudocount)の追加
def add_pseudocount(count_matrix, pseudo=1):
"""
全てのカウントに擬似カウントを追加
"""
# ラプラスの擬似カウント
adjusted_matrix = {}
for nucleotide in 'ACGT':
adjusted_matrix[nucleotide] = [
count + pseudo for count in count_matrix[nucleotide]
]
return adjusted_matrix
# 擬似カウント追加後
adjusted = add_pseudocount(count_matrix)
# 'A': [4, 1, 3, 2] # 0が消えた!
# 'C': [1, 3, 1, 3]
# 'G': [2, 2, 3, 1]
# 'T': [1, 2, 1, 2]
# 確率に変換
total = 8 # 4配列 + 4擬似カウント
profile = {
'A': [4/8, 1/8, 3/8, 2/8],
'C': [1/8, 3/8, 1/8, 3/8],
'G': [2/8, 2/8, 3/8, 1/8],
'T': [1/8, 2/8, 1/8, 2/8]
}
# すべて正の確率!
4-3. 擬似カウントの大きさの影響
def compare_pseudocounts():
"""
擬似カウントの大きさによる影響
"""
original = {'A': 10, 'C': 0, 'G': 0, 'T': 0}
# 小さい擬似カウント(0.1)
small_pseudo = {
'A': (10 + 0.1) / (10 + 0.4), # ≈ 0.96
'C': (0 + 0.1) / (10 + 0.4), # ≈ 0.01
'G': (0 + 0.1) / (10 + 0.4), # ≈ 0.01
'T': (0 + 0.1) / (10 + 0.4) # ≈ 0.01
}
# 元のデータを強く反映
# 大きい擬似カウント(1.0)
large_pseudo = {
'A': (10 + 1) / (10 + 4), # ≈ 0.79
'C': (0 + 1) / (10 + 4), # ≈ 0.07
'G': (0 + 1) / (10 + 4), # ≈ 0.07
'T': (0 + 1) / (10 + 4) # ≈ 0.07
}
# より均等に近づく
# 超大きい擬似カウント(10.0)
huge_pseudo = {
'A': (10 + 10) / (10 + 40), # = 0.4
'C': (0 + 10) / (10 + 40), # = 0.2
'G': (0 + 10) / (10 + 40), # = 0.2
'T': (0 + 10) / (10 + 40) # = 0.2
}
# ほぼ均等(元のデータが薄まる)
🔬 ステップ5:アルゴリズムの限界
5-1. 統計的な限界
問題設定:
- DNA配列の長さ:1000文字
- モチーフの長さ:15文字
- 許容変異数:5個
計算してみると...
def calculate_random_matches():
"""
ランダムに一致する確率
"""
k = 15 # モチーフ長
d = 5 # 変異数
# 特定の15-merが5変異以内で一致する確率
# 約 C(15,5) × 3^5 / 4^15
from math import comb
matches = comb(15, 5) * (3 ** 5)
total = 4 ** 15
prob_match = matches / total
print(f"ランダムマッチ確率:{prob_match:.6f}")
# 1000文字の配列での期待値
positions = 1000 - 15 + 1
expected = positions * prob_match
print(f"期待される偽陽性:{expected:.2f}個")
# 結果:偽陽性が多すぎる!
5-2. 信号対雑音比(Signal-to-Noise Ratio)
真のモチーフ:10個(10配列に1個ずつ)
偽陽性:50個以上(ランダムな一致)
信号(真) vs 雑音(偽)
10 vs 50
もはや区別不可能!
🧪 ステップ6:ChIP-seq - 実験による解決
6-1. ChIP-seqとは何か
ChIP = Chromatin ImmunoPrecipitation(クロマチン免疫沈降)
seq = sequencing(シーケンシング)
簡単に言うと:
「転写因子が実際に結合している場所だけを取り出す技術」
6-2. ChIP-seqの仕組み
6-3. なぜこれが画期的か
def compare_search_space():
"""
ChIP-seqによる探索空間の削減
"""
# 通常のゲノム探索
genome_length = 3_000_000_000 # 30億塩基
# ChIP-seqの場合
chip_regions = 10_000 # 結合領域数
region_length = 200 # 各領域の長さ
# 探索空間の削減率
original_space = genome_length
reduced_space = chip_regions * region_length
reduction = original_space / reduced_space
print(f"探索空間が{reduction:,.0f}倍削減!")
# 結果:1,500倍の削減!
# これにより...
# 変異5個のモチーフ → 発見不可能
# ↓ ChIP-seq適用後
# 変異5個のモチーフ → 発見可能!
🎯 ステップ7:ChIP-seqの実例
7-1. 実際の実験の流れ
1. 細胞培養
目的の転写因子を発現させる
2. クロスリンク(架橋)
ホルムアルデヒドで固定
(転写因子とDNAをくっつける)
3. 断片化
超音波でDNAを200-500bpに切断
4. 免疫沈降
転写因子特異的抗体を使用
磁気ビーズで回収
5. DNA精製
クロスリンクを解除
DNAを抽出
6. シーケンシング
次世代シーケンサーで解読
7. データ解析
モチーフ発見アルゴリズム適用
7-2. ChIP-seqデータの特徴
def analyze_chip_seq_data():
"""
ChIP-seqデータの特徴
"""
# ピーク(結合が強い場所)
peak_regions = [
("chr1", 1000000, 1000200, 500), # 染色体、開始、終了、強度
("chr1", 2000000, 2000200, 300),
("chr2", 5000000, 5000200, 700),
# ... 数千〜数万のピーク
]
# 各ピーク領域でモチーフ探索
for chrom, start, end, intensity in peak_regions:
region_length = end - start # 200bp
# この狭い領域なら...
# 高度に変異したモチーフも発見可能!
💻 ステップ8:ChIP-seq + アルゴリズムの統合
8-1. 二段階アプローチ
def integrated_motif_discovery(chip_seq_peaks):
"""
ChIP-seq + ギブスサンプラーの統合
"""
# ステップ1:ChIP-seqでDNA領域を絞る
candidate_sequences = []
for peak in chip_seq_peaks:
seq = extract_sequence(peak)
candidate_sequences.append(seq[:200]) # 200bpに限定
# ステップ2:絞った領域でモチーフ探索
# 短い配列なので、変異が多くても発見可能
motifs = gibbs_sampler(
candidate_sequences,
k=15, # モチーフ長
d=5 # 5変異でもOK!
)
return motifs
8-2. 成功率の劇的な改善
従来の方法(ゲノム全体を探索):
- 成功率:10%(変異5個の場合)
- 計算時間:数日
ChIP-seq + アルゴリズム:
- 成功率:90%(変異5個でも)
- 計算時間:数分
改善率:9倍!
🤔 ステップ9:なぜ生物学者は諦めなかったか
9-1. 執念の理由
モチーフ = 遺伝子制御の鍵
↓
遺伝子制御 = 生命現象の根本
↓
理解できれば...
- 病気の原因解明
- 新薬開発
- 再生医療
- 進化の理解
9-2. 技術革新の連鎖
1990年代:アルゴリズムだけで挑戦
→ 限界にぶつかる
2000年代:ChIP-chip(マイクロアレイ)
→ ある程度成功
2007年〜:ChIP-seq(次世代シーケンサー)
→ 大成功!
現在:single-cell ChIP-seq
→ 1細胞レベルで解析
📊 ステップ10:まとめと未来への展望
10-1. 今日学んだこと
レベル1:ゼロ確率の危険性
- アルゴリズムが機能しなくなる
- 現実を正しく反映しない
レベル2:ラプラスの知恵
- 擬似カウントという解決策
- 「絶対」を避ける哲学
レベル3:アルゴリズムの限界
- 統計的に不可能な問題が存在
- 信号対雑音比の問題
レベル4:実験技術との融合
- ChIP-seqによる探索空間の削減
- アルゴリズム+実験=最強
10-2. 重要な教訓
1. 完璧なアルゴリズムは存在しない
→ 限界を知ることが重要
2. 異なるアプローチの組み合わせ
→ 計算+実験=ブレークスルー
3. 諦めない姿勢
→ 不可能に見えても、別の道がある
4. 歴史から学ぶ
→ 18世紀の知恵が21世紀に生きる
🚀 最後に:ラプラスからのメッセージ
「確率とは、知識の不完全さの表現である」
- ピエール=シモン・ラプラス
私たちの知識は不完全
↓
だから確率を使う
↓
だからゼロと1を避ける
↓
だから実験で補完する
不完全さを認めることが、
完全に近づく第一歩。