カーネル法とは、データを高次元の特徴空間へ写したうえで線形の手法を当てはめ、もとの空間では直線で分けられない非線形なデータを扱えるようにする機械学習の枠組みです。中心にあるのが「カーネルトリック」で、高次元への写像そのものは計算せず、カーネル関数で2点の内積だけを求めます。サポートベクターマシン(SVM)、カーネルリッジ回帰、ガウス過程、カーネルPCAがこの仕組みで非線形化されています。この記事では、カーネルトリックの仕組みと4種類のカーネル関数の使い分けを、scikit-learn 1.9.1で実行した結果とあわせて整理し、データが数万件を超えたときの計算量の壁と回避策までを扱います。
まとめ:カーネル法とカーネル関数の要点
- カーネル法は単体の予測モデルではなく、内積だけで書ける線形手法(SVM・リッジ回帰・PCAなど)を非線形に拡張する仕組みです。
- カーネルトリックは、写像後のベクトルを作らずにカーネル関数で内積を直接求める計算上の近道です。RBFカーネルの写像先は無限次元ですが、内積は有限の式で計算できます。
- 迷ったらRBF(ガウス)カーネルから始めます。円状に分布した2クラスのデータでは、線形カーネルの正解率55.3%に対してRBFは99.7%でした。
- カーネル関数は正定値でなければ理論上の保証が崩れます。シグモイドカーネルは条件によって正定値にならず、円状データでは学習データから作ったグラム行列の固有値700個のうち65個が負で、正解率も54.7%にとどまりました。
- SVCの学習時間は件数の伸びよりずっと速く増えます(公式ドキュメントは「少なくとも2乗」と記載)。手元の計測(3回の中央値)では件数16倍で約158倍(2,000件0.10秒→32,000件15.79秒)になりました。数万件を超えたらNystroemなどのカーネル近似と線形モデルの組み合わせに切り替えます。
| 種類 | 式 | 向くデータ | 円状データの正解率 |
|---|---|---|---|
| RBF(ガウス) | exp(-γ‖x-y‖²) | 形が読めない非線形全般 | 99.7% |
| 多項式 | (γ x·y + c)^d | 特徴の積に意味がある | 99.3%(d=2) |
| 線形 | x·y | 高次元・疎(テキスト等) | 55.3% |
| シグモイド | tanh(γ x·y + c) | 通常は選ばない | 54.7% |
カーネル法とは:非線形データを線形手法で扱う枠組み
カーネル法は、入力データを写像φで高次元の特徴空間へ移し、そこで内積を使う線形の手法を適用する考え方です。原点を中心に円状に分布した2クラスのデータは、平面上の直線1本では分けられません。各点の原点からの距離の2乗を3本目の軸として足すと、内側のクラスと外側のクラスは1枚の平面で分けられるようになります。次元を上げると線形に分離できることが多い、という性質を使うのがカーネル法です。
統計数理研究所の福水健次氏による公開講座資料「さまざまなカーネル法」は、この発想を「データの非線形特徴・高次モーメントを表現するため、特徴写像によってデータを特徴空間(RKHS)に写像し、特徴空間で線形のデータ解析アルゴリズムを適用する」とまとめています。RKHS(再生核ヒルベルト空間)は、カーネル関数から一意に決まる特徴空間の数学上の呼び名です。
カーネル法は単体のモデルではなく、計算が内積の形で書ける線形手法を非線形化する部品です。機械学習のなかでは、深層学習が広まる前から、数百〜数万件のデータで精度を出す手段として使われてきました。
カーネルトリックの仕組み:写像を計算せず内積だけを求める
カーネルトリックは、写像φを陽に計算せず、カーネル関数 k(x, y) = φ(x)·φ(y) で内積だけを直接求める手法です。SVMの双対問題やリッジ回帰の多くは、入力データを内積の形でしか使いません。写像後のベクトルを組み立てなくても、対応する内積が計算できれば学習も予測も回せます。
2次元から3次元への写像で内積が一致することをPythonで確かめる
2次元の点 (x₁, x₂) を (x₁², √2·x₁x₂, x₂²) へ写す写像を考えます。2点の写像後の内積を展開すると、もとの2次元の内積を2乗した値 (x·y)² に一致します。次のコードは、写像してから内積を取った値と、内積を2乗しただけの値を比べています。
import numpy as np
x = np.array([1.0, 2.0])
z = np.array([3.0, 1.0])
def phi(v):
# 2次元を3次元へ写す多項式写像
return np.array([v[0]**2, np.sqrt(2) * v[0] * v[1], v[1]**2])
print(phi(x) @ phi(z)) # 写像してから内積
print((x @ z) ** 2) # もとの空間の内積を2乗するだけ
出力はどちらも 25.0 です。この式は多項式カーネル(γ=1, c=0, d=2)そのもので、3次元のベクトルを作らずに同じ値が得られます。次数dや入力の次元が増えると写像先の次元は組み合わせ的に増えますが、カーネル側の計算はもとの次元の内積1回で済みます。
グラム行列とRepresenter定理:計算量がデータ件数で決まる理由
カーネル法では、学習データn件のすべての組についてカーネル値を並べたn×nの行列(グラム行列、カーネル行列)を作って計算を進めます。計算量が特徴空間の次元ではなくデータ件数nで決まるのはこのためです。
この扱いを支えるのがRepresenter定理です。Schölkopf・Herbrich・Smolaの「A Generalized Representer Theorem」(COLT 2001、LNCS 2111)は、正則化つきの損失最小化の解が、学習データ点を中心に置いたカーネル関数の重み付き和 f(x) = Σ αᵢ k(xᵢ, x) で表せることを示しました。無限次元の空間で最適化しているように見えて、実際に求めるのはn個の係数αᵢだけです。scikit-learnのKernelRidgeで200件を学習すると、係数 dual_coef_ の形は (200,) になり、学習データ1件に係数が1つずつ付くことを確かめられます。
主要なカーネル関数4種の使い分けと円状データでの正解率
カーネル関数は、2点がどれだけ似ているかを内積として返す関数です。どれを選ぶかでモデルの表現力と過学習のしやすさが決まります。比較のため、scikit-learnの make_circles で作った円状の2クラス1,000件(ノイズ0.1)を7:3に分け、標準化してから4種類のカーネルでSVCを学習しました。
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
X, y = make_circles(n_samples=1000, noise=0.1, factor=0.4, random_state=0)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=0, stratify=y)
for kernel, params in [("linear", {}), ("poly", {"degree": 2}), ("rbf", {}), ("sigmoid", {})]:
model = make_pipeline(StandardScaler(), SVC(kernel=kernel, **params)).fit(X_tr, y_tr)
print(kernel, round(model.score(X_te, y_te), 3), model[-1].n_support_.sum())
| kernel | テスト正解率 | サポートベクター数 |
|---|---|---|
| linear | 0.553 | 678 |
| poly(degree=2) | 0.993 | 36 |
| rbf | 0.997 | 53 |
| sigmoid | 0.547 | 367 |
学習データ700件のうち、線形カーネルでは678件がサポートベクターになりました。境界を決めきれず、ほぼ全点が境界付近に残った状態です。
RBFカーネル(ガウスカーネル):γで境界の細かさを決める
RBFカーネル(radial basis function)は k(x, y) = exp(-γ‖x-y‖²) で、2点の距離が近いほど1に近い値を返します。ガウスカーネルとも呼ばれ、exp(-‖x-y‖²/(2σ²)) と書く流儀ではγ = 1/(2σ²) の関係です。scikit-learnのSVCは kernel の既定値が 'rbf'、gamma の既定値が 'scale' で、このとき γ = 1 / (特徴量の数 × Xの分散) が使われます。
scikit-learnのRBF SVMのパラメータの公式例は、gammaを「1つの学習データの影響がどこまで及ぶか」を決める値と説明しています。上のコードで SVC(kernel="rbf", gamma=gamma) とし、γを0.01〜1000で振って学習データとテストデータの正解率を並べると、次のようになりました(C=1、標準化済み)。
| gamma | 学習 | テスト | サポートベクター数 |
|---|---|---|---|
| 0.01 | 0.741 | 0.690 | 694 |
| 0.1 | 0.999 | 1.000 | 131 |
| 1 | 1.000 | 0.997 | 48 |
| 10 | 1.000 | 0.997 | 177 |
| 100 | 1.000 | 0.987 | 569 |
| 1000 | 1.000 | 0.837 | 691 |
γ=0.01では境界がなめらかすぎて未学習になり、γ=1000では学習データを100%当てながらテストは83.7%まで落ちました。各点の影響範囲が狭すぎて、学習データの点そのものを囲む境界になったためです。サポートベクター数がU字に動くので、学習正解率が高いのにサポートベクターが学習データの大半を占めていたら、γが大きすぎると判断できます。距離で効くカーネルなので、特徴量の単位がそろっていないと一部の特徴だけで距離が決まります。RBFを使うときは標準化を前処理に入れてください。
多項式カーネル:次数dで特徴の積をどこまで見るかを決める
多項式カーネルは k(x, y) = (γ x·y + c)^d で、次数dを上げるほど高次の特徴の組み合わせ(交互作用)を捉えます。d=1なら線形カーネルと同じで、d=2なら特徴どうしの2次の積を扱います(cが0より大きければ1次の項と定数も入ります)。円状データでは、半径の2乗が x₁² + x₂² で表せるため、d=2で99.3%に届きました。
scikit-learnのSVCでは degree の既定値が3、coef0(式のc)の既定値が0.0です。c=0のままだと (γ x·y)^3 になり、3次の項だけが残って1次・2次の項は消えます。低次の項も効かせたいなら coef0=1 などを明示します。LIBSVMの実践ガイドは、次数が大きいと多項式カーネルの値が無限大か0に近づき、数値的に扱いにくくなると指摘しています。過学習も起きやすくなるので、d=2〜3にとどめるのが実務での目安です。scikit-learnではRBFと同じ gamma 引数を使いますが、多項式カーネルのγは内積のスケール係数で、影響範囲を決めるRBFのγとは役割が違います。
線形カーネル:高次元・疎なデータで先に試す
線形カーネルは k(x, y) = x·y で、写像を行わずもとの内積をそのまま使います。円状データでは55.3%と役に立ちませんでしたが、特徴量が数千〜数万次元あるデータでは事情が逆になります。単語の出現をベクトル化したテキスト分類(Bag of WordsやTF-IDF)がその代表で、すでに線形に分けやすいことが多く、RBFに替えても精度が伸びにくいうえ学習が遅くなります。LIBSVMの実践ガイド(付録C)も、特徴量の数が多いときは高次元へ写しても性能が上がらず、線形カーネルで十分だとしています。特徴量が多いデータでは、線形カーネル(またはLinearSVC)から試します。
シグモイドカーネル:正定値にならず通常は選ばない
シグモイドカーネルは k(x, y) = tanh(γ x·y + c) で、2層のニューラルネットワークに似た形をしています。SVCが内部で使うLIBSVMの公式FAQは、シグモイドカーネルで作ったカーネル行列は正定値にならない場合があると明記しています。同じFAQは、精度も一般にRBFを上回らないとしています。円状データでは54.7%と線形カーネル並みにとどまり、この学習データ700件で作ったシグモイドのグラム行列(SVCの既定と同じγ=0.5, c=0)も、固有値700個のうち65個が負でした。特別な理由がなければ選びません。
カーネル関数が満たす条件:正定値性とMercerの定理
2変数の関数なら何でもカーネルとして使えるわけではありません。k(x, y) がある写像φの内積として書けるには、どんなデータ点の組を選んでもグラム行列が半正定値(固有値がすべて0以上)でなければなりません。この条件を満たす関数を正定値カーネルと呼びます。連続関数について、正定値であることと固有関数展開で内積の形に書けることを結び付けたのが、James Mercerが1909年に発表したMercerの定理(Phil. Trans. R. Soc. A, 209巻)です。
正定値かどうかは、グラム行列の固有値を計算すれば確かめられます。正規分布から200点(5次元)を取り、3種類のカーネルでグラム行列を作って最小固有値を見ました。
import numpy as np
from sklearn.metrics.pairwise import rbf_kernel, polynomial_kernel, sigmoid_kernel
A = np.random.default_rng(0).normal(size=(200, 5))
for name, K in [
("rbf", rbf_kernel(A, gamma=0.5)),
("poly", polynomial_kernel(A, degree=2, gamma=1, coef0=1)),
("sigmoid", sigmoid_kernel(A, gamma=1, coef0=1)),
]:
eig = np.linalg.eigvalsh(K) # 対称行列の固有値
print(name, "最小固有値=%.4g" % eig.min(), "負の固有値の数=%d" % (eig < -1e-8).sum())
| カーネル | 最小固有値 | 負の固有値の数 |
|---|---|---|
| RBF(γ=0.5) | 0.004674 | 0 |
| 多項式(d=2, c=1) | -4.387e-13 | 0 |
| シグモイド(γ=1, c=1) | -16.67 | 100 |
多項式カーネルの -4.387e-13 は浮動小数点の丸め誤差で、実質0です。シグモイドは200個の固有値のうち100個が負で、どの特徴空間の内積としても表せない行列になっています。この状態ではSVMの最適化問題が凸でなくなり、解の一意性の保証がなくなります。
実務で役立つのは、正定値カーネルどうしの和・積・正の定数倍も正定値になるという性質です。「RBF+線形」のように既存のカーネルを足し合わせて新しいカーネルを組んでも、条件は崩れません。ガウス過程のカーネル設計は、この組み合わせを前提にしています。
カーネル法の主な応用:SVM・カーネル回帰・ガウス過程・カーネルPCA
サポートベクターマシン(SVM):カーネル法の代表的な使い道
SVMは、2クラスの間の余白(マージン)が最大になる境界を求める分類手法です。双対問題が学習データの内積だけで書けるため、内積をカーネル関数に置き換えれば非線形の境界を引けます。境界を決めるのは一部の学習データ(サポートベクター)だけで、予測時もサポートベクターとのカーネル値だけを計算します。上の円状データでRBFを使ったSVCは、700件中53件のサポートベクターで99.7%を出しました。
カーネル回帰:カーネルリッジ回帰とNadaraya-Watson推定の違い
「カーネル回帰」という言葉は、仕組みの違う2つの手法を指します。1つは本記事の意味でのカーネル法を回帰に使うカーネルリッジ回帰です。scikit-learnのユーザーガイドは、L2正則化付きの最小二乗(リッジ回帰)とカーネルトリックを組み合わせたもの、と定義しています。同じページは、モデルの形はサポートベクター回帰(SVR)と同じで、損失が二乗誤差かε不感応損失かが違うと説明しています。KernelRidgeは閉じた式で学習できて中規模データではSVRより速い一方、全学習データに係数が付くため予測はSVRより遅くなります。
もう1つは、予測したい点の近くにある観測値をカーネルで重み付けして平均するNadaraya-Watson推定です。statsmodelsのKernelRegは、reg_type の「local constant」がNadaraya-Watsonカーネル回帰にあたると説明しています。こちらのカーネルはデータを平滑化する重み(カーネル密度推定と同じ種類)で、正定値カーネルによる特徴空間の内積とは別物です。
sin関数にノイズを足した200点で、通常のリッジ回帰とRBFカーネルのカーネルリッジ回帰を比べると、真の曲線に対する誤差(RMSE)は0.420と0.043でした。
import numpy as np
from sklearn.kernel_ridge import KernelRidge
from sklearn.linear_model import Ridge
rng = np.random.default_rng(0)
X = np.sort(rng.uniform(0, 6, 200))[:, None]
y = np.sin(X).ravel() + rng.normal(0, 0.2, 200)
X_test = np.linspace(0, 6, 500)[:, None]
for name, model in [("Ridge", Ridge(alpha=1.0)), ("KernelRidge", KernelRidge(kernel="rbf", alpha=0.1, gamma=1.0))]:
model.fit(X, y)
rmse = np.sqrt(((model.predict(X_test) - np.sin(X_test).ravel()) ** 2).mean())
print(name, round(rmse, 3))
print(KernelRidge(kernel="rbf").fit(X, y).dual_coef_.shape) # 学習データ1件ごとに係数が1つ
KernelRidgeの kernel の既定値は 'linear' です。kernel="rbf" を書き忘れると、切片のないリッジ回帰(Ridge(fit_intercept=False))と同じ、原点を通る直線しか引けません。
ガウス過程回帰:カーネルを共分散として予測の不確かさまで出す
ガウス過程回帰は、カーネル関数を「2点の出力がどれだけ連動するか」を表す共分散として使い、予測値と一緒に予測の不確かさ(分散)を返します。scikit-learnのGaussianProcessRegressorは、kernel を指定しないと ConstantKernel() * RBF() を使います。ユーザーガイドによると、カーネルのハイパーパラメータは学習時に対数周辺尤度を最大化して決まります。SVMのγのように交差検証で探さなくてよい反面、既定のカーネルにはノイズの項がありません(alpha の既定値は1e-10)。カーネル回帰の節と同じsin+ノイズの200点では、既定のままだと長さスケールが0.000738まで縮んで誤差(RMSE)0.695でしたが、ノイズをデータから推定する WhiteKernel() を足すと長さスケール2.01・RMSE 0.027になりました。対数周辺尤度には局所解が複数あり得るので、n_restarts_optimizer で初期値を変えた再最適化も使えます。少ない試行回数で応答を推定したい実験計画やシミュレーションの代替モデル(CAEを機械学習で高速化するサロゲートモデル)でよく使われます。
カーネルPCA:非線形な方向のばらつきを取り出す次元削減
カーネルPCAは、特徴空間で主成分分析を行う手法です。計算はグラム行列(中心化したもの)の固有値分解に帰着します。前出の福水氏の講義資料には、13次元・178件のワインのデータ(UCI Wine)での通常のPCAとの比較や、手書き数字7,291件(USPS)のノイズ除去の例があります。主成分軸を元の特徴量で解釈しにくく、元の空間へ戻す計算(pre-image問題)も別に要るため、結果の説明が求められる分析には通常のPCAを使います。
scikit-learnでのカーネルSVM実装とγ・Cの調整
scikit-learnでカーネルSVMを組むときは、標準化とSVCを1本のパイプラインにまとめ、γとCを交差検証で同時に探します。標準化をパイプラインの外で全データに当てると、検証用データの平均や分散が学習に漏れます。scikit-learnのパイプラインに入れておけば、分割ごとに学習側だけで標準化の値を計算します。
from sklearn.datasets import make_circles
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
X, y = make_circles(n_samples=1000, noise=0.1, factor=0.4, random_state=0)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=0, stratify=y)
pipe = make_pipeline(StandardScaler(), SVC(kernel="rbf"))
grid = {"svc__C": [0.1, 1, 10, 100], "svc__gamma": [0.01, 0.1, 1, 10]}
search = GridSearchCV(pipe, grid, cv=5).fit(X_tr, y_tr)
print(search.best_params_)
print(round(search.best_score_, 3), round(search.score(X_te, y_te), 3))
実行結果は {‘svc__C’: 1, ‘svc__gamma’: 10} で、5分割交差検証の平均正解率1.0、テスト正解率0.997でした。γ=10ではC=1・10・100の3通りが交差検証で同点(1.0)で、GridSearchCVは探索順で先に来たC=1を返しています。Cは誤分類をどこまで許すかを決める値で、大きいほど学習データに合わせ込みます。scikit-learnのSVMユーザーガイドもCとgammaの選び方が性能を大きく左右すると書いており、2つは組で探します。LIBSVMの実践ガイドが勧めるとおり、範囲は指数的に増やす数列(ここでは10倍刻み)で粗く取り、良い区間が見えたら細かくします。探索の打ち切り方はハイパーパラメータ探索、分割の選び方は交差検証の記事で詳しく扱っています。
データが数万件を超えたときの計算量とカーネル近似
カーネル法の弱点は計算量です。SVCの公式ドキュメントは、学習時間はサンプル数に対して少なくとも2乗で増え、数万件を超えると実用的でなくなる場合があると書いています。そのうえで、大規模データにはLinearSVCかSGDClassifierを使い、必要ならNystroemなどのカーネル近似を前段に置くよう勧めています。
グラム行列をfloat64で丸ごと持つと、1万件で0.8GB、10万件で80GBになります。この節では、20次元の2クラス分類データ(make_classification、テストは別の5,000件)で、学習件数を倍々に増やしてSVCとカーネル近似の学習時間とテスト正解率を測りました(Intel Core i9-9880H・macOS、学習時間は3回計測の中央値)。各セルは「学習時間/テスト正解率」です。件数ごとに別に生成したデータなので、行どうしの正解率は同じ問題の比較ではありません。近似は300次元とし、近似側のγもSVCの既定値と同じ0.05にそろえています。
| 学習件数 | SVC(RBF) | Nystroem+LinearSVC | RBFSampler+LinearSVC |
|---|---|---|---|
| 2,000 | 0.10秒/0.923 | 0.20秒/0.920 | 0.13秒/0.860 |
| 4,000 | 0.46秒/0.940 | 0.38秒/0.923 | 0.33秒/0.873 |
| 8,000 | 1.53秒/0.956 | 0.78秒/0.945 | 0.70秒/0.900 |
| 16,000 | 4.76秒/0.953 | 1.61秒/0.937 | 1.58秒/0.889 |
| 32,000 | 15.79秒/0.968 | 4.04秒/0.943 | 3.32秒/0.893 |
件数を16倍にするとSVCの学習時間は約158倍になり、件数を倍にするごとに3.1〜4.6倍ずつ伸びました。2乗の256倍には届いていませんが、件数の伸びをはるかに上回る増え方です。近似の2つは件数16倍で20〜26倍とほぼ件数に比例して伸び、32,000件ではSVCの4〜5分の1の時間です。そのぶん正解率は落ち、SVCとの差はNystroemで2.5ポイント、RBFSamplerで7.5ポイントでした。
次のコードは表の32,000件の行(正解率)を再現します。学習時間は各 fit を time.perf_counter() で挟んで測りました。
from sklearn.datasets import make_classification
from sklearn.kernel_approximation import Nystroem, RBFSampler
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC, LinearSVC
X, y = make_classification(n_samples=37000, n_features=20, n_informative=10, random_state=0)
X_tr, X_te, y_tr, y_te = X[:32000], X[32000:], y[:32000], y[32000:]
gamma = 1 / 20 # 標準化後の SVC(gamma="scale") と同じ値にそろえる
models = {
"SVC": make_pipeline(StandardScaler(), SVC(kernel="rbf")),
"Nystroem": make_pipeline(StandardScaler(), Nystroem(gamma=gamma, n_components=300, random_state=0), LinearSVC()),
"RBFSampler": make_pipeline(StandardScaler(), RBFSampler(gamma=gamma, n_components=300, random_state=0), LinearSVC()),
}
for name, model in models.items():
print(name, round(model.fit(X_tr, y_tr).score(X_te, y_te), 3))
2つの近似は作り方が違います。Nystroemは学習データの一部を基底に選んで任意のカーネルの特徴写像を近似し、RBFSamplerはランダムフーリエ特徴でRBFカーネルだけを近似します。後者のもとになったのは、Rahimi・Rechtの「Random Features for Large-Scale Kernel Machines」(NIPS 2007)です。今回は、データから基底を選ぶNystroemのほうがSVCに近い精度でした。
注意したいのは、RBFSamplerの gamma の既定値が SVC の 'scale' ではなく固定の1.0だという点です。gammaを指定せずに同じ実験をすると、20次元・標準化済みのデータでは影響範囲が狭すぎて、どの件数でも正解率が0.489〜0.503(当て推量と同じ)でした。SVCから近似へ置き換えるときは、gammaを明示してそろえてください。
カーネル法を選ぶべき場面と避けるべき場面
カーネル法が向くのは、学習データが数百〜数万件で、特徴量がある程度作り込まれた表形式のデータです。SVMやカーネルリッジ回帰はハイパーパラメータを決めれば凸最適化で解が決まるので、同じデータと設定なら毎回同じ解になり、調整するハイパーパラメータもRBFならγとCの2つで済みます。ガウス過程なら予測の不確かさまで出せます。件数が少なくて深層学習では過学習する場面では、今でも有力な選択肢です。
次の条件に当てはまるなら、カーネル法は選びません。
- 学習データが10万件を超える:グラム行列を丸ごと持つKernelRidgeやガウス過程は80GB規模のメモリが必要になります。SVC(LIBSVM)は行列を丸ごと持たずキャッシュ(既定200MB)で計算しますが、学習時間が件数の2乗前後で伸びるため現実的な時間では終わりません。近似を使っても精度が落ちるので、勾配ブースティングやニューラルネットワークと比べてから決めます。
- 入力が画像・音声・文章の生データ:どの特徴が効くかをカーネル関数1つで表すのは難しく、特徴そのものを学習する深層学習のほうが向きます。カーネル法を使うなら、学習済みモデルの埋め込みベクトルを入力にします。
- 判断の根拠を特徴量単位で説明する必要がある:RBFカーネルのSVMは、どの特徴量がどれだけ効いたかを係数として読めません。説明が要件なら線形モデルか決定木系を選びます。
- 予測の応答時間が厳しい:予測のたびにサポートベクター全件(KernelRidgeなら学習データ全件)とのカーネル値を計算するので、件数に比例して予測が遅くなります。
自社のデータでどの手法が合うかの見極めから実装・運用まで相談したい場合は、一創の機械学習モデル開発の支援内容をご覧ください。
よくある質問
機械学習の「カーネル」は、OSや画像処理のカーネルと同じ意味ですか?
別物です。機械学習のカーネルは2点の類似度を内積として返す関数で、OSのカーネルはハードウェアとアプリケーションを仲立ちするLinuxなどの中核部分を指します。画像処理のカーネルは、ぼかしやエッジ検出で画素に掛ける小さな重みの行列(フィルタ)のことです。線形代数では、行列を掛けると0になるベクトルの集合(零空間・核)をカーネルと呼びます。
カーネル法は線形ですか、非線形ですか?
特徴空間では線形、もとの入力空間では非線形です。高次元へ写した先では超平面という線形の境界を引いており、それを元の空間に戻すと曲線や曲面の境界になります。線形カーネルを選んだ場合だけは、元の空間でも線形のままです。
カーネル法とSVMはどういう関係ですか?
SVMはカーネル法を組み込める分類手法の1つで、カーネル法はSVMに限らない仕組みです。SVM自体は線形の境界を引く手法として始まり、内積をカーネル関数に置き換えることで非線形の分類ができるようになりました。同じ置き換えは、リッジ回帰・PCA・ガウス過程にも使えます。
カーネル密度推定はカーネル法と同じものですか?
名前は似ていますが別の手法です。カーネル密度推定は、各データ点にガウス関数などの山を置いて重ね合わせ、データの分布をなめらかに推定する方法です。ここでのカーネルは面積が1になる重み関数で、特徴空間の内積を表す正定値カーネルとは役割が違います。ガウス関数がどちらにも登場するため混同されやすい点に注意してください。
量子カーネル法とは何ですか?
量子回路でデータを特徴空間へ写し、その内積(カーネル値)を量子コンピュータで推定して、古典的なSVMに渡す手法です。Havlíčekらが2019年にNature 567巻で発表した「Supervised learning with quantum-enhanced feature spaces」が、この手法を示した代表的な論文にあたります。カーネルトリックの枠組みはそのままで、カーネル値の計算だけを量子コンピュータに任せる構成です。