Skip to content
Published on

ヘルスケア・金融AI完全ガイド: 医療画像解析からアルゴリズム取引まで

Authors

概要

AIはヘルスケアと金融という2つの重要な産業で前例のない変革をもたらしています。放射線科医の画像読影を支援するディープラーニングモデルから、毎秒数千件の取引を処理するアルゴリズム取引システムまで、AIは両分野のコアインフラとして定着しています。このガイドでは、実際のプロダクションに対応したコード例とともに、各分野の主要な応用事例を深掘りします。


Part 1: ヘルスケアAI

1. 医療画像AI

医療画像解析はディープラーニングが最も大きなインパクトをもたらしている分野の一つです。CheXNet(スタンフォード大学)は胸部X線画像から放射線科医レベルの肺炎診断精度を実現し、AI支援診断研究の基盤となっています。

DICOM画像の処理

医療画像の標準フォーマットであるDICOMをPythonで処理する基本パイプラインです。

import pydicom
import numpy as np
from torchvision import transforms
import torch

# DICOM画像の読み込み
ds = pydicom.dcmread('chest_xray.dcm')
img_array = ds.pixel_array.astype(np.float32)

# 正規化(最小最大正規化)
img_normalized = (img_array - img_array.min()) / (img_array.max() - img_array.min())

# モデル推論用の前処理
transform = transforms.Compose([
    transforms.ToPILImage(),
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize([0.485], [0.229])
])

tensor = transform(img_normalized).unsqueeze(0)

U-Netによる医療画像セグメンテーション

U-NetはMRIやCTスキャンにおける解剖学的構造や病変の自動分割に広く使用されるアーキテクチャです。

import torch
import torch.nn as nn

class DoubleConv(nn.Module):
    def __init__(self, in_ch, out_ch):
        super().__init__()
        self.conv = nn.Sequential(
            nn.Conv2d(in_ch, out_ch, 3, padding=1),
            nn.BatchNorm2d(out_ch),
            nn.ReLU(inplace=True),
            nn.Conv2d(out_ch, out_ch, 3, padding=1),
            nn.BatchNorm2d(out_ch),
            nn.ReLU(inplace=True)
        )
    def forward(self, x):
        return self.conv(x)

class UNet(nn.Module):
    def __init__(self, in_channels=1, num_classes=2):
        super().__init__()
        self.enc1 = DoubleConv(in_channels, 64)
        self.enc2 = DoubleConv(64, 128)
        self.pool = nn.MaxPool2d(2)
        self.bottleneck = DoubleConv(128, 256)
        self.up1 = nn.ConvTranspose2d(256, 128, 2, stride=2)
        self.dec1 = DoubleConv(256, 128)
        self.up2 = nn.ConvTranspose2d(128, 64, 2, stride=2)
        self.dec2 = DoubleConv(128, 64)
        self.out_conv = nn.Conv2d(64, num_classes, 1)

    def forward(self, x):
        e1 = self.enc1(x)
        e2 = self.enc2(self.pool(e1))
        b = self.bottleneck(self.pool(e2))
        d1 = self.dec1(torch.cat([self.up1(b), e2], dim=1))
        d2 = self.dec2(torch.cat([self.up2(d1), e1], dim=1))
        return self.out_conv(d2)

評価指標: 医療セグメンテーションではDice ScoreとIoU(Intersection over Union)が主要指標です。Dice Scoreは予測とグランドトゥルースの重なりを測定し、医療画像に典型的な極端な前景・背景の不均衡においてAccuracyよりはるかに有用です。

全スライド画像(WSI): 病理スライドはギガピクセル画像になることがあります。標準的なアプローチはMultiple Instance Learning(MIL)とパッチ抽出です。スライドをタイルに分割し、各タイルをCNNで埋め込み、アテンションプーリングなどで集約してスライドレベルの予測を行います。


2. 臨床NLP

電子健康記録(EHR)には膨大な非構造化テキストデータが含まれています。NLPモデルは医師ノート、退院サマリー、放射線レポートから臨床的に意味のある情報を抽出します。

医療固有表現認識(NER)

from transformers import pipeline

# BioBERTベースのNERパイプライン
ner_pipeline = pipeline(
    "ner",
    model="dmis-lab/biobert-v1.1",
    tokenizer="dmis-lab/biobert-v1.1",
    aggregation_strategy="simple"
)

