【機械学習】臨床データセットで学ぶ回帰分析「糖尿病の進行予測」

こんにちは、受託コンサルティングチームの hosor です。

バイオインフォマティクス分野において、機械学習はゲノムデータや臨床情報といった膨大なデータセットから、新たな知見を引き出すための強力なツールとして広く活用されています。

例えば、遺伝子発現プロファイルから特定の疾患の進行度を予測したり、患者の臨床的特徴から治療薬への応答性を予測したりするなど、その応用範囲は多岐にわたります。

本記事では、Python の代表的な機械学習ライブラリである scikit-learn を用いて、糖尿病データセットに対して回帰分析を実施し、糖尿病の進行度合いを予測します。

回帰

解析環境

  • Ubuntu 22.04 LTS
  • Python v3.14.0
    • pandas v2.3.3
    • scikit-learn v1.7.2
    • matplotlib v3.10.6

データセット

今回は、scikit-learn に組み込まれている Diabetes (糖尿病) データセットを、臨床研究で得られたデータセットと見立てて扱います。

このデータセットには、442 人の被験者のデータが含まれており、予測したい目的変数は「ベースライン測定から 1 年後の疾患の進行度」を示す数値です。

予測に用いる特徴量は 4 種類の患者情報と、6 種類の血清測定値であり、これらはバイオマーカー候補と考えることができます。

  • age: 年齢
  • sex: 性別
  • bmi: BMI
  • bp: 平均血圧
  • s1 tc: 総コレステロール
  • s2 ldl: 低密度リポタンパク質
  • s3 hdl: 高密度リポタンパク質
  • s4 tch: 総コレステロール/高密度リポタンパク質
  • s5 ltg: 血清トリグリセリドの対数値
  • s6 glu: 血糖値

このデータセットの特徴量は、あらかじめ平均 0、分散 1 に標準化されています。

これは、異なる単位やスケールを持つ特徴量を公平に扱うために行われる、一般的な前処理です。

それでは、実際にデータを読み込み、確認していきます。

import pandas as pd
from sklearn.datasets import load_diabetes

# Diabetes データセットをロードする
diabetes_data = load_diabetes()

# 特徴量を pandas の DataFrame に変換する
X = pd.DataFrame(diabetes_data.data, columns=diabetes_data.feature_names)

# 目的変数を pandas の Series に変換する
y = pd.Series(diabetes_data.target, name='target')

# データの確認
print(X.head())
        age       sex       bmi        bp        s1        s2        s3        s4        s5        s6
0  0.038076  0.050680  0.061696  0.021872 -0.044223 -0.034821 -0.043401 -0.002592  0.019907 -0.017646
1 -0.001882 -0.044642 -0.051474 -0.026328 -0.008449 -0.019163  0.074412 -0.039493 -0.068332 -0.092204
2  0.085299  0.050680  0.044451 -0.005670 -0.045599 -0.034194 -0.032356 -0.002592  0.002861 -0.025930
3 -0.089063 -0.044642 -0.011595 -0.036656  0.012191  0.024991 -0.036038  0.034309  0.022688 -0.009362
4  0.005383 -0.044642 -0.036385  0.021872  0.003935  0.015596  0.008142 -0.002592 -0.031988 -0.046641

print(y.head())
0    151.0
1     75.0
2    141.0
3    206.0
4    135.0
Name: target, dtype: float64

print(X.describe())
                age           sex           bmi            bp            s1            s2            s3            s4            s5            s6
count  4.420000e+02  4.420000e+02  4.420000e+02  4.420000e+02  4.420000e+02  4.420000e+02  4.420000e+02  4.420000e+02  4.420000e+02  4.420000e+02
mean  -2.511817e-19  1.230790e-17 -2.245564e-16 -4.797570e-17 -1.381499e-17  3.918434e-17 -5.777179e-18 -9.042540e-18  9.293722e-17  1.130318e-17
std    4.761905e-02  4.761905e-02  4.761905e-02  4.761905e-02  4.761905e-02  4.761905e-02  4.761905e-02  4.761905e-02  4.761905e-02  4.761905e-02
min   -1.072256e-01 -4.464164e-02 -9.027530e-02 -1.123988e-01 -1.267807e-01 -1.156131e-01 -1.023071e-01 -7.639450e-02 -1.260971e-01 -1.377672e-01
25%   -3.729927e-02 -4.464164e-02 -3.422907e-02 -3.665608e-02 -3.424784e-02 -3.035840e-02 -3.511716e-02 -3.949338e-02 -3.324559e-02 -3.317903e-02
50%    5.383060e-03 -4.464164e-02 -7.283766e-03 -5.670422e-03 -4.320866e-03 -3.819065e-03 -6.584468e-03 -2.592262e-03 -1.947171e-03 -1.077698e-03
75%    3.807591e-02  5.068012e-02  3.124802e-02  3.564379e-02  2.835801e-02  2.984439e-02  2.931150e-02  3.430886e-02  3.243232e-02  2.791705e-02
max    1.107267e-01  5.068012e-02  1.705552e-01  1.320436e-01  1.539137e-01  1.987880e-01  1.811791e-01  1.852344e-01  1.335973e-01  1.356118e-01

