サポートベクターマシン(Support Vector Machine; SVM) は、1990 年代後半から 2010 年代前半にかけて広く使われた分類アルゴリズムです。現在は深層学習や勾配ブースティングが選択される場面が増えていますが、症例数に対して特徴量が多いデータ、たとえば Radiomics、歩行波形、生体信号などの領域では現在でも選択されます。本記事では、SVM を理解するうえで重要なマージン最大化、サポートベクター、カーネルトリック、ハードマージンとソフトマージンを、リハビリテーション研究で使えるように整理します[1]。
本稿は 第3部 医療AI・機械学習アルゴリズム図鑑 第6記事です。kNN が「近い症例」、ナイーブベイズ が「条件付き確率」に基づくのに対して、SVM は「境界をどこに引くか」を重視します。次の記事からは、決定木 や アンサンブル学習 など、木構造を使う手法に進みます。RBF カーネルの C と γ の調整は 14·01 過学習デモ と 14·02 交差検証デモ で体感できます。
// 01 · LEARN OUTCOMESこの記事でわかること
読了後、次の 4 点を理解できるようになります。
- マージン最大化が「両クラスから最も離れた境界」を引くことだと説明できる
- カーネルトリックが「明示的に高次元化せず非線形分離する」仕組みを直感的に理解できる
- ハイパーパラメータ C と γ の意味を、過学習トレードオフとともに説明できる
- SVM が候補になる場面と、他の手法と比較すべき場面を判断できる
// 02 · CONCLUSIONまず結論
// 03 · FIGURE直感的な図解
まず、SVM の学習で重要な「マージン最大化」を図で解説します。SVM は、単に 2 クラスを分ける線を探すのではなく、両側のデータからなるべく離れた境界を選ぶことで学習します。これが、マージン最大化です。
次に、カーネルトリックです。直線では分けにくいデータでも、別の空間で見ると分けやすくなることがあります。SVM では、この変換を直接計算せず、カーネル関数を使って効率よく扱います。
3 つ目は、ハードマージンとソフトマージンの違いです。現実の臨床データには外れ値や重なりがあるため、誤分類をまったく許さない設定よりも、少し誤分類を許して安定した境界を引く方がよいことがあります。この調整に関わるのが C です。
// 04 · CLINICAL医療・リハビリでの具体例
SVM が使いやすい場面と、別の手法を優先した方がよい場面を、リハビリテーション研究の文脈で整理します。
MRI や CT から抽出した Radiomics 特徴量(テクスチャ、形状、強度ヒストグラムなど)で、機能予後や転帰を予測する場面を考えます。症例数が少なく、特徴量が多い場合、RBF カーネル SVM は比較候補になります。ただし、特徴量選択や交差検証を適切に行わないと過学習しやすいため、ロジスティック回帰、ランダムフォレスト、勾配ブースティングなどと比較して評価します[2]。
モーションキャプチャやウェアラブルセンサーから得た歩行波形を、振幅、位相、周波数成分などの特徴量に変換し、SVM で分類する使い方です。DMD、脳性麻痺、パーキンソン病など、症例数が限られる疾患の歩行解析では候補になります。ただし、時系列をどのような特徴量に変換するかによって性能が大きく変わります。
線形 SVM と ロジスティック回帰 は、どちらも特徴量の線形結合で分類境界を作る点では似ています。一方で、SVM は主にマージンを重視し、ロジスティック回帰は確率を直接モデル化します。そのため、係数の向きや大きさを参考にすることはできますが、線形 SVM の出力をそのまま確率として解釈することはできません。
N=1000 以上、変数が数十個ある一般的な表形式データでは、SVM だけにこだわる必要はありません。特にカテゴリ変数が多い場合、SVM では One-Hot Encoding と標準化が必要になり、前処理がやや複雑になります。勾配ブースティング は表形式データに強く、カテゴリ変数や非線形性も扱いやすいため、SVM と比較する有力な候補になります。
// 05 · THEORY数式・理論
SVM の数学的構造を、マージン定式化 → 双対形式 → カーネル → ソフトマージンの順で整理します。
マージン最大化の定式化
# 線形分離可能な場合(ハードマージン)
予測関数: f(x) = sign(wᵀx + b)
分類条件: yᵢ · (wᵀxᵢ + b) ≥ 1 for all i
↑
yᵢ ∈ {−1, +1} で表記
# マージン = 2 / ‖w‖
最大化したいのは margin → 最小化したいのは ‖w‖² / 2
# 主問題(Primal Problem)
minimize: ‖w‖² / 2
subject to: yᵢ (wᵀxᵢ + b) ≥ 1 for all i
双対形式とカーネル
主問題をラグランジュ双対化すると、「サンプル間の内積 xᵢᵀxⱼ だけが現れる形」になります。これがカーネルトリックの土台です。
# 双対問題(Lagrange dual)
maximize: Σᵢ αᵢ − (1/2) Σᵢⱼ αᵢ αⱼ yᵢ yⱼ (xᵢᵀxⱼ)
↑
内積のみ
subject to: αᵢ ≥ 0, Σᵢ αᵢ yᵢ = 0
# αᵢ > 0 となる xᵢ がサポートベクター
# それ以外の点は境界に影響しない
# カーネルトリック: 内積を関数 K(x, x') に置き換える
K_linear(x, x') = xᵀx' (線形)
K_poly(x, x') = (γ xᵀx' + r)^d (多項式)
K_RBF(x, x') = exp(−γ ‖x − x'‖²) (★ RBF / ガウス)
K_sigmoid(x, x') = tanh(γ xᵀx' + r) (シグモイド)
→ 暗黙的に高次元化したと等価な計算ができる
→ 明示的な高次元座標 φ(x) を計算する必要なし
ソフトマージン(C パラメータ)
現実のデータは完全分離不可能なので、誤分類を許容しつつペナルティを加えます。
# ソフトマージン定式化
minimize: ‖w‖² / 2 + C · Σᵢ ξᵢ
↑
誤分類ペナルティ
subject to: yᵢ (wᵀxᵢ + b) ≥ 1 − ξᵢ
ξᵢ ≥ 0 (slack 変数、誤分類量)
# C の意味
C 大 → 誤分類ペナルティ重視 → ハードマージン寄り(過学習リスク↑)
C 小 → マージン重視 → ソフト寄り(under-fitting リスク↑)
# 経験則の探索範囲
C ∈ [10⁻³, 10⁻², 10⁻¹, 1, 10, 100, 1000]
log-scale で 7 点程度を CV で評価
RBF カーネルの γ パラメータ
RBF(ガウス)カーネルは万能ですが、もう 1 つのハイパーパラメータ γ を持ちます。
# RBF カーネル
K(x, x') = exp(−γ ‖x − x'‖²)
# γ の意味
γ 大 → 小さい局所領域に反応(複雑な境界、過学習リスク↑)
γ 小 → 広い領域で平均化(滑らかな境界、under-fitting リスク↑)
# 探索範囲
γ ∈ [10⁻⁴, 10⁻³, 10⁻², 10⁻¹, 1, 10]
or γ = 1/(d · σ²) の自動設定(scikit-learn の "scale")
# C と γ は両方同時に grid search で調整
candidate_C × candidate_γ = 7 × 6 = 42 通りを CV
C と γ は、片方だけでなく同時に調整する必要があります。Hsu らの practical guide でも、特徴量のスケーリングと、C・γ のグリッド探索を交差検証で行う手順が示されています[3]。
計算量と限界
# 訓練計算量
- 線形 SVM(LinearSVC):O(N · d)、比較的大きなデータにも対応しやすい
- カーネル SVM(SVC):O(N² · d) 〜 O(N³)
↑
N=10 万 でメモリ・時間が破綻
# 予測計算量
- 各 xt について、サポートベクター全部との内積計算
- O(n_SV · d)、サポートベクター数に依存
# サンプル数の目安
N ≤ 数千: SVC(RBF) を検討しやすい
N = 数千〜数万: LinearSVC、近似法、サブサンプルを検討
N > 数万: 勾配ブースティング、線形モデル、深層学習なども比較する
特に SVC はサンプル数に対して少なくとも二次的に計算時間が増えるため、数万例を超えるデータでは LinearSVC や近似カーネル、別モデルを検討します[7]。
// 06 · IMPLEMENTATION · PYTHON実装
scikit-learn での基本実装です。SVM では、標準化を Pipeline に入れること、C と γ を交差検証で調整すること、確率を使う場合は校正を確認することが重要です。
import numpy as np
import pandas as pd
from sklearn.svm import SVC, LinearSVC
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.metrics import roc_auc_score, classification_report
from sklearn.feature_selection import SelectKBest, f_classif
df = pd.read_csv("rehab_cohort.csv")
X = df[["age", "fim_motor_admission", "fim_cog_admission",
"onset_days", "nihss"]]
y = df["discharge_home"]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42
)
# ============================================
# ① RBF カーネル SVM(標準的な選択)
# ============================================
svm_pipe = Pipeline([
("scaler", StandardScaler()), # ★ 標準化を Pipeline 内で実行
("svc", SVC(
kernel="rbf",
C=1.0,
gamma="scale", # 1/(d·σ²) で自動設定
class_weight="balanced", # 不均衡対応
probability=False, # AUC 評価は decision_function を使う
random_state=42,
)),
])
svm_pipe.fit(X_train, y_train)
y_score = svm_pipe.decision_function(X_test)
print(f"SVM(RBF) AUC: {roc_auc_score(y_test, y_score):.3f}")
# ============================================
# ② C と γ の同時最適化(grid search)
# ============================================
param_grid = {
"svc__C": [0.01, 0.1, 1, 10, 100],
"svc__gamma": ["scale", "auto", 0.01, 0.1, 1],
}
grid = GridSearchCV(
svm_pipe, param_grid,
cv=5, scoring="roc_auc", n_jobs=-1
)
grid.fit(X_train, y_train)
print(f"Best params: {grid.best_params_}")
print(f"Best CV AUC: {grid.best_score_:.3f}")
# ============================================
# ③ 線形 SVM(高速・大規模向け)
# ============================================
linear_pipe = Pipeline([
("scaler", StandardScaler()),
("svc", LinearSVC(
C=1.0,
class_weight="balanced",
max_iter=10000,
random_state=42,
)),
])
linear_pipe.fit(X_train, y_train)
# LinearSVC は確率を直接出さないので CalibratedClassifierCV で校正
from sklearn.calibration import CalibratedClassifierCV
calibrated_linear = CalibratedClassifierCV(
linear_pipe, method="sigmoid", cv=5
)
calibrated_linear.fit(X_train, y_train)
y_proba_linear = calibrated_linear.predict_proba(X_test)[:, 1]
print(f"Linear SVM AUC: {roc_auc_score(y_test, y_proba_linear):.3f}")
# ============================================
# ④ サポートベクターの確認
# ============================================
svm_pipe.fit(X_train, y_train)
n_sv = svm_pipe["svc"].n_support_
print(f"Support vectors: class 0 = {n_sv[0]}, class 1 = {n_sv[1]}")
# サポートベクター数が多すぎる(>50%)= 過学習傾向
# サポートベクターのインデックス
sv_indices = svm_pipe["svc"].support_
print(f"SV indices: {sv_indices[:10]}...")
# ============================================
# ⑤ 線形 SVM の係数(解釈性)
# ============================================
linear_pipe.fit(X_train, y_train)
coef = linear_pipe["svc"].coef_[0]
for name, c in zip(X.columns, coef):
print(f" {name}: {c:+.3f}")
# 標準化済み変数 1 単位の影響(ロジスティック回帰の係数に類似)
# ============================================
# ⑥ 高次元データでの典型パターン
# ============================================
# Radiomics 風: N=80, d=300 を想定
# pre-screening で d を 30 程度に絞ってから RBF SVM
high_dim_pipe = Pipeline([
("scaler", StandardScaler()),
("selector", SelectKBest(f_classif, k=30)), # 上位 30 特徴量
("svc", SVC(kernel="rbf", C=1.0, gamma="scale",
probability=False)),
])
重要: scikit-learn の SVC の基本出力は、確率ではなく決定関数のスコアです。AUC 評価だけなら decision_function で十分です。確率を意思決定に使う場合は、probability=True による Platt scaling や CalibratedClassifierCV による校正を検討します。ただし、校正後の確率も検証データで calibration を確認してから解釈する必要があります[4][7]。
// 07 · MYTHSよくある誤解
- SVM はどんなデータにも強い
- 誤り。SVM は今でも有用ですが、得意な場面は限られます。Radiomics や生体信号のように特徴量が多い小規模データでは候補になります。一方、一般的な表形式データでは、ロジスティック回帰 や 勾配ブースティング と比較して選ぶ方が安全です。
- カーネルは RBF だけ試せばよい
- 不正確です。RBF カーネルはよく使われますが、線形で十分に分けられるデータでは LinearSVC の方が速く、解釈もしやすいことがあります。まず線形モデルを比較し、非線形性が必要そうであれば RBF を検討する、という順番が実務的です。
- SVM は確率を出力できる
- 不正確。SVM の本来の出力は分類スコア(マージン上の符号付き距離)であり、確率ではありません。Platt scaling で事後的に確率化できますが、確率の校正はデータや手法に依存します。意思決定に確率を使う場合は、calibration plot や Brier score などで確認します[5]。
- 標準化はなくても大きな問題にならない
- 誤りです。SVM は内積や距離に基づくため、スケールの大きい変数が境界を強く支配します。年齢、FIM、発症後日数など単位の違う変数を一緒に使う場合は、Pipeline の中で StandardScaler を組み込みます。
// 08 · WRITING論文での書き方
Methods に記述すべき項目
- SVM を選択した理由(小サンプル高次元 / Radiomics / ベースライン比較)
- カーネルの種類(線形 / RBF / 多項式)とその選択理由
- 標準化を Pipeline で行ったことの明記
- ハイパーパラメータ C と γ の探索範囲・最適化方法(CV、grid search)
- クラス不均衡への対処(
class_weight="balanced"等) - 確率出力を使った場合は Platt scaling や CalibratedClassifierCV の利用
- サポートベクター数(過学習指標として参考)
Methods の書き出し例
"We trained a Support Vector Machine classifier with an RBF
kernel for classification of MRI radiomic features (300
features, N=84). All features were standardized to zero mean
and unit variance using StandardScaler fit only on the training
fold. Hyperparameters C and γ were jointly optimized via
5-fold cross-validation with grid search (C ∈ {0.01, 0.1, 1,
10, 100}; γ ∈ {scale, auto, 0.01, 0.1, 1}), maximizing AUC.
Class imbalance (60% favorable outcome) was handled by
class_weight='balanced'. Probability estimates were obtained
via Platt scaling. The final model used C=10, γ=0.01, with 32
support vectors out of 67 training samples (48%)."
査読者が指摘しやすい点
- 「カーネルの選択理由が示されていない」
- 「C と γ の探索範囲が arbitrary に見える」
- 「標準化を行ったか明記されていない」
- 「サポートベクター数が訓練サンプルの 50% 超(過学習傾向)」
- 「Calibration の確認がない(確率を解釈する場合)」
- 「勾配ブースティングや LogReg との比較がない」
レポーティング規範は TRIPOD+AI Item 11 を参照。SVM を使用する場合、カーネル選択・C/γ の探索・サポートベクター比率を Methods や Supplementary に明記すると、再現性を高めやすくなります[6]。
// 09 · CHECKLISTチェックリスト
SVM の使い方を点検する 6 項目。
- 01SVM が適切な場面か(小サンプル高次元 / Radiomics)を判断した
- 02標準化(StandardScaler)を Pipeline 内で必ず実行
- 03カーネル(線形 / RBF / 多項式)を選択した理由がある
- 04C と γ を CV で同時最適化(grid または Bayesian search)
- 05不均衡データに
class_weight="balanced"等で対処 - 06ロジスティック回帰や勾配ブースティングと性能比較した
// 10 · QUIZミニクイズ
-
Q1「サポートベクター」とは何か?
- 訓練データの全サンプル
- マージン上または内側にある少数の点(境界を決める)
- 最も多数派のクラスの代表点
- 外れ値の集合
SHOW ANSWER
B. マージン上または(ソフトマージンでは)マージン内側に位置する点だけが、決定境界の方程式に寄与する。それ以外の点を消しても境界は変わらない。これが SVM が「サポートベクター」に基づくと呼ばれる所以。サポートベクター数が訓練サンプルの 50% 超なら過学習傾向のサイン。 -
Q2RBF カーネル SVM で C を非常に大きく(C=10000)設定した。最も起こりやすい問題は?
- under-fitting
- 過学習(マージン狭く、境界が訓練データのノイズに合わせる)
- 学習できなくなる
- 標準化が効かなくなる
SHOW ANSWER
B. C は誤分類ペナルティの強さ。C 大 → 誤分類を一切許さないハードマージン寄り → 外れ値 1 点で境界が大きく傾く(Fig.3 左)。過学習対策には C を小さくしてマージンを広く取る。CV で最適 C を探索するのが基本。 -
Q3N=5000、変数 50 個の表形式データで予後予測モデルを作る。最も効率的な選択は?
- RBF カーネル SVM
- XGBoost / LightGBM などの勾配ブースティング
- 深層学習(MLP)
- kNN
SHOW ANSWER
B. 中規模(N=5000)の表形式データは勾配ブースティングの得意領域。SVM は O(N²) で遅くなり、カテゴリ変数の OneHot で次元爆発するリスク。深層学習はサンプル不足で過学習しやすい。kNN は次元の呪いで性能低下。このサイズの表形式予後予測では、勾配ブースティングを有力候補として比較する。
// 11 · FAQよくある質問
- SVM で標準化は必要ですか?
- SVM は内積や距離に基づくため、特徴量のスケールに強く影響されます。年齢、FIM、発症後日数など単位の違う変数を使う場合は、訓練データ内で標準化を行うことが基本です。
- SVM の C と γ は何を表しますか?
- C は誤分類をどの程度許すかを調整するパラメータです。γ は RBF カーネルで、1 つの症例がどの範囲まで影響するかを調整します。どちらも過学習と過小適合のバランスに関わるため、交差検証で探索します。
- SVM は医療・リハビリ研究でどのような場面に向いていますか?
- SVM は、Radiomics や歩行波形、生体信号など、症例数に対して特徴量が多いデータで候補になります。一方、中規模以上の表形式データでは、勾配ブースティングなどと比較して選択するのが現実的です。
// REF参考文献
- Cortes C, Vapnik V. Support-vector networks. Mach Learn 1995;20:273-297. — doi
- Lambin P, Leijenaar RTH, Deist TM, et al. Radiomics: the bridge between medical imaging and personalized medicine. Nat Rev Clin Oncol 2017;14(12):749-762. — doi
- Hsu CW, Chang CC, Lin CJ. A practical guide to support vector classification. Technical Report, NTU 2003. — pdf
- Platt J. Probabilistic outputs for support vector machines and comparisons to regularized likelihood methods. In: Advances in Large Margin Classifiers. MIT Press; 1999.
- Niculescu-Mizil A, Caruana R. Predicting good probabilities with supervised learning. ICML 2005:625-632. — doi
- Collins GS, Moons KGM, et al. TRIPOD+AI statement. BMJ 2024;385:e078378. — doi
- scikit-learn developers. SVC — C-Support Vector Classification. scikit-learn documentation. — docs