clinical_text = """
Patient presents with acute myocardial infarction.
Administered aspirin 325mg and clopidogrel 600mg.
ECG shows ST elevation in leads V1-V4.
"""

entities = ner_pipeline(clinical_text)
for ent in entities:
    print(f"エンティティ: {ent['word']}, ラベル: {ent['entity_group']}, スコア: {ent['score']:.3f}")

臨床テキスト要約

Med-PaLM 2(Google)とBioMedLM(スタンフォード)は臨床・生物医学テキストでファインチューニングされたドメイン特化型の大規模言語モデルです。臨床質問応答、退院サマリー生成、医療知識検索などのタスクで汎用モデルを大幅に上回ります。

PhysioNet & MIMIC-III: MIMIC-III臨床データベース(PhysioNet: https://physionet.org/content/mimiciii/)は臨床NLP研究の標準ベンチマークです。4万人以上のICU患者の退院サマリー、放射線レポート、看護ノートなどの匿名化EHRデータを含みます。


3. AI創薬

従来の創薬は10〜15年、数十億ドルのコストがかかります。AIはこのパイプラインの複数の段階を加速しています。

RDKitによる分子特性予測

from rdkit import Chem
from rdkit.Chem import Descriptors
import pandas as pd

def compute_molecular_features(smiles_list):
    features = []
    for smiles in smiles_list:
        mol = Chem.MolFromSmiles(smiles)
        if mol:
            features.append({
                'MW': Descriptors.MolWt(mol),
                'LogP': Descriptors.MolLogP(mol),
                'HBD': Descriptors.NumHDonors(mol),
                'HBA': Descriptors.NumHAcceptors(mol),
                'TPSA': Descriptors.TPSA(mol)
            })
    return pd.DataFrame(features)

def lipinski_filter(df):
    """リピンスキーの5の法則: 経口バイオアベイラビリティフィルター"""
    return df[
        (df['MW'] <= 500) &
        (df['LogP'] <= 5) &
        (df['HBD'] <= 5) &
        (df['HBA'] <= 10)
    ]

smiles_list = [
    'CC(=O)Oc1ccccc1C(=O)O',  # アスピリン
    'CC12CCC3C(C1CCC2O)CCC4=CC(=O)CCC34C',  # テストステロン
]
df = compute_molecular_features(smiles_list)
drug_candidates = lipinski_filter(df)

AlphaFold2とタンパク質構造予測

DeepMindのAlphaFold2(https://alphafold.ebi.ac.uk/)はアミノ酸配列から実験的精度に近い3Dタンパク質構造を予測します。50年以上解決されなかったタンパク質折り畳み問題を事実上解決し、構造生物学に革命をもたらしました。

# ColabFold(AlphaFold2インターフェース)の使用例
# pip install colabfold

from colabfold.batch import get_queries, run

queries = [("target_protein", "MKTIIALSYIFCLVFA")]

results = run(
    queries=queries,
    result_dir="./alphafold_results",
    use_templates=False,
    num_recycles=3,
    model_type="auto"
)

DeepMindは2億個以上のタンパク質構造予測結果を公開データベースとして提供しています。創薬研究者はこれらの構造を仮想スクリーニングや構造ベース創薬に活用し、有望な結合部位の特定にかかる時間を劇的に短縮しています。

GNNによる分子生成

グラフニューラルネットワーク(GNN)は分子を原子(ノード)と結合(エッジ)のグラフとして表現し、化学的なパターンを学習して新しい薬物候補を生成します。

import torch
from torch_geometric.data import Data
from torch_geometric.nn import GCNConv, global_mean_pool

class MoleculeGNN(torch.nn.Module):
    def __init__(self, num_features, hidden_dim, num_classes):
        super().__init__()
        self.conv1 = GCNConv(num_features, hidden_dim)
        self.conv2 = GCNConv(hidden_dim, hidden_dim)
        self.classifier = torch.nn.Linear(hidden_dim, num_classes)
        self.relu = torch.nn.ReLU()

    def forward(self, data):
        x, edge_index, batch = data.x, data.edge_index, data.batch
        x = self.relu(self.conv1(x, edge_index))
        x = self.relu(self.conv2(x, edge_index))
        x = global_mean_pool(x, batch)
        return self.classifier(x)

4. ウェアラブルとAI

コンシューマー向けウェアラブルデバイスは継続的な生体信号データストリームを生成し、大規模なリアルタイム健康モニタリングを可能にします。

1D CNNによるECG不整脈分類

import torch
import torch.nn as nn

class ECGClassifier(nn.Module):
    """ECG不整脈分類のための1D CNN"""
    def __init__(self, num_classes=5):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv1d(1, 32, kernel_size=11, padding=5),
            nn.BatchNorm1d(32),
            nn.ReLU(),
            nn.MaxPool1d(2),
            nn.Conv1d(32, 64, kernel_size=7, padding=3),
            nn.BatchNorm1d(64),
            nn.ReLU(),
            nn.MaxPool1d(2),
            nn.Conv1d(64, 128, kernel_size=5, padding=2),
            nn.BatchNorm1d(128),
            nn.ReLU(),
            nn.AdaptiveAvgPool1d(32)
        )
        self.classifier = nn.Sequential(
            nn.Linear(128 * 32, 256),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(256, num_classes)
        )

    def forward(self, x):
        x = self.features(x)
        x = x.view(x.size(0), -1)
        return self.classifier(x)

# PhysioNet MIT-BIH 不整脈データベース
# 参考: https://physionet.org/content/mitdb/1.0.0/

人間活動認識(HAR): ウェアラブルの加速度計とジャイロスコープデータから歩行、走行、階段昇降などの活動を分類できます。近年、Transformerベースモデルがコンシューマー向けHARベンチマークでCNN/LSTMを上回っています。


Part 2: 金融AI

5. 株価予測モデル

株価予測は金融AIで最も研究されているテーマですが、同時に最も困難な問題です。効率的市場仮説(EMH)によれば公開情報はすでに価格に織り込まれており、価格データだけで一貫した超過収益を得ることは極めて難しいとされています。

テクニカル指標を使ったフィーチャーエンジニアリング

import yfinance as yf
import pandas as pd
import numpy as np

# 株価データのダウンロード
# 参考: https://pypi.org/project/yfinance/
ticker = yf.Ticker("AAPL")
df = ticker.history(period="5y")

def compute_rsi(prices, window=14):
    delta = prices.diff()
    gain = (delta.where(delta > 0, 0)).rolling(window).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window).mean()
    rs = gain / loss
    return 100 - (100 / (1 + rs))

