Look for the interactive boxes: Why a Straight Line Fails (Section 02), The Bouncer’s Platform (03), Four Kernels, Same Data (04), Strict vs Lenient Teacher: C (11), Torchlight vs Floodlight: Gamma (12), Live Grid Search (14) and Grid vs Random Search (15). They all run live in your browser.
The Bouncer at the Nightclub
But on a busy night the VIPs stand in a circle in the middle of the floor, completely surrounded by regular guests. Now no straight rope works. However the bouncer turns it, some VIPs end up on the wrong side.
This is exactly the problem a linear SVM has. The kernel trick is the bouncer’s clever solution: change the floor into a bowl — the middle stays low and the edges rise. Now the VIPs and the regulars are at different heights, and a flat sheet (a plane) can separate them perfectly.
That change of height is the core idea behind SVM kernels. This tutorial goes step by step — why 2D fails, how a third dimension solves it, the four kernels you will use in Python, and then how to tune the two most important settings: C and γ (gamma).
A kernel is a similarity function K(a, b). It gives the dot product of two points as if they had been moved into a higher-dimensional space — without ever doing that expensive move. It is a mathematical shortcut that makes high-dimensional geometry affordable.
Why a Straight Line Fails
A basic (linear) SVM finds the widest possible straight line in 2D — or hyperplane in more dimensions — between two classes. This works beautifully when the data is linearly separable. Real data is often not that polite.
Try It — Why a Straight Line Fails
Choose a data shape and train a linear SVM. Then switch to the RBF kernel and watch the boundary bend.
इन interactive boxes को देखिए: Why a Straight Line Fails (सेक्शन 02), The Bouncer’s Platform (03), Four Kernels, Same Data (04), Strict vs Lenient Teacher: C (11), Torchlight vs Floodlight: Gamma (12), Live Grid Search (14) और Grid vs Random Search (15)। ये सब आपके browser में live चलते हैं।
Nightclub का Bouncer
पर भीड़ वाली रात में VIPs floor के बीच में एक गोले में खड़े होते हैं, और आम मेहमान उन्हें चारों ओर से घेर लेते हैं। अब कोई सीधी रस्सी काम नहीं करती। Bouncer उसे कैसे भी घुमाए, कुछ VIPs ग़लत तरफ़ रह जाते हैं।
Linear SVM के साथ ठीक यही समस्या है। Kernel trick bouncer का चालाक हल है: floor को एक कटोरे में बदल दो — बीच का हिस्सा नीचे रहता है और किनारे ऊपर उठते हैं। अब VIPs और आम मेहमान अलग-अलग ऊँचाई पर हैं, और एक सपाट चादर (एक plane) उन्हें पूरी तरह अलग कर सकती है।
ऊँचाई का यही बदलाव SVM kernels का मूल विचार है। यह tutorial एक-एक कदम चलता है — 2D क्यों फ़ेल होता है, तीसरा dimension इसे कैसे हल करता है, Python में आप कौन-से चार kernels इस्तेमाल करेंगे, और फिर दो सबसे ज़रूरी settings को कैसे tune करें: C और γ (gamma)।
Kernel एक similarity function K(a, b) है। यह दो points का dot product देता है, मानो उन्हें किसी ज़्यादा dimensions वाले space में ले जाया गया हो — पर वह महँगा कदम कभी उठाना नहीं पड़ता। यह गणित का एक shortcut है, जो ज़्यादा dimensions वाली geometry को सस्ता बना देता है।
सीधी Line क्यों फ़ेल होती है
एक साधारण (linear) SVM दो classes के बीच 2D में सबसे चौड़ी संभव सीधी line ढूँढता है — या ज़्यादा dimensions में hyperplane। जब data linearly separable हो, तब यह बहुत बढ़िया काम करता है। पर असली data अक्सर इतना सीधा-सादा नहीं होता।
ख़ुद आज़माइए — Why a Straight Line Fails
Data का कोई आकार चुनिए और एक linear SVM train कीजिए। फिर RBF kernel पर जाइए और boundary को मुड़ते हुए देखिए।
请留意这些可以互动的方框:Why a Straight Line Fails(第 02 节)、The Bouncer’s Platform(03)、Four Kernels, Same Data(04)、Strict vs Lenient Teacher: C(11)、Torchlight vs Floodlight: Gamma(12)、Live Grid Search(14)和 Grid vs Random Search(15)。它们都在你的浏览器里实时运行。
夜店门口的保安
但在热闹的晚上,VIP 在舞池中间站成一个圆圈,四周被普通客人完全围住。 这时候没有一根直的绳子管用。不管保安怎么转绳子,总有一些 VIP 落在错误的一边。
linear SVM 遇到的正是这个问题。kernel trick 就是保安的聪明办法: 把舞池变成一个碗 —— 中间保持低,边缘升高。现在 VIP 和普通客人在不同的高度上, 一张平的板子(一个平面)就能把他们完美地分开。
这种高度的变化,就是 SVM kernel 背后的核心思想。本教程一步一步讲 —— 为什么 2D 会失败,第三个 dimension 怎样解决问题,你在 Python 里会用到的四种 kernel, 然后是怎样调最重要的两个设置:C 和 γ(gamma)。
kernel 是一个相似度函数 K(a, b)。它给出两个点的 dot product,就好像 它们已经被搬到了一个 dimension 更高的空间里 —— 但从来不用真的做这次代价很高的搬动。 它是一条数学捷径,让高 dimension 的几何变得用得起。
为什么直线会失败
基本的(linear)SVM 在两个 class 之间找尽可能宽的直线(在 2D 中)—— 在更多 dimension 中就是 hyperplane。 当数据可以线性分开时,它的效果非常好。可真实数据往往没那么听话。
动手试试 —— Why a Straight Line Fails
选一种数据形状,训练一个 linear SVM。然后换成 RBF kernel,看边界怎样弯曲。
A linear SVM assumes the classes can be split (almost) by a straight line or flat plane. Give it circular data and it still draws a line — with poor accuracy. The kernel trick removes this limit.
Lifting Data into 3D — The Kernel Trick
From the side you now see the red dots at the bottom of a bowl and the blue dots high up on its sides. A flat sheet of cardboard — a hyperplane — can slide between them and separate them perfectly.
The new height was
z = x² + y². That is a feature map φ(x) — a rule that creates a new dimension.
A kernel is the shortcut that gives the dot products of those new points directly.
Try It — The Bouncer’s Platform
Press Lift into 3D, then move the plane height. When no point is on the wrong side, look at the top view: the flat plane has become a circle.
Linear SVM मानकर चलता है कि classes को (लगभग) एक सीधी line या सपाट plane से बाँटा जा सकता है। उसे गोल data दीजिए, तब भी वह line ही बनाएगा — और accuracy ख़राब होगी। Kernel trick यह सीमा हटा देता है।
Data को 3D में उठाना — Kernel Trick
अब बग़ल से देखने पर लाल बिंदु एक कटोरे की तली में दिखते हैं और नीले बिंदु उसकी दीवारों पर ऊपर। Cardboard की एक सपाट शीट — एक hyperplane — इनके बीच से खिसकाई जा सकती है और इन्हें पूरी तरह अलग कर सकती है।
नई ऊँचाई थी
z = x² + y²। यह एक feature map φ(x) है — एक नियम जो नया dimension बनाता है।
Kernel वह shortcut है जो इन नए points के dot products सीधे दे देता है।
ख़ुद आज़माइए — The Bouncer’s Platform
3D में उठाएँ दबाइए, फिर plane की ऊँचाई बदलिए। जब कोई point ग़लत तरफ़ न रहे, तो ऊपर वाला view देखिए: सपाट plane एक circle बन गया है।
linear SVM 假设两个 class 能(几乎)被一条直线或一个平的平面分开。 给它圆形的数据,它还是会画一条直线 —— accuracy 很差。kernel trick 去掉了这个限制。
把数据抬升到 3D —— Kernel Trick
从侧面看,红点在碗底,蓝点在碗壁的高处。 一张平的硬纸板 —— 一个 hyperplane —— 可以从它们中间滑进去,把它们完美地分开。
新的高度是
z = x² + y²。这就是一个 feature map φ(x) —— 一条创造新 dimension 的规则。
kernel 是一条捷径,它直接给出这些新点之间的 dot product。
动手试试 —— The Bouncer’s Platform
按抬升到 3D,然后移动平面高度。当没有点在错误的一边时,看看俯视图:平的平面变成了一个圆。
The SVM training and prediction formulas only need dot products between pairs of points, never the coordinates themselves. A kernel gives those dot products directly from the original data. You get the power of a 1,000-dimensional (or infinite-dimensional) space while doing arithmetic only in 2D. The price: the SVM must compare points in pairs, so training cost grows quickly with the number of rows.
The Four Kernel Types
scikit-learn’s SVC has four built-in kernels, plus two ways to bring your own. Each kernel measures similarity in a different way — and therefore gives a different shape of decision boundary.
Try It — Four Kernels, Same Data
All four kernels are trained live on the same data. Switch data shapes and compare. On circles, set the polynomial degree to 3 and untick coef0 r = 1 — then see what happens.
SVM के training और prediction formulas को सिर्फ़ points के जोड़ों के बीच dot products चाहिए, ख़ुद coordinates कभी नहीं। Kernel ये dot products सीधे मूल data से दे देता है। आपको 1,000 dimensions (या अनंत dimensions) वाले space की ताक़त मिलती है, जबकि हिसाब सिर्फ़ 2D में होता है। क़ीमत: SVM को points की जोड़ियों में तुलना करनी पड़ती है, इसलिए rows की संख्या के साथ training की cost तेज़ी से बढ़ती है।
चार तरह के Kernels
scikit-learn के SVC में चार built-in kernels हैं, और अपना kernel लाने के दो तरीक़े भी। हर kernel similarity को अलग तरह से मापता है — इसलिए हर एक decision boundary का अलग आकार देता है।
ख़ुद आज़माइए — Four Kernels, Same Data
चारों kernels एक ही data पर live train होते हैं। Data का आकार बदलिए और तुलना कीजिए। Circles पर polynomial degree को 3 कीजिए और coef0 r = 1 का tick हटाइए — फिर देखिए क्या होता है।
SVM 的训练和预测公式只需要点与点之间的 dot product,从来不需要坐标本身。 kernel 直接从原始数据给出这些 dot product。你得到了 1,000 个 dimension(甚至无限 dimension)空间的能力,计算却只在 2D 中进行。 代价是:SVM 必须把点两两比较,所以训练成本会随着行数快速增长。
四种 Kernel 类型
scikit-learn 的 SVC 有四种内置的 kernel,另外还有两种方法使用你自己的 kernel。每种 kernel 用不同的方式衡量相似度 —— 所以会给出不同形状的 decision boundary。
动手试试 —— Four Kernels, Same Data
四种 kernel 都在同一份数据上实时训练。换一换数据形状,比较一下。在圆环数据上,把 polynomial degree 设为 3,并取消勾选 coef0 r = 1 —— 然后看看会发生什么。
Deep Dive — Each Kernel Type
① Linear Kernel
The simplest kernel: the plain dot product of two vectors. No transformation. The SVM finds a straight hyperplane.
गहराई से — हर Kernel Type
① Linear Kernel
सबसे simple kernel: दो vectors का सीधा dot product। कोई बदलाव नहीं। SVM एक सीधा hyperplane ढूँढता है।
深入了解 —— 每种 Kernel 类型
① Linear Kernel
最简单的 kernel:两个 vector 的普通 dot product。没有任何变换。SVM 找的是一个直的 hyperplane。
from sklearn.svm import SVC
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
# 500 samples, 10 features, 5 of them informative
X, y = make_classification(n_samples=500, n_features=10, n_informative=5, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = make_pipeline(StandardScaler(), SVC(kernel="linear", C=1.0))
model.fit(X_train, y_train)
print(f"Linear kernel test accuracy: {model.score(X_test, y_test):.3f}")
print(f"Support vectors: {model[-1].n_support_.sum()} of {len(X_train)}")
81% accuracy. This synthetic data is not fully linear, so a straight boundary leaves some errors — and 158 of 400 points end up as support vectors.
For large datasets with a linear kernel, use sklearn.svm.LinearSVC instead of SVC(kernel='linear').
It uses a different solver (liblinear instead of libsvm) whose training time grows roughly linearly with the number of rows,
while SVC grows between n² and n³.
② RBF Kernel (Gaussian)
The Radial Basis Function kernel is the workhorse of SVMs. When you do not know which kernel to use, start here. Its feature space has infinitely many dimensions, and it creates smooth, flexible boundaries.
C sets the trade-off between a wide margin and few training mistakes. γ sets how far the influence of one training point reaches. Tune both together with GridSearchCV (Sections 11–14).
81% accuracy। यह synthetic data पूरी तरह linear नहीं है, इसलिए सीधी boundary कुछ ग़लतियाँ छोड़ देती है — और 400 में से 158 points support vectors बन जाते हैं।
Linear kernel वाले बड़े datasets के लिए SVC(kernel='linear') की जगह sklearn.svm.LinearSVC इस्तेमाल कीजिए।
यह एक अलग solver इस्तेमाल करता है (libsvm की जगह liblinear), जिसका training time rows की संख्या के साथ लगभग linear बढ़ता है,
जबकि SVC का time n² और n³ के बीच बढ़ता है।
② RBF Kernel (Gaussian)
Radial Basis Function kernel SVMs का सबसे मेहनती kernel है। जब पता न हो कि कौन-सा kernel लें, तो यहीं से शुरू कीजिए। इसके feature space में अनंत dimensions होते हैं, और यह smooth, flexible boundaries बनाता है।
C चौड़े margin और training की कम ग़लतियों के बीच संतुलन तय करता है। γ तय करता है कि एक training point का असर कितनी दूर तक पहुँचे। दोनों को GridSearchCV के साथ एक साथ tune कीजिए (सेक्शन 11–14)।
81% 的 accuracy。这份合成数据不完全是 linear 的,所以一条直的边界会留下一些错误 —— 400 个点里有 158 个成了 support vectors。
对于用 linear kernel 的大 dataset,用 sklearn.svm.LinearSVC,不要用 SVC(kernel='linear')。
它用的是另一个 solver(liblinear,而不是 libsvm),训练时间大约随行数线性增长,
而 SVC 的增长在 n² 和 n³ 之间。
② RBF Kernel(Gaussian)
Radial Basis Function kernel 是 SVM 的主力。当你不知道该用哪个 kernel 时,就从这里开始。它的 feature 空间有无限多个 dimension,能产生平滑、灵活的边界。
C 决定宽 margin 和少犯训练错误之间的取舍。γ 决定一个训练点的影响能到多远。用 GridSearchCV 把两个一起调(第 11–14 节)。
from sklearn.svm import SVC
from sklearn.datasets import make_circles
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# Circular data: a linear SVM would fail here
X, y = make_circles(n_samples=400, noise=0.1, factor=0.4, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Scaler INSIDE the pipeline, so each CV fold is scaled using only its own training part
pipe = Pipeline([("scaler", StandardScaler()), ("svm", SVC(kernel="rbf"))])
param_grid = {
"svm__C": [0.1, 1, 10, 100],
"svm__gamma": ["scale", "auto", 0.01, 0.1, 1],
}
grid = GridSearchCV(pipe, param_grid, cv=5, scoring="accuracy")
grid.fit(X_train, y_train)
print(f"Best params: {grid.best_params_}")
print(f"Best CV acc: {grid.best_score_:.3f}")
print(f"Test accuracy: {grid.score(X_test, y_test):.3f}")
This circle dataset is easy for RBF: cross-validation reaches 100%. Notice that the StandardScaler sits inside the pipeline —
if you scale all training data before the grid search, each validation fold has already “seen” the others (a small data leak).
③ Polynomial Kernel
The polynomial kernel adds feature interactions up to degree d. Degree 2 includes all pairwise products (x₁x₂, x₁², x₂²…). Degree 3 adds cubic terms.
coef0=0), only terms of exactly degree d remain. Degree 3 then has only cubic terms — no x₁², no x₂².
यह circle dataset RBF के लिए आसान है: cross-validation 100% तक पहुँचता है। ध्यान दीजिए कि StandardScaler pipeline के अंदर है —
अगर आप grid search से पहले पूरे training data को scale करें, तो हर validation fold बाक़ी folds को पहले ही “देख” चुका होता है (थोड़ा-सा data leak)।
③ Polynomial Kernel
Polynomial kernel feature interactions जोड़ता है — degree d तक। Degree 2 में सारे जोड़ीदार products आते हैं (x₁x₂, x₁², x₂²…)। Degree 3 cubic terms जोड़ता है।
coef0=0), सिर्फ़ ठीक degree d वाले terms बचते हैं। तब degree 3 में सिर्फ़ cubic terms होते हैं — न x₁², न x₂²।
这个圆环 dataset 对 RBF 来说很容易:cross-validation 达到 100%。注意 StandardScaler 放在 pipeline 里面 ——
如果你在 grid search 之前就对全部训练数据做 scaling,每个验证 fold 就已经“看过”其他 fold 了(一个小小的 data leakage)。
③ Polynomial Kernel
polynomial kernel 加入 feature interactions,最高到 degree d。degree 2 包含所有两两相乘的项(x₁x₂、x₁²、x₂²……)。degree 3 再加上三次项。
coef0=0)时,只剩下正好是 d 次的项。这时 degree 3 只有三次项 —— 没有 x₁²,也没有 x₂²。from sklearn.svm import SVC
from sklearn.datasets import make_moons
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score
# Moon-shaped data: needs a curved boundary
X, y = make_moons(n_samples=500, noise=0.15, random_state=42)
pipe = Pipeline([
("scaler", StandardScaler()),
("svm", SVC(kernel="poly", degree=3, C=5, coef0=1, gamma="scale")),
])
scores = cross_val_score(pipe, X, y, cv=5, scoring="accuracy")
print(f"CV accuracy (degree=3): {scores.mean():.3f} +/- {scores.std():.3f}")
for d in [1, 2, 3, 4, 5]:
pipe.set_params(svm__degree=d)
s = cross_val_score(pipe, X, y, cv=5)
print(f" degree={d}: {s.mean():.3f}")
Degrees 1 and 2 are too simple for the moon shape (about 85%); degree 3 jumps to 99.4%. Degrees 4 and 5 add nothing more — so prefer the simpler degree 3.
④ Sigmoid Kernel
The sigmoid kernel behaves a little like a one-hidden-layer neural network. It is the least used of the four, and it is not a valid (positive semi-definite) kernel for all parameter values.
Degree 1 और 2 moon के आकार के लिए बहुत simple हैं (लगभग 85%); degree 3 सीधे 99.4% पर पहुँच जाता है। Degree 4 और 5 कुछ नया नहीं जोड़ते — इसलिए ज़्यादा simple degree 3 चुनिए।
④ Sigmoid Kernel
Sigmoid kernel कुछ-कुछ एक hidden layer वाले neural network जैसा बर्ताव करता है। चारों में यह सबसे कम इस्तेमाल होता है, और parameters की हर value के लिए valid (positive semi-definite) kernel नहीं है।
degree 1 和 2 对月牙形状来说太简单了(大约 85%);degree 3 一下跳到 99.4%。degree 4 和 5 没有再提高 —— 所以选更简单的 degree 3。
④ Sigmoid Kernel
sigmoid kernel 的表现有点像只有一个隐藏层的 neural network。它是四种里用得最少的,而且不是对所有参数值都是有效的(positive semi-definite)kernel。
from sklearn.svm import SVC
from sklearn.datasets import make_classification
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score
X, y = make_classification(n_samples=600, n_features=8, random_state=42)
for kernel in ["sigmoid", "rbf"]:
pipe = Pipeline([("scaler", StandardScaler()),
("svm", SVC(kernel=kernel, C=1.0, coef0=0, gamma="scale"))])
scores = cross_val_score(pipe, X, y, cv=5)
print(f"{kernel:8s} CV accuracy: {scores.mean():.3f}")
Here the sigmoid kernel gets 88.5%, a little below RBF (91.3%). That is the usual story.
The sigmoid kernel satisfies Mercer’s condition only for some values of γ and r. Then the optimisation is no longer guaranteed to find the best answer. If sigmoid happens to be your best kernel, also try a real neural network.
All Kernels — Side-by-Side Code
The clearest way to see the difference: train every kernel on the same dataset and compare.
यहाँ sigmoid kernel को 88.5% मिलता है, जो RBF (91.3%) से थोड़ा कम है। आमतौर पर यही होता है।
Sigmoid kernel Mercer की शर्त सिर्फ़ γ और r की कुछ values के लिए पूरी करता है। बाक़ी values पर optimisation के सबसे अच्छा जवाब ढूँढने की कोई गारंटी नहीं रहती। अगर sigmoid ही आपका सबसे अच्छा kernel निकले, तो एक असली neural network भी आज़माइए।
सारे Kernels — आमने-सामने Code
फ़र्क़ देखने का सबसे साफ़ तरीक़ा: हर kernel को एक ही dataset पर train कीजिए और तुलना कीजिए।
这里 sigmoid kernel 得到 88.5%,比 RBF(91.3%)低一点。通常就是这样。
sigmoid kernel 只在 γ 和 r 取某些值时才满足 Mercer 条件。不满足时,优化就不再保证能找到最好的答案。 如果 sigmoid 恰好是你最好的 kernel,也试试一个真正的 neural network。
所有 Kernel —— 并排比较的代码
看清区别最好的办法:在同一个 dataset 上训练每一种 kernel,然后比较。
from sklearn.svm import SVC
from sklearn.datasets import make_circles
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
# Circular data: the hardest case for a linear kernel
X, y = make_circles(n_samples=600, noise=0.1, factor=0.4, random_state=0)
kernels = {
"linear": SVC(kernel="linear", C=1.0),
"rbf": SVC(kernel="rbf", C=10, gamma="scale"),
"poly": SVC(kernel="poly", C=5, degree=2, gamma="scale"),
"poly d=3":SVC(kernel="poly", C=5, degree=3, gamma="scale"),
"sigmoid": SVC(kernel="sigmoid", C=1.0, gamma="scale"),
}
print(f"{'Kernel':<10} {'Mean CV acc':>12} {'Std':>8}")
print("-" * 32)
for name, clf in kernels.items():
pipe = Pipeline([("scaler", StandardScaler()), ("svm", clf)])
scores = cross_val_score(pipe, X, y, cv=5, scoring="accuracy")
print(f"{name:<10} {scores.mean():>12.3f} {scores.std():>8.3f}")
On circles, linear (0.557) and sigmoid (0.575) are barely better than guessing (0.500).
RBF (0.997) and polynomial degree 2 (0.995) solve the problem.
The surprise: polynomial degree 3 gets only 0.632. With the default coef0=0 it has only cubic terms, and a circle needs x² + y².
Kernel settings matter as much as the kernel name. This is also why RBF is the default first choice — it handles linear and curved data well without such traps.
How to Choose the Right Kernel
SVC(kernel='rbf') inside a pipeline with StandardScaler. Run a grid search over C and γ. If the cross-validated score is good enough for your problem and training is fast enough, you may be done.LinearSVC for speed.coef0 too.StandardScaler() in the pipeline before the SVM.| Kernel | Best situation | Key params | Scale data? | Speed |
|---|---|---|---|---|
| Linear | Text, high-dimensional sparse data, features > samples | C | Recommended | Fast |
| RBF | Default choice, unknown structure | C, gamma | Required | Medium |
| Polynomial | Feature interactions | C, degree, coef0, gamma | Required | Medium |
| Sigmoid | Special cases only | C, gamma, coef0 | Required | Medium |
| Custom | Domain-specific similarity (graphs, strings) | Your function | Depends | Often slow |
Complete Worked Example — Iris Dataset
Now everything together in one real pipeline: hold out a test set, scale, search over kernels and their own hyperparameters, then evaluate once on the test set.
Circles पर linear (0.557) और sigmoid (0.575) अंदाज़े (0.500) से बस ज़रा-से बेहतर हैं।
RBF (0.997) और polynomial degree 2 (0.995) समस्या हल कर देते हैं।
हैरानी की बात: polynomial degree 3 को सिर्फ़ 0.632 मिलता है। Default coef0=0 के साथ इसमें सिर्फ़ cubic terms होते हैं, और circle को x² + y² चाहिए।
Kernel की settings उतनी ही मायने रखती हैं जितना kernel का नाम। इसीलिए RBF default पहली पसंद है — यह ऐसे जालों के बिना linear और मुड़े हुए, दोनों तरह के data को अच्छे से संभालता है।
सही Kernel कैसे चुनें
StandardScaler वाली pipeline के अंदर SVC(kernel='rbf') से शुरू कीजिए। C और γ पर grid search चलाइए। अगर cross-validated score आपकी समस्या के लिए काफ़ी अच्छा है और training काफ़ी तेज़ है, तो शायद काम हो गया।LinearSVC इस्तेमाल कीजिए।coef0 को भी tune करना याद रखिए।StandardScaler() रखिए।| Kernel | सबसे अच्छी स्थिति | मुख्य Params | Data scale करें? | Speed |
|---|---|---|---|---|
| Linear | Text, high-dimensional sparse data, features > samples | C | सलाह दी जाती है | तेज़ |
| RBF | Default पसंद, ढाँचा पता न हो | C, gamma | ज़रूरी | मध्यम |
| Polynomial | Feature interactions | C, degree, coef0, gamma | ज़रूरी | मध्यम |
| Sigmoid | सिर्फ़ ख़ास मामलों में | C, gamma, coef0 | ज़रूरी | मध्यम |
| Custom | Domain के हिसाब से similarity (graphs, strings) | आपका function | निर्भर करता है | अक्सर धीमा |
पूरा उदाहरण — Iris Dataset
अब सब कुछ एक साथ, एक असली pipeline में: एक test set अलग रखिए, scale कीजिए, kernels और उनके अपने hyperparameters पर search कीजिए, फिर test set पर एक बार evaluate कीजिए।
在圆环数据上,linear(0.557)和 sigmoid(0.575)只比乱猜(0.500)好一点点。
RBF(0.997)和 polynomial degree 2(0.995)解决了这个问题。
意外的是:polynomial degree 3 只得到 0.632。用默认的 coef0=0 时它只有三次项,而一个圆需要 x² + y²。
kernel 的设置和 kernel 的名字一样重要。这也是为什么 RBF 是默认的首选 —— 它对 linear 和弯曲的数据都处理得很好,没有这样的陷阱。
怎样选对 Kernel
SVC(kernel='rbf') 和 StandardScaler 放进一个 pipeline。在 C 和 γ 上做 grid search。如果 cross-validation 的分数对你的问题来说够好,训练也够快,可能就完成了。LinearSVC。coef0。StandardScaler() 放在 SVM 前面。| Kernel | 最适合的情况 | 关键参数 | 要 scaling 吗? | 速度 |
|---|---|---|---|---|
| Linear | 文本、高 dimension 稀疏数据、feature 比样本多 | C | 推荐 | 快 |
| RBF | 默认选择,结构未知 | C, gamma | 必须 | 中等 |
| Polynomial | feature interactions | C, degree, coef0, gamma | 必须 | 中等 |
| Sigmoid | 只用于特殊情况 | C, gamma, coef0 | 必须 | 中等 |
| 自定义 | 特定领域的相似度(图、字符串) | 你的函数 | 看情况 | 常常很慢 |
完整的实例 —— Iris Dataset
现在把所有东西放进一个真实的 pipeline:留出一个 test set,做 scaling,同时搜索 kernel 和它们各自的 hyperparameter,最后在 test set 上只评估一次。
from sklearn.datasets import load_iris
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report
# 1. Load data
iris = load_iris()
X, y = iris.data, iris.target
# 2. Hold out a true test set (never touched during tuning)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y)
# 3. Pipeline: scaling + SVM
pipe = Pipeline([("scaler", StandardScaler()), ("svm", SVC())])
# 4. Search over kernels AND their own hyperparameters
param_grid = [
{"svm__kernel": ["linear"], "svm__C": [0.1, 1, 10]},
{"svm__kernel": ["rbf"], "svm__C": [0.1, 1, 10, 100], "svm__gamma": ["scale", 0.01, 0.1]},
{"svm__kernel": ["poly"], "svm__C": [1, 10], "svm__degree": [2, 3], "svm__gamma": ["scale"]},
]
grid = GridSearchCV(pipe, param_grid, cv=5, scoring="accuracy", n_jobs=-1)
grid.fit(X_train, y_train)
# 5. Evaluate once on the held-out test set
best = grid.best_estimator_
print(f"Best params : {grid.best_params_}")
print(f"CV accuracy : {grid.best_score_:.3f}")
print(f"Test accuracy: {best.score(X_test, y_test):.3f}\n")
print(classification_report(y_test, best.predict(X_test), target_names=iris.target_names, digits=3))
The winner is the simplest model — a linear kernel with C = 0.1 (CV 97.5%).
On the 30 test flowers it gets 93.3% (two mistakes). With so few test points one flower is worth 3.3%,
so the small gap between CV and test score is normal noise, not a sign of a bad model.
Notice we did not set probability=True: it is only needed for predict_proba, and it makes training much slower.
Visualising Decision Boundaries in Python
A picture is worth a hundred accuracy scores. This function plots the boundary, the margin lines and the support vectors for any 2D dataset and any kernel.
जीतने वाला सबसे simple model है — C = 0.1 वाला linear kernel (CV 97.5%)।
30 test फूलों पर इसे 93.3% मिलता है (दो ग़लतियाँ)। इतने कम test points के साथ एक फूल 3.3% के बराबर है,
इसलिए CV और test score के बीच का छोटा-सा gap सामान्य noise है, ख़राब model का संकेत नहीं।
ध्यान दीजिए, हमने probability=True set नहीं किया: यह सिर्फ़ predict_proba के लिए चाहिए, और training को बहुत धीमा कर देता है।
Python में Decision Boundaries को देखना
एक तस्वीर सौ accuracy scores के बराबर है। यह function किसी भी 2D dataset और किसी भी kernel के लिए boundary, margin lines और support vectors plot करता है।
胜出的是最简单的 model —— C = 0.1 的 linear kernel(CV 97.5%)。
在 30 朵 test 花上它得到 93.3%(两个错误)。test 的点这么少,一朵花就占 3.3%,
所以 CV 和 test 分数之间的小差距只是正常的噪声,并不说明 model 不好。
注意我们没有设置 probability=True:只有 predict_proba 才需要它,而且它会让训练慢很多。
在 Python 中把 Decision Boundary 画出来
一张图胜过一百个 accuracy 分数。这个函数可以为任何 2D dataset 和任何 kernel 画出边界、margin 线和 support vectors。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.datasets import make_circles
from sklearn.preprocessing import StandardScaler
def plot_kernel_boundary(X, y, kernel, C=1.0, gamma="scale", degree=3, ax=None, title=""):
"""Plot the 2D decision boundary of an SVM with the given kernel."""
X_scaled = StandardScaler().fit_transform(X)
model = SVC(kernel=kernel, C=C, gamma=gamma, degree=degree).fit(X_scaled, y)
# A fine grid of points covering the plot
x_min, x_max = X_scaled[:, 0].min() - 0.5, X_scaled[:, 0].max() + 0.5
y_min, y_max = X_scaled[:, 1].min() - 0.5, X_scaled[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02))
Z = model.decision_function(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
if ax is None:
_, ax = plt.subplots(figsize=(6, 5))
ax.contourf(xx, yy, Z > 0, alpha=0.3, cmap="RdBu")
ax.contour(xx, yy, Z, levels=[-1, 0, 1], colors="k", linestyles=["--", "-", "--"]) # margin and boundary
ax.scatter(X_scaled[:, 0], X_scaled[:, 1], c=y, cmap="RdBu", edgecolors="k", s=30)
sv = model.support_vectors_ # circle the support vectors
ax.scatter(sv[:, 0], sv[:, 1], s=150, linewidths=1.5, edgecolors="orange", facecolors="none")
ax.set_title(f"{title} train acc: {model.score(X_scaled, y):.2f} SVs: {len(sv)}")
return ax
X, y = make_circles(n_samples=300, noise=0.1, factor=0.4, random_state=42)
fig, axes = plt.subplots(1, 4, figsize=(20, 4))
for ax, kern in zip(axes, ["linear", "rbf", "poly", "sigmoid"]):
plot_kernel_boundary(X, y, kernel=kern, C=10, ax=ax, title=kern.upper())
plt.tight_layout()
plt.savefig("kernel_comparison.png", dpi=150, bbox_inches="tight")
Orange circles mark the support vectors — the points on or inside the margin that define the boundary. The number of support vectors is a useful signal, but read it in both directions: very many support vectors can mean too small C (a very wide, soft margin), too small γ (a boundary that cannot fit), or too large γ (every point becomes its own little island). Section 12 shows all three in real numbers.
Golden Rules — Kernels
StandardScaler inside a Pipeline to avoid data leakage.GridSearchCV or RandomizedSearchCV, on a log scale. A large C with a large γ overfits badly.LinearSVC, SGDClassifier, a kernel approximation (Nystroem), or gradient boosting.The C Parameter — Controlling the Margin
Teacher B (low C) is relaxed: she allows some mistakes and focuses on the big picture. If she is too relaxed, though, the students never learn enough.
C is that strictness dial. It controls how much the SVM is allowed to misclassify training points in exchange for a wider, safer margin.
large C → narrow margin, fewer errors
Try It — Strict vs Lenient Teacher
Move C from lenient to strict. Watch the boundary, the number of support vectors, and the curve of train vs test accuracy below.
नारंगी गोले support vectors दिखाते हैं — वे points जो margin पर या उसके अंदर हैं और boundary तय करते हैं। Support vectors की संख्या एक काम का संकेत है, पर इसे दोनों तरफ़ से पढ़िए: बहुत सारे support vectors का मतलब हो सकता है बहुत छोटा C (बहुत चौड़ा, नरम margin), बहुत छोटा γ (ऐसी boundary जो fit नहीं हो पाती), या बहुत बड़ा γ (हर point अपना छोटा-सा टापू बन जाता है)। सेक्शन 12 ये तीनों असली संख्याओं में दिखाता है।
सुनहरे नियम — Kernels
StandardScaler को Pipeline के अंदर रखिए।GridSearchCV या RandomizedSearchCV से, log scale पर। बड़ा C और बड़ा γ साथ हों, तो model बुरी तरह overfit करता है।LinearSVC, SGDClassifier, kernel approximation (Nystroem) या gradient boosting पर विचार कीजिए।C Parameter — Margin पर क़ाबू
शिक्षक B (छोटा C) आराम से चलती है: वह कुछ ग़लतियाँ माफ़ कर देती है और बड़ी तस्वीर पर ध्यान देती है। पर अगर वह ज़रूरत से ज़्यादा ढील दे, तो छात्र कभी पूरा नहीं सीख पाते।
C यही सख़्ती का dial है। यह तय करता है कि ज़्यादा चौड़े, सुरक्षित margin के बदले SVM को training points को कितना ग़लत classify करने की छूट है।
बड़ा C → पतला margin, कम ग़लतियाँ
ख़ुद आज़माइए — Strict vs Lenient Teacher
C को नरम से सख़्त की ओर ले जाइए। Boundary, support vectors की संख्या और नीचे train vs test accuracy का curve देखिए।
橙色圆圈标出的是 support vectors —— 落在 margin 上或 margin 里面、决定边界的那些点。 support vectors 的数量是一个有用的信号,但要从两个方向去读: support vectors 非常多,可能说明 C 太小(margin 非常宽、非常软),γ 太小(边界贴合不了数据), 或者 γ 太大(每个点都成了自己的小岛)。 第 12 节用真实的数字展示了这三种情况。
黄金法则 —— Kernel
StandardScaler 放进 Pipeline 里,避免 data leakage。GridSearchCV 或 RandomizedSearchCV,在 log scale 上搜索。C 大再加上 γ 大,会严重 overfitting。LinearSVC、SGDClassifier、kernel approximation(Nystroem),或者 gradient boosting。参数 C —— 控制 Margin
B 老师(C 小)很放松:她允许一些错误,更关注整体。 不过,如果她太放松,学生就永远学不够。
C 就是这个严格程度的旋钮。它控制 SVM 可以把多少训练点分错,来换取一个更宽、更安全的 margin。
C 大 → margin 窄,错误少
动手试试 —— Strict vs Lenient Teacher
把 C 从宽松移到严格。观察边界、support vectors 的数量,以及下面 train 和 test accuracy 的曲线。
| C value | Margin | Training accuracy | Generalisation | Use when |
|---|---|---|---|---|
0.001 – 0.1 | Very wide | Low | May underfit | Very noisy data |
0.5 – 5 | Balanced | Medium | Good | Default starting point — most problems |
10 – 100 | Narrow | High | Watch the gap | Clean data, little overlap |
1000+ | Very thin | Very high | Overfit risk (especially with large γ) | Only if cross-validation agrees |
| C की Value | Margin | Training Accuracy | Generalisation | कब इस्तेमाल करें |
|---|---|---|---|---|
0.001 – 0.1 | बहुत चौड़ा | कम | Underfit कर सकता है | बहुत noisy data |
0.5 – 5 | संतुलित | मध्यम | अच्छा | Default शुरुआत — ज़्यादातर समस्याएँ |
10 – 100 | पतला | ज़्यादा | Gap पर नज़र रखिए | साफ़ data, कम overlap |
1000+ | बहुत पतला | बहुत ज़्यादा | Overfit का ख़तरा (ख़ासकर बड़े γ के साथ) | सिर्फ़ तब, जब cross-validation भी सहमत हो |
| C 值 | Margin | Training accuracy | 泛化 | 什么时候用 |
|---|---|---|---|---|
0.001 – 0.1 | 非常宽 | 低 | 可能 underfitting | 噪声非常多的数据 |
0.5 – 5 | 平衡 | 中等 | 好 | 默认起点 —— 大多数问题 |
10 – 100 | 窄 | 高 | 注意差距 | 干净的数据,重叠很少 |
1000+ | 非常窄 | 非常高 | 有 overfitting 风险(尤其是 γ 大时) | 只在 cross-validation 也同意时 |
from sklearn.svm import SVC
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_validate
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
X, y = make_classification(n_samples=500, n_features=2, n_redundant=0, n_informative=2,
n_clusters_per_class=1, flip_y=0.1, random_state=42)
print(f"{'C':<8} {'Train acc':>10} {'CV acc':>8} {'Gap':>7} {'# SVs':>6}")
print("-" * 43)
for c in [0.001, 0.01, 0.1, 1, 10, 100, 1000]:
pipe = Pipeline([("sc", StandardScaler()), ("svm", SVC(kernel="rbf", C=c, gamma="scale"))])
cv = cross_validate(pipe, X, y, cv=5, return_train_score=True)
pipe.fit(X, y)
tr, te = cv["train_score"].mean(), cv["test_score"].mean()
print(f"{c:<8} {tr:>10.3f} {te:>8.3f} {tr-te:>7.3f} {pipe[-1].n_support_.sum():>6}")
Read the table from top to bottom. At C = 0.001 the model just guesses (50%) and every point is a support vector. CV accuracy climbs fast up to C = 1 and then only slowly. Even at C = 1000 the gap stays below one percentage point here — with γ = 'scale' this 2D boundary stays smooth, so a strict C barely hurts. The lesson: always look at the gap. A gap of several points (as for large γ in the next section) is the red flag.
The Gamma Parameter — Controlling the Reach
γ is used by the RBF, polynomial and sigmoid kernels. In the RBF kernel it sets how far the influence of one training point reaches — like the radius of vision of each support vector.
Low γ is a floodlight: each point lights up a wide area. The boundary becomes a smooth, gentle curve that sees the big picture.
Too narrow (high γ) and the model memorises every quirk of the training data. Too wide (low γ) and it misses the real shape of the classes.
'auto' = 1 / n_features
Try It — Torchlight vs Floodlight
Move γ from floodlight to torchlight. The small chart shows how far one point’s influence reaches; the curve shows train and test accuracy for every γ.
Table को ऊपर से नीचे पढ़िए। C = 0.001 पर model बस अंदाज़ा लगाता है (50%) और हर point support vector है। CV accuracy C = 1 तक तेज़ी से बढ़ती है और फिर धीरे-धीरे। यहाँ C = 1000 पर भी gap एक percentage point से कम रहता है — γ = 'scale' के साथ यह 2D boundary smooth रहती है, इसलिए सख़्त C से लगभग कोई नुक़सान नहीं होता। सबक़: हमेशा gap देखिए। कई points का gap (जैसा अगले सेक्शन में बड़े γ के लिए है) ख़तरे की लाल झंडी है।
Gamma Parameter — पहुँच पर क़ाबू
γ को RBF, polynomial और sigmoid kernels इस्तेमाल करते हैं। RBF kernel में यह तय करता है कि एक training point का असर कितनी दूर तक पहुँचे — जैसे हर support vector की नज़र का दायरा।
छोटा γ एक floodlight है: हर point एक बड़े हिस्से को रोशन करता है। Boundary एक smooth, हल्का curve बन जाती है, जो बड़ी तस्वीर देखती है।
बहुत पतली रोशनी (बड़ा γ) हो, तो model training data की हर अजीब बात रट लेता है। बहुत चौड़ी रोशनी (छोटा γ) हो, तो वह classes का असली आकार चूक जाता है।
'auto' = 1 / n_features
ख़ुद आज़माइए — Torchlight vs Floodlight
γ को floodlight से torchlight की ओर ले जाइए। छोटा chart दिखाता है कि एक point का असर कितनी दूर तक पहुँचता है; curve हर γ के लिए train और test accuracy दिखाता है।
从上往下读这张表。在 C = 0.001 时,model 只是在猜(50%),而且每一个点都是 support vector。 CV accuracy 很快上升到 C = 1,之后只是慢慢上升。在这里,即使到了 C = 1000,差距也保持在一个百分点以下 —— 用 γ = 'scale' 时,这条 2D 边界一直很平滑,所以严格的 C 几乎没有坏处。 结论:一定要看差距。差距达到好几个百分点(就像下一节中 γ 大的时候),才是危险信号。
参数 Gamma —— 控制影响范围
RBF、polynomial 和 sigmoid kernel 都会用到 γ。在 RBF kernel 中,它决定一个训练点的影响能到多远 —— 就像每个 support vector 的视野半径。
γ 小就像泛光灯:每个点照亮一大片区域。边界变成一条平滑、柔和的曲线,看到的是整体。
太窄(γ 大),model 会记住训练数据的每个怪癖。太宽(γ 小),它又会错过 class 真正的形状。
'auto' = 1 / n_features
动手试试 —— Torchlight vs Floodlight
把 γ 从泛光灯移到手电筒。小图显示一个点的影响能到多远;曲线显示每个 γ 对应的 train 和 test accuracy。
| γ (after scaling) | Boundary shape | Risk | When to try |
|---|---|---|---|
0.001 – 0.01 | Very smooth, almost linear | Underfits | When RBF should behave almost like linear |
'scale' (default) | Adapted to the data spread | Good start | Always try this first |
0.1 – 1 | Moderate curves | Often best | Most real datasets |
1 – 10 | Tight around clusters | Watch the gap | Clean, well-separated data |
10 – 100+ | Wraps single points | Overfit risk | Rarely — check CV carefully |
| γ (scaling के बाद) | Boundary का आकार | ख़तरा | कब आज़माएँ |
|---|---|---|---|
0.001 – 0.01 | बहुत smooth, लगभग linear | Underfit करता है | जब RBF को लगभग linear जैसा बर्ताव करना हो |
'scale' (default) | Data के फैलाव के हिसाब से | अच्छी शुरुआत | हमेशा पहले यही आज़माइए |
0.1 – 1 | मध्यम curves | अक्सर सबसे अच्छा | ज़्यादातर असली datasets |
1 – 10 | Clusters के चारों ओर कसी हुई | Gap पर नज़र रखिए | साफ़, अच्छी तरह अलग data |
10 – 100+ | अकेले points के चारों ओर लिपटती है | Overfit का ख़तरा | बहुत कम — CV ध्यान से जाँचिए |
| γ(scaling 之后) | 边界形状 | 风险 | 什么时候试 |
|---|---|---|---|
0.001 – 0.01 | 非常平滑,几乎是直的 | Underfitting | 希望 RBF 的表现几乎和 linear 一样时 |
'scale'(默认) | 根据数据的分散程度调整 | 好的起点 | 永远先试这个 |
0.1 – 1 | 适度弯曲 | 常常最好 | 大多数真实 dataset |
1 – 10 | 紧紧包住一簇簇的点 | 注意差距 | 干净、分得很开的数据 |
10 – 100+ | 包住单个点 | 有 overfitting 风险 | 很少用 —— 仔细检查 CV |
from sklearn.svm import SVC
from sklearn.datasets import make_circles
from sklearn.model_selection import cross_validate, StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
X, y = make_circles(n_samples=400, noise=0.2, factor=0.5, random_state=42) # noisy, overlapping rings
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=0)
print(f"{'gamma':<8} {'Train acc':>10} {'CV acc':>8} {'# SVs':>7}")
print("-" * 36)
for g in [0.001, 0.01, 0.1, 0.5, 1, 5, 50, 500]:
pipe = Pipeline([("sc", StandardScaler()), ("svm", SVC(kernel="rbf", C=10, gamma=g))])
cv = cross_validate(pipe, X, y, cv=skf, return_train_score=True)
pipe.fit(X, y)
n_sv = pipe.named_steps["svm"].support_vectors_.shape[0]
print(f"{g:<8} {cv['train_score'].mean():>10.3f} {cv['test_score'].mean():>8.3f} {n_sv:>7d}")
Look at the last column. At γ = 0.001 all 400 points are support vectors — the boundary is too smooth to fit, so almost every point is inside the margin. The count falls to about 111 at γ = 0.5, where CV accuracy is best (0.887). Then it rises again: at γ = 500 there are 397 support vectors, train accuracy is 100% but CV falls to 0.670 — every point has become its own island. So many support vectors can mean underfitting or overfitting; the train–CV gap tells you which.
C and Gamma — How They Interact
C and γ do not act alone. Together they decide whether the model underfits, generalises well, or memorises the data. Tune them jointly — never one at a time.
| Low γ (smooth) | High γ (spiky) | |
|---|---|---|
| Low C (soft, wide margin) | Underfit — too simple | Can be OK — spiky shape, but mistakes are cheap |
| High C (strict) | Often good — smooth boundary, few mistakes | Overfit — tight, spiky, memorises the training data |
A common mistake is to tune C with γ fixed, then tune γ with C fixed. This misses the interaction: good settings lie along a diagonal — a larger C usually needs a smaller γ. Always search both together in one 2D grid, as in the next section.
Grid Search — Exhaustive Hyperparameter Tuning
Grid search tries every combination of the values you list and uses cross-validation to pick the best one.
Try It — Live Grid Search
Press Run grid search and watch every cell being cross-validated. Then click cells to compare their decision boundaries.
आख़िरी column देखिए। γ = 0.001 पर सारे 400 points support vectors हैं — boundary इतनी smooth है कि fit नहीं हो पाती, इसलिए लगभग हर point margin के अंदर है। γ = 0.5 पर गिनती घटकर लगभग 111 रह जाती है, और यहीं CV accuracy सबसे अच्छी है (0.887)। फिर यह दोबारा बढ़ती है: γ = 500 पर 397 support vectors हैं, train accuracy 100% है, पर CV गिरकर 0.670 हो जाता है — हर point अपना अलग टापू बन गया है। तो बहुत सारे support vectors का मतलब underfitting भी हो सकता है और overfitting भी; कौन-सा है, यह train–CV gap बताता है।
C और Gamma — ये आपस में कैसे असर डालते हैं
C और γ अकेले काम नहीं करते। दोनों मिलकर तय करते हैं कि model underfit करेगा, अच्छी तरह generalise करेगा, या data रट लेगा। इन्हें एक साथ tune कीजिए — कभी एक-एक करके नहीं।
| छोटा γ (smooth) | बड़ा γ (spiky) | |
|---|---|---|
| छोटा C (नरम, चौड़ा margin) | Underfit — बहुत simple | ठीक हो सकता है — spiky आकार, पर ग़लतियाँ सस्ती हैं |
| बड़ा C (सख़्त) | अक्सर अच्छा — smooth boundary, कम ग़लतियाँ | Overfit — कसी हुई, spiky, training data रट लेती है |
एक आम ग़लती है: γ को स्थिर रखकर C tune करना, फिर C को स्थिर रखकर γ tune करना। इससे दोनों का आपसी असर छूट जाता है: अच्छी settings एक diagonal पर होती हैं — बड़े C को आमतौर पर छोटा γ चाहिए। दोनों को हमेशा एक 2D grid में साथ-साथ search कीजिए, जैसा अगले सेक्शन में है।
Grid Search — हर Combination वाली Hyperparameter Tuning
Grid search आपकी दी गई values का हर combination आज़माता है और सबसे अच्छा चुनने के लिए cross-validation इस्तेमाल करता है।
ख़ुद आज़माइए — Live Grid Search
Grid search चलाएँ दबाइए और हर cell को cross-validate होते देखिए। फिर cells पर click करके उनकी decision boundaries की तुलना कीजिए।
看最后一列。在 γ = 0.001 时,全部 400 个点都是 support vectors —— 边界太平滑,贴合不了数据,所以几乎每个点都在 margin 里面。 在 γ = 0.5 时,数量降到大约 111,这时 CV accuracy 最好(0.887)。 然后它又上升:在 γ = 500 时有 397 个 support vectors,train accuracy 是 100%,但 CV 降到 0.670 —— 每个点都成了自己的小岛。 所以 support vectors 多,可能意味着 underfitting,也可能意味着 overfitting;train–CV 差距会告诉你是哪一种。
C 和 Gamma —— 它们怎样相互影响
C 和 γ 不是单独起作用的。它们一起决定 model 是 underfitting、泛化得好,还是把数据死记下来。要把它们一起调 —— 绝不要一次只调一个。
| γ 小(平滑) | γ 大(尖锐) | |
|---|---|---|
| C 小(软的、宽的 margin) | Underfitting —— 太简单 | 可能还行 —— 形状尖锐,但犯错的代价低 |
| C 大(严格) | 常常很好 —— 边界平滑,错误少 | Overfitting —— 又紧又尖,把训练数据死记下来 |
一个常见的错误是:先固定 γ 调 C,再固定 C 调 γ。这样会错过它们之间的相互影响:好的设置分布在一条斜线上 —— C 越大,通常需要的 γ 越小。永远在一个 2D grid 里同时搜索两个参数,就像下一节那样。
Grid Search —— 穷举式的 Hyperparameter 调参
grid search 会试遍你列出的值的每一种组合,并用 cross-validation 选出最好的那个。
动手试试 —— Live Grid Search
按运行 grid search,看每个格子怎样做 cross-validation。然后点击格子,比较它们的 decision boundary。
Complete GridSearchCV Code
GridSearchCV का पूरा Code
完整的 GridSearchCV 代码
from sklearn.svm import SVC
from sklearn.datasets import make_circles
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
import pandas as pd
import numpy as np
X, y = make_circles(n_samples=600, noise=0.2, factor=0.5, random_state=42) # noisy, overlapping rings
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, stratify=y, random_state=42)
pipe = Pipeline([("sc", StandardScaler()), ("svm", SVC(kernel="rbf"))])
param_grid = {
"svm__C": [0.1, 1, 10, 100, 500],
"svm__gamma": [0.001, 0.01, 0.1, 1, 10],
} # 5 x 5 = 25 combinations x 5 folds = 125 fits
grid_search = GridSearchCV(pipe, param_grid, cv=5, scoring="accuracy",
n_jobs=-1, refit=True) # refit the best model on all training data
grid_search.fit(X_train, y_train)
print("Best params :", grid_search.best_params_)
print(f"Best CV acc : {grid_search.best_score_:.4f}")
print(f"Test acc : {grid_search.score(X_test, y_test):.4f}\n")
results = pd.DataFrame(grid_search.cv_results_)
top5 = results.sort_values("rank_test_score")[
["param_svm__C", "param_svm__gamma", "mean_test_score", "std_test_score"]].head(5)
print(top5.round(4).to_string(index=False))
Three combinations tie at 0.8771 — along the same diagonal (C = 1, γ = 0.1), (C = 100, γ = 0.01), (C = 500, γ = 0.1).
When scores tie, prefer the simpler, smoother model (smaller C and γ) or the one with lower std_test_score.
Here GridSearchCV simply took the first one, C = 1 and γ = 0.1, which is also the simplest.
Plotting the Grid Search Results
तीन combinations 0.8771 पर बराबर हैं — एक ही diagonal पर: (C = 1, γ = 0.1), (C = 100, γ = 0.01), (C = 500, γ = 0.1)।
जब scores बराबर हों, तो ज़्यादा simple, smooth model चुनिए (छोटा C और γ), या वह जिसका std_test_score कम हो।
यहाँ GridSearchCV ने बस पहला वाला ले लिया, C = 1 और γ = 0.1, जो सबसे simple भी है।
Grid Search के नतीजों को Plot करना
有三种组合并列 0.8771 —— 它们在同一条斜线上:(C = 1, γ = 0.1)、(C = 100, γ = 0.01)、(C = 500, γ = 0.1)。
分数相同时,选更简单、更平滑的 model(C 和 γ 更小),或者 std_test_score 更低的那个。
这里 GridSearchCV 只是取了第一个,C = 1、γ = 0.1,它也正好是最简单的。
把 Grid Search 的结果画出来
import matplotlib.pyplot as plt
# cv_results_ follows the order of the grid: C changes slowest, gamma fastest
scores = grid_search.cv_results_["mean_test_score"].reshape(
len(param_grid["svm__C"]), len(param_grid["svm__gamma"]))
print(scores.round(2))
fig, ax = plt.subplots(figsize=(7, 5))
im = ax.imshow(scores, cmap="viridis", origin="lower")
ax.set_xticks(range(len(param_grid["svm__gamma"])), labels=param_grid["svm__gamma"])
ax.set_yticks(range(len(param_grid["svm__C"])), labels=param_grid["svm__C"])
ax.set_xlabel("gamma"); ax.set_ylabel("C")
for i in range(scores.shape[0]):
for j in range(scores.shape[1]):
ax.text(j, i, f"{scores[i, j]:.2f}", ha="center", va="center", color="white")
plt.colorbar(im, label="CV accuracy")
plt.tight_layout()
plt.savefig("gridsearch_heatmap.png", dpi=150)
Rows are C (0.1 at the top of the printout, 500 at the bottom), columns are γ (0.001 → 10). You can see the diagonal ridge of good scores, the weak bottom-left corner of the plot (both small), and the drop in the top-right corner (both large).
With 4 values of C, 5 of γ, 2 kernel degrees and 5 folds you already need 200 fits. Every new parameter multiplies the cost. That is why random search is often better value with many parameters.
Random Search — Smarter Hyperparameter Tuning
Random search samples combinations at random from distributions you choose, instead of testing every point of a grid. It sounds less careful, but it is often more efficient.
But suppose only one direction matters — the treasure lies in a narrow stripe. Your 5×5 grid tests only 5 different positions along that important direction; the other 20 flags just repeat them at different, unimportant positions.
Random search scatters 25 flags randomly, so it tests 25 different positions along every direction — including the important one. Bergstra & Bengio (2012) showed that random search usually finds equally good or better settings than grid search for the same budget, because usually only a few hyperparameters really matter.
Try It — Grid vs Random Search
A toy score landscape where only log C matters. Change the budget, draw new random points, and press Repeat 500 times to see how often random search wins.
Rows C हैं (printout में ऊपर 0.1, नीचे 500), columns γ हैं (0.001 → 10)। आप अच्छे scores की diagonal ridge देख सकते हैं, plot का कमज़ोर नीचे-बायाँ कोना (दोनों छोटे), और ऊपर-दाएँ कोने में गिरावट (दोनों बड़े)।
C की 4 values, γ की 5, kernel की 2 degrees और 5 folds के साथ आपको पहले ही 200 fits चाहिए। हर नया parameter cost को गुणा कर देता है। इसीलिए बहुत सारे parameters के साथ random search अक्सर ज़्यादा फ़ायदे का सौदा है।
Random Search — ज़्यादा समझदार Hyperparameter Tuning
Random search grid के हर point को test करने की जगह, आपकी चुनी हुई distributions से combinations random तरीक़े से चुनता है। सुनने में यह कम सावधान लगता है, पर अक्सर यह ज़्यादा efficient होता है।
पर मान लीजिए सिर्फ़ एक दिशा मायने रखती है — ख़ज़ाना एक पतली पट्टी में है। आपका 5×5 grid उस ज़रूरी दिशा में सिर्फ़ 5 अलग जगहें test करता है; बाक़ी 20 झंडे बस उन्हीं को दूसरी, ग़ैर-ज़रूरी जगहों पर दोहराते हैं।
Random search 25 झंडे random तरीक़े से बिखेरता है, इसलिए वह हर दिशा में 25 अलग जगहें test करता है — ज़रूरी दिशा में भी। Bergstra & Bengio (2012) ने दिखाया कि उसी budget में random search आमतौर पर grid search जितनी अच्छी या उससे बेहतर settings ढूँढता है, क्योंकि आमतौर पर सिर्फ़ कुछ hyperparameters ही सच में मायने रखते हैं।
ख़ुद आज़माइए — Grid vs Random Search
एक toy score landscape, जिसमें सिर्फ़ log C मायने रखता है। Budget बदलिए, नए random points निकालिए, और 500 बार दोहराएँ दबाकर देखिए कि random search कितनी बार जीतता है।
行是 C(打印结果中 0.1 在最上面,500 在最下面),列是 γ(0.001 → 10)。你可以看到好分数组成的斜线山脊,图中较弱的左下角(两个都小),以及右上角的下降(两个都大)。
C 取 4 个值,γ 取 5 个值,再加 2 个 kernel degree 和 5 个 fold,就已经需要 200 次训练。每多一个参数,成本就要乘一次。这就是为什么参数多的时候,random search 常常更划算。
Random Search —— 更聪明的 Hyperparameter 调参
random search 从你选的 distribution 中随机抽取组合,而不是试遍 grid 上的每个点。它听起来没那么仔细,但常常更有效率。
但假设只有一个方向重要 —— 宝藏在一条很窄的条带里。你的 5×5 网格在这个重要的方向上只试了 5 个不同的位置; 其他 20 面旗子只是在另一个不重要的方向上把它们重复了一遍。
random search 把 25 面旗子随机撒开,所以它在每个方向上都试了 25 个不同的位置 —— 包括那个重要的方向。 Bergstra & Bengio(2012)证明:在相同的预算下,random search 通常能找到和 grid search 一样好甚至更好的设置,因为通常只有少数几个 hyperparameter 真正重要。
动手试试 —— Grid vs Random Search
一个只有 log C 重要的玩具分数地形。改变预算,重新随机抽取点,然后按重复 500 次,看 random search 有多常获胜。
RandomizedSearchCV with Continuous Distributions
Continuous Distributions के साथ RandomizedSearchCV
用连续 Distribution 的 RandomizedSearchCV
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import loguniform
pipe = Pipeline([("sc", StandardScaler()), ("svm", SVC())])
param_dist = {
"svm__kernel": ["rbf", "poly", "linear"],
"svm__C": loguniform(1e-2, 1e4), # every order of magnitude equally likely
"svm__gamma": loguniform(1e-4, 1e1),
"svm__degree": [2, 3, 4], # only used when kernel='poly'
}
rand_search = RandomizedSearchCV(pipe, param_dist, n_iter=60, cv=5,
scoring="accuracy", n_jobs=-1, random_state=42)
rand_search.fit(X_train, y_train)
best = {k: (round(float(v), 4) if isinstance(v, float) else v) for k, v in rand_search.best_params_.items()}
print("Best params :", best)
print(f"Best CV acc : {rand_search.best_score_:.4f}")
print(f"Test acc : {rand_search.score(X_test, y_test):.4f}")
60 random combinations across three kernels found RBF with C ≈ 108 and γ ≈ 0.007 — another point on the same diagonal ridge as the grid search (CV 0.8812). The degree value is ignored because the kernel is RBF.
Always use loguniform for C and γ. Good values can be anywhere from 0.01 to 10,000.
With uniform(0.01, 10000), about 90% of the samples would be above 1,000. Log-uniform samples every order of magnitude equally often.
Grid Search vs Random Search — Direct Comparison
तीन kernels में 60 random combinations ने C ≈ 108 और γ ≈ 0.007 वाला RBF ढूँढा — यह grid search वाली उसी diagonal ridge पर एक और point है (CV 0.8812)। degree की value को नज़रअंदाज़ कर दिया जाता है, क्योंकि kernel RBF है।
C और γ के लिए हमेशा loguniform इस्तेमाल कीजिए। अच्छी values 0.01 से 10,000 तक कहीं भी हो सकती हैं।
uniform(0.01, 10000) के साथ लगभग 90% samples 1,000 से ऊपर होंगे। Log-uniform हर order of magnitude से बराबर बार samples लेता है।
Grid Search vs Random Search — सीधी तुलना
在三种 kernel 上试了 60 个随机组合,找到了 C ≈ 108、γ ≈ 0.007 的 RBF —— 这是和 grid search 同一条斜线山脊上的另一个点(CV 0.8812)。degree 的值被忽略了,因为 kernel 是 RBF。
C 和 γ 永远用 loguniform。好的值可能在 0.01 到 10,000 之间的任何地方。
如果用 uniform(0.01, 10000),大约 90% 的样本会大于 1,000。log-uniform 对每个数量级抽样的频率都一样。
Grid Search vs Random Search —— 直接比较
import time
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
pipe = Pipeline([("sc", StandardScaler()), ("svm", SVC(kernel="rbf"))])
C_range = np.logspace(-2, 4, 7) # 7 values
gamma_range = np.logspace(-4, 1, 6) # 6 values -> 42 combinations
t0 = time.perf_counter()
gs = GridSearchCV(pipe, {"svm__C": C_range, "svm__gamma": gamma_range}, cv=5, n_jobs=-1)
gs.fit(X_train, y_train)
t_grid = time.perf_counter() - t0
t0 = time.perf_counter()
rs = RandomizedSearchCV(pipe, {"svm__C": loguniform(1e-2, 1e4), "svm__gamma": loguniform(1e-4, 10)},
n_iter=42, cv=5, n_jobs=-1, random_state=42) # same budget: 42 combinations
rs.fit(X_train, y_train)
t_rand = time.perf_counter() - t0
print(f"Grid -> CV: {gs.best_score_:.4f} test: {gs.score(X_test, y_test):.4f} time: {t_grid:.1f}s")
print(f"Random -> CV: {rs.best_score_:.4f} test: {rs.score(X_test, y_test):.4f} time: {t_rand:.1f}s")
With only two parameters and the same budget (42 combinations), both methods reach the same CV score (0.8771) in about the same time. The different test scores (0.933 vs 0.917) are just 2 of 120 test points — noise. Random search pays off when there are more parameters and only a few of them matter.
| Grid Search | Random Search | |
|---|---|---|
| Coverage | Every combination of the listed values | Random samples from distributions |
| Best for | 1–3 parameters, small ranges, fast models | 3+ parameters, wide ranges, continuous values |
| Compute cost | Multiplies with every new parameter | Fixed: n_iter × n_folds |
| Reproducibility | Fully deterministic | Set random_state |
| Finds the exact grid optimum | Yes (within the grid) | No — but it can find good values between grid points |
| Recommended for SVM | Quick search over C and γ | Search over kernel + C + γ + degree |
सिर्फ़ दो parameters और एक जैसे budget (42 combinations) के साथ, दोनों तरीक़े लगभग एक जैसे समय में एक ही CV score (0.8771) तक पहुँचते हैं। अलग-अलग test scores (0.933 vs 0.917) बस 120 में से 2 test points का फ़र्क़ हैं — noise। Random search का फ़ायदा तब मिलता है, जब parameters ज़्यादा हों और उनमें से कुछ ही मायने रखते हों।
| Grid Search | Random Search | |
|---|---|---|
| Coverage | दी गई values का हर combination | Distributions से random samples |
| किसके लिए सबसे अच्छा | 1–3 parameters, छोटी ranges, तेज़ models | 3+ parameters, चौड़ी ranges, continuous values |
| Compute cost | हर नए parameter के साथ गुणा होती है | तय: n_iter × n_folds |
| दोबारा वही नतीजा | पूरी तरह deterministic | random_state set कीजिए |
| Grid का ठीक optimum ढूँढता है | हाँ (grid के अंदर) | नहीं — पर grid points के बीच की अच्छी values ढूँढ सकता है |
| SVM के लिए सलाह | C और γ पर जल्दी search | kernel + C + γ + degree पर search |
只有两个参数、预算相同(42 种组合)时,两种方法达到相同的 CV 分数(0.8771),用时也差不多。 test 分数不同(0.933 vs 0.917),只是 120 个 test 点中差了 2 个 —— 是噪声。 当参数更多、而其中只有少数几个重要时,random search 才显出优势。
| Grid Search | Random Search | |
|---|---|---|
| 覆盖范围 | 列出的值的每一种组合 | 从 distribution 中随机抽样 |
| 最适合 | 1–3 个参数、范围小、训练快的 model | 3 个以上参数、范围宽、连续的值 |
| 计算成本 | 每多一个参数就乘一次 | 固定:n_iter × n_folds |
| 可重复性 | 完全确定 | 要设置 random_state |
| 能找到 grid 上确切的最优点 | 能(在 grid 范围内) | 不能 —— 但它能找到 grid 点之间的好值 |
| SVM 推荐用法 | 快速搜索 C 和 γ | 搜索 kernel + C + γ + degree |
# Stage 1: coarse random search over a wide range
coarse = RandomizedSearchCV(
pipe,
{"svm__C": loguniform(1e-3, 1e5), "svm__gamma": loguniform(1e-5, 1e2)},
n_iter=40, cv=3, n_jobs=-1, random_state=42)
coarse.fit(X_train, y_train)
best_C, best_gamma = coarse.best_params_["svm__C"], coarse.best_params_["svm__gamma"]
print(f"Stage 1 best: C={best_C:.2f} gamma={best_gamma:.4f} CV={coarse.best_score_:.4f}")
# Stage 2: fine grid around the Stage 1 result (x0.1 ... x10)
fine_C = np.logspace(np.log10(best_C / 10), np.log10(best_C * 10), 5)
fine_gamma = np.logspace(np.log10(best_gamma / 10), np.log10(best_gamma * 10), 5)
fine = GridSearchCV(pipe, {"svm__C": fine_C, "svm__gamma": fine_gamma},
cv=5, n_jobs=-1)
fine.fit(X_train, y_train)
p = fine.best_params_
print(f"Stage 2 best: C={p['svm__C']:.2f} gamma={p['svm__gamma']:.4f} CV={fine.best_score_:.4f}")
print(f"Final test accuracy: {fine.score(X_test, y_test):.4f}")
Stage 1 used 40 × 3 = 120 fits to find the right region (C ≈ 700, γ ≈ 0.16). Stage 2 used 25 × 5 = 125 fits and moved along the ridge to C ≈ 72, γ ≈ 0.016 (CV 0.8812). A single fine grid over the whole range (C from 0.001 to 100,000 and γ from 0.00001 to 100) at the same resolution would need thousands of fits.
Hyperparameter Tuning — Golden Rules
StandardScaler inside a Pipeline so it is refitted inside every CV fold (no data leakage).np.logspace(-3, 4, 8), not range(1, 100). These parameters work across many orders of magnitude, so linear spacing wastes most of the budget.Stage 1 ने सही इलाक़ा ढूँढने के लिए 40 × 3 = 120 fits इस्तेमाल किए (C ≈ 700, γ ≈ 0.16)। Stage 2 ने 25 × 5 = 125 fits इस्तेमाल किए और ridge के साथ खिसककर C ≈ 72, γ ≈ 0.016 पर पहुँचा (CV 0.8812)। पूरी range (C 0.001 से 100,000 तक और γ 0.00001 से 100 तक) पर उसी बारीकी वाले एक grid को हज़ारों fits चाहिए होते।
Hyperparameter Tuning — सुनहरे नियम
StandardScaler को Pipeline के अंदर रखिए, ताकि वह हर CV fold के अंदर दोबारा fit हो (कोई data leakage नहीं)।np.logspace(-3, 4, 8) इस्तेमाल कीजिए, range(1, 100) नहीं। ये parameters कई orders of magnitude में काम करते हैं, इसलिए बराबर दूरी वाली values ज़्यादातर budget बर्बाद कर देती हैं।第 1 阶段用了 40 × 3 = 120 次训练,找到了正确的区域(C ≈ 700,γ ≈ 0.16)。第 2 阶段用了 25 × 5 = 125 次训练,沿着山脊移动到 C ≈ 72,γ ≈ 0.016(CV 0.8812)。 如果用同样的精细程度,在整个范围(C 从 0.001 到 100,000,γ 从 0.00001 到 100)上做一个精细的 grid,会需要几千次训练。
Hyperparameter 调参 —— 黄金法则
StandardScaler 放进 Pipeline,这样它会在每个 CV fold 里重新 fit(没有 data leakage)。np.logspace(-3, 4, 8),不要用 range(1, 100)。这些参数跨越很多个数量级,所以等间距的取值会浪费大部分预算。