head でデータの構造を、describe で各バイオマーカーの分布の概要を確認しています。

データの分割

機械学習モデルの性能を客観的に評価し、未知のデータへの対応能力 (汎化性能) を検証するためには、データを訓練用とテスト用に分割することが不可欠です。

訓練データはモデルの学習にのみ使用し、学習済みのモデルをテストデータで評価します。

この手順を怠ると、モデルが訓練データに過剰に適合する「過学習」に陥り、新しいデータに対して正確な予測ができなくなってしまいます。

from sklearn.model_selection import train_test_split

# データを 70% の訓練データと 30% のテストデータに分割する
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 分割後のデータサイズを確認する
print(f"Total samples: {len(X)}")
Total samples: 442

print(f"Training samples: {len(X_train)}")
Training samples: 309

print(f"Test samples: {len(X_test)}")
Test samples: 133

回帰モデルの選択と学習・予測

データの分割の次に、モデルを選択して学習させます。

今回は、解釈が容易で性能の基準 (ベースライン) を評価しやすいため、最も基本的な線形回帰モデルを使用します。

このモデルは、各バイオマーカーが疾患の進行度に与える影響の大きさを学習するため、生物学的な意味を理解しやすい利点があります。

from sklearn.linear_model import LinearRegression

# 線形回帰モデルのインスタンスを生成する
model = LinearRegression()

# 訓練データを用いてモデルを学習させる
model.fit(X_train, y_train)

# 学習済みモデルを用いてテストデータの目的変数を予測する
y_pred = model.predict(X_test)

作成したモデルの評価

モデルの性能評価では、予測値が実際の値とどれだけ一致しているかを定量的に見ます。

ここでは、評価指標として平均二乗誤差 (MSE) と決定係数 (R²) を用います。

  • 平均二乗誤差 (MSE): 予測誤差の大きさを示し、0 に近いほど良いとされます。

  • 決定係数 (R²): モデルがデータのばらつきをどの程度説明できているかを示す指標 (0~1) で、1 に近いほど良いとされます。

単に予測が当たるか (平均二乗誤差) だけでなく、モデルが現象をどれだけうまく説明できるか (決定係数) も確認することが重要です。

from sklearn.metrics import mean_squared_error, r2_score

# 平均二乗誤差を計算する
mse = mean_squared_error(y_test, y_pred)

# 決定係数を計算する
r2 = r2_score(y_test, y_pred)

print(f"MSE: {mse:.2f}")
MSE: 2821.75

print(f"R2: {r2:.2f}")
R2: 0.48

結果の可視化と考察

評価指標の数値だけでなく、結果を可視化することで、モデルの性能や傾向を直感的に把握できます。

具体的には、実際の値 (横軸) と予測値 (縦軸) で散布図を作成します。

import matplotlib.pyplot as plt

plt.figure(figsize=(8, 8))
plt.scatter(y_test, y_pred, alpha=0.7)
plt.xlabel("Actual Progression")
plt.ylabel("Predicted Progression")
plt.title("Actual vs Predicted")
plt.grid(True)
plt.axis("equal") 
plt.savefig("actual_vs_predicted.pdf")

actual_vs_predicted.pdf

グラフから、全体として正の相関が認められるものの、点のばらつきが大きいことがわかります。

特に、進行度が極端に高い、あるいは低いサンプル群において、誤差が大きくなる傾向が見られます。

これは、今回の 10 種類のバイオマーカーだけでは説明できないような別の生物学的要因が存在する可能性や、疾患進行度との関係が単純な線形ではない可能性を示唆しています。

まとめ

Diabetes (糖尿病) データセットを例に、回帰分析の基本的な手順 (データ確認、分割、学習、評価) を解説しました。

今回用いた線形回帰はあくまでベースラインであり、精度向上のためには、特徴量の評価・より複雑なモデルの検討・ハイパーパラメータ調整といった作業が必要です。

この分析フローは、遺伝子発現データから薬物の効果を予測するなど、他のバイオインフォマティクス分野にも応用可能です。

機械学習やデータ解析に関してお困りごとがございましたら、アメリエフにお声がけください!