def add_technical_indicators(df):
    df['SMA20'] = df['Close'].rolling(20).mean()
    df['SMA50'] = df['Close'].rolling(50).mean()
    df['EMA12'] = df['Close'].ewm(span=12).mean()
    df['EMA26'] = df['Close'].ewm(span=26).mean()
    df['MACD'] = df['EMA12'] - df['EMA26']
    df['Signal'] = df['MACD'].ewm(span=9).mean()
    df['RSI'] = compute_rsi(df['Close'], 14)
    df['BB_upper'] = df['SMA20'] + 2 * df['Close'].rolling(20).std()
    df['BB_lower'] = df['SMA20'] - 2 * df['Close'].rolling(20).std()
    df['Volatility'] = df['Close'].pct_change().rolling(20).std()
    df['Volume_MA'] = df['Volume'].rolling(20).mean()
    return df.dropna()

df = add_technical_indicators(df)

LSTMによる時系列予測

import torch
import torch.nn as nn
from sklearn.preprocessing import MinMaxScaler

class StockLSTM(nn.Module):
    def __init__(self, input_size, hidden_size=128, num_layers=2, dropout=0.2):
        super().__init__()
        self.lstm = nn.LSTM(
            input_size=input_size,
            hidden_size=hidden_size,
            num_layers=num_layers,
            batch_first=True,
            dropout=dropout
        )
        self.fc = nn.Sequential(
            nn.Linear(hidden_size, 64),
            nn.ReLU(),
            nn.Linear(64, 1)
        )

    def forward(self, x):
        out, _ = self.lstm(x)
        return self.fc(out[:, -1, :])

# ウォークフォワード交差検証(ルックアヘッドバイアス防止)
def walk_forward_split(df, train_size=0.7, val_size=0.15):
    n = len(df)
    train_end = int(n * train_size)
    val_end = int(n * (train_size + val_size))
    return df[:train_end], df[train_end:val_end], df[val_end:]

重要: 時系列データにランダム分割を使用してはいけません。未来のデータが学習セットに漏洩するルックアヘッドバイアスが発生し、実際のライブトレードよりもはるかに良いバックテスト結果が生じます。


6. アルゴリズム取引

Backtraderによる移動平均クロス戦略

import backtrader as bt
# 参考: https://www.backtrader.com/docu/

class MACrossStrategy(bt.Strategy):
    params = (('fast', 10), ('slow', 30),)

    def __init__(self):
        self.sma_fast = bt.indicators.SMA(period=self.p.fast)
        self.sma_slow = bt.indicators.SMA(period=self.p.slow)
        self.crossover = bt.indicators.CrossOver(self.sma_fast, self.sma_slow)

    def next(self):
        if not self.position:
            if self.crossover > 0:
                self.buy(size=100)
        elif self.crossover < 0:
            self.sell(size=100)

# バックテスト実行
cerebro = bt.Cerebro()
cerebro.addstrategy(MACrossStrategy)
cerebro.broker.setcash(100000.0)
cerebro.broker.setcommission(commission=0.001)
results = cerebro.run()
print(f"最終ポートフォリオ価値: {cerebro.broker.getvalue():.2f}")

マルコビッツ平均分散ポートフォリオ最適化

import numpy as np
from scipy.optimize import minimize

def portfolio_stats(weights, returns):
    port_return = np.sum(returns.mean() * weights) * 252
    port_vol = np.sqrt(weights @ returns.cov() @ weights * 252)
    sharpe = port_return / port_vol
    return port_return, port_vol, sharpe

def min_variance_portfolio(returns):
    n = returns.shape[1]
    constraints = {'type': 'eq', 'fun': lambda w: np.sum(w) - 1}
    bounds = [(0, 1)] * n
    result = minimize(
        lambda w: portfolio_stats(w, returns)[1],
        x0=np.ones(n) / n,
        bounds=bounds,
        constraints=constraints
    )
    return result.x

強化学習によるトレーディング(PPO)

import gym
import numpy as np
from stable_baselines3 import PPO

class TradingEnv(gym.Env):
    """RLのための簡略化された株式取引環境"""
    def __init__(self, df, initial_balance=10000):
        super().__init__()
        self.df = df
        self.initial_balance = initial_balance
        # アクション: 0=保持, 1=購入, 2=売却
        self.action_space = gym.spaces.Discrete(3)
        self.observation_space = gym.spaces.Box(
            low=-np.inf, high=np.inf, shape=(10,), dtype=np.float32
        )
        self.reset()

    def reset(self):
        self.balance = self.initial_balance
        self.shares = 0
        self.current_step = 0
        return self._get_obs()

    def _get_obs(self):
        row = self.df.iloc[self.current_step]
        return np.array([
            row['Close'], row['SMA20'], row['SMA50'],
            row['RSI'], row['MACD'], row['Volatility'],
            self.balance, self.shares,
            row['Volume'], row['BB_upper'] - row['BB_lower']
        ], dtype=np.float32)

    def step(self, action):
        price = self.df.iloc[self.current_step]['Close']
        reward = 0
        if action == 1 and self.balance >= price:
            self.shares += 1
            self.balance -= price
        elif action == 2 and self.shares > 0:
            self.shares -= 1
            self.balance += price
            reward = price - self.df.iloc[max(0, self.current_step - 1)]['Close']
        self.current_step += 1
        done = self.current_step >= len(self.df) - 1
        return self._get_obs(), reward, done, {}

model = PPO("MlpPolicy", TradingEnv(df), verbose=1)
model.learn(total_timesteps=100000)

7. 不正検出

クレジットカード不正検出は極端なクラス不均衡という特有の課題があります。不正取引は全取引の0.1%未満しか占めないことが一般的です。

SMOTEオーバーサンプリングとIsolation Forest

from sklearn.ensemble import IsolationForest
from imblearn.over_sampling import SMOTE
from sklearn.metrics import classification_report, roc_auc_score

# 少数クラスのオーバーサンプリング - 必ず学習データのみに適用
smote = SMOTE(sampling_strategy=0.1, random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)

# 教師なし異常検出
iso_forest = IsolationForest(
    n_estimators=200,
    contamination=0.001,
    random_state=42
)
iso_forest.fit(X_train)
anomaly_scores = iso_forest.decision_function(X_test)

# SHAPによるモデル説明
import shap
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test[:100])
shap.summary_plot(shap_values, X_test[:100], feature_names=feature_names)

オートエンコーダーベースの異常検出

正常取引データのみでオートエンコーダーを学習します。推論時に不正取引は再構成誤差が大きくなるため、これを異常スコアとして活用します。

import torch
import torch.nn as nn

class FraudAutoencoder(nn.Module):
    def __init__(self, input_dim, encoding_dim=16):
        super().__init__()
        self.encoder = nn.Sequential(
            nn.Linear(input_dim, 64),
            nn.ReLU(),
            nn.Linear(64, 32),
            nn.ReLU(),
            nn.Linear(32, encoding_dim)
        )
        self.decoder = nn.Sequential(
            nn.Linear(encoding_dim, 32),
            nn.ReLU(),
            nn.Linear(32, 64),
            nn.ReLU(),
            nn.Linear(64, input_dim)
        )

    def forward(self, x):
        return self.decoder(self.encoder(x))

def detect_fraud(model, x, threshold=0.5):
    with torch.no_grad():
        reconstructed = model(x)
    reconstruction_error = torch.mean((x - reconstructed) ** 2, dim=1)
    return reconstruction_error > threshold

8. 信用リスクモデル

バーゼルIII規制のもと、金融機関は信用リスクを定量化する義務があります。期待損失(Expected Loss)は次のように計算されます。

  • EL = PD x LGD x EAD
    • PD(Probability of Default): デフォルト確率
    • LGD(Loss Given Default): デフォルト時損失率
    • EAD(Exposure at Default): デフォルト時エクスポージャー
from sklearn.linear_model import LogisticRegression
from sklearn.calibration import CalibratedClassifierCV
import lightgbm as lgb

# 確率キャリブレーション付きPDモデル
pd_model = LogisticRegression(class_weight='balanced', max_iter=1000)
pd_calibrated = CalibratedClassifierCV(pd_model, cv=5)
pd_calibrated.fit(X_train, y_train)
pd_scores = pd_calibrated.predict_proba(X_test)[:, 1]

# 勾配ブースティングスコアカード
lgb_model = lgb.LGBMClassifier(
    n_estimators=500,
    learning_rate=0.05,
    num_leaves=31,
    class_weight='balanced'
)
lgb_model.fit(X_train, y_train, eval_set=[(X_val, y_val)])

# デフォルトまでの時間モデリングのための生存分析
from lifelines import CoxPHFitter
cph = CoxPHFitter()
cph.fit(df_survival, duration_col='time_to_default', event_col='defaulted')
cph.print_summary()

9. 金融NLP

FinBERTによるニュースセンチメント分析

from transformers import pipeline
import pandas as pd

# FinBERT: 金融ドメイン特化BERT
sentiment_pipeline = pipeline(
    "sentiment-analysis",
    model="ProsusAI/finbert"
)

def analyze_news_sentiment(headlines):
    results = sentiment_pipeline(headlines)
    return pd.DataFrame([
        {'headline': h, 'label': r['label'], 'score': r['score']}
        for h, r in zip(headlines, results)
    ])

headlines = [
    "Apple reports record quarterly earnings",
    "Federal Reserve signals rate hike ahead",
    "Tech sector faces regulatory headwinds"
]

df_sentiment = analyze_news_sentiment(headlines)
print(df_sentiment)

SEC EDGARの財務諸表パース

import requests
from bs4 import BeautifulSoup
import re

def fetch_10k_section(cik, accession_number):
    """SEC EDGARから10-K年次報告書のリスクファクターセクションを取得"""
    base_url = "https://www.sec.gov/Archives/edgar"
    url = f"{base_url}/{cik}/{accession_number}/10k.htm"
    response = requests.get(url, headers={'User-Agent': 'research@example.com'})
    soup = BeautifulSoup(response.text, 'html.parser')
    risk_section = soup.find(text=re.compile("Risk Factors", re.IGNORECASE))
    return risk_section.parent.get_text() if risk_section else ""

ESGスコアリング: LLMはサステナビリティレポート、ニュース記事、決算説明会のトランスクリプトからESG(環境・社会・ガバナンス)シグナルを抽出するために活用されています。これらのシグナルはESG投資ポートフォリオに直接組み込まれます。


重要な注意事項

ヘルスケア

  1. 規制承認: 米国では臨床意思決定に使用されるAIソフトウェアはFDAのSoftware as a Medical Device(SaMD)フレームワークの対象となり、市販前承認または認可が必要です。
  2. HIPAA準拠: 保護健康情報(PHI)を扱うシステムはすべて、匿名化、アクセス制御、監査ログの実装が必要です。
  3. アルゴリズムバイアス: 特定の人口統計に偏ったデータで学習されたモデルは、過小代表グループで性能が低下する可能性があり、患者安全上の懸念となります。
  4. 臨床検証: 優れたインシリコ性能が実世界での有効性を保証するものではありません。前向き臨床試験が引き続き不可欠です。

金融

  1. ルックアヘッドバイアス: データ分割における時系列的な厳密さは交渉の余地がありません。わずかな漏洩でも無価値な戦略を収益性があるように見せる可能性があります。
  2. 過学習: 金融データはノイズが多く非定常です。複雑なモデルは市場レジームが変化するとアウトオブサンプルで失敗することがよくあります。
  3. レジームチェンジ: 過去に有効だった戦略は、市場構造、ボラティリティ、相関関係が変化すると突然失敗する可能性があります。
  4. 取引コスト: バックテストにはスリッページ、手数料、市場インパクトを必ずモデル化する必要があります。これらを無視すると不採算な戦略が優秀に見えてしまいます。

参考資料


クイズ

Q1. 金融バックテストにおけるルックアヘッドバイアスとは何か、なぜ危険なのか?

正答: 取引判断の時点では利用できない未来の情報をモデル学習や売買シグナル生成に使用するエラーで、人為的に高いバックテスト性能をもたらします。

解説: 例えば、当日の終値を使って当日の取引シグナルを生成するのはルックアヘッドバイアスです。価格が確定する前には取引できないからです。ウォークフォワード検証と厳密な時系列分割でこれを防ぎます。漏洩データで構築された戦略は大きなアルファを生成するように見えても、ライブ取引では即座に失敗し、実際の金融損失につながります。

Q2. 医療画像セグメンテーションでAccuracyよりDice Scoreが好まれる理由は?

正答: 背景と前景のピクセル間の極端なクラス不均衡により、Accuracyは誤解を招く指標になるためです。常に背景を予測するモデルでも非常に高いAccuracyを達成しますが、臨床的には役に立ちません。

解説: 腫瘍がボクセルの1%を占める脳MRIでは、「腫瘍なし」と常に予測すれば99%のAccuracyになります。Dice Scoreは2TP割る(2TP足すFP足すFN)で計算され、予測とグランドトゥルースの重なりを直接測定し、小さな前景クラスの見落としを正しくペナルティとして扱います。

Q3. リピンスキーの5の法則とは何か、創薬においてなぜ使われるのか?

正答: 経口バイオアベイラビリティが許容できる薬物候補をフィルタリングするための経験則で、分子量500Da未満、LogP 5未満、水素結合ドナー5未満、水素結合アクセプター10未満という4つの物理化学的特性に基づきます。

解説: 経口バイオアベイラビリティの低さは後期臨床試験失敗の主な原因です。スクリーニングパイプラインの早期に5の法則を適用することで、吸収される可能性が低い分子が除外され、高価なin vitroおよびin vivo試験に進む候補の数が劇的に削減されます。

Q4. 不正検出データセットにSMOTEを適用する際の重要な落とし穴は何か?

正答: SMOTEは学習データにのみ適用する必要があります。検証セットやテストセットに適用すると合成サンプルが導入され、性能指標が過大評価され実世界の分布を反映しなくなります。

解説: 不正検出における全体的な精度よりも、Precision-Recall AUCとF1スコアがより適切な評価指標です。これらは少数(不正)クラスの性能を明示的に測定するからです。学習データでも、SMOTEで生成されたサンプルは不正パターンの真の分布を捉えられない場合があるため、堅牢なアウトオブサンプル評価と組み合わせる必要があります。

Q5. AlphaFold2が創薬にとって特に革新的な理由は何か?

正答: AlphaFold2はアミノ酸配列から実験的精度に近い3Dタンパク質構造を予測し、数年間の実験室作業が必要だった構造決定を数分のコンピュータ計算で行えるようにしました。

解説: 構造ベース創薬では標的タンパク質の3D形状、特に結合ポケットを知ることが、精密に適合する分子を設計するために不可欠です。AlphaFold2以前は、X線結晶学やクライオ電子顕微鏡法などの実験的手法が必要で、時間とコストがかかり、常に成功するとは限りませんでした。DeepMindは2億個以上の予測構造を公開データベースとして公開しており、前例のない規模での仮想スクリーニングが可能となっています。