Look for the interactive boxes: Margin Explorer (Section 01), Soft Margin and C (05), The Kernel Trick (06), Kernel Playground (07), Scaling Matters (08) and SVR: the Epsilon Tube (09). Every SVM in them is trained live in your browser.
The Story That Explains SVM
He does not draw just any line. He says: “I want the line that keeps the nearest village on each side as far from the border as possible — a wide, safe no-man’s-land on both sides.” He looks only at the villages nearest to the border, because they decide where the line must go. He calls them his support villages. Every other village has no effect on the border.
The wider the no-man’s-land, the more confident he is that future travellers will be put in the right kingdom, even if their position is a little uncertain. This widest no-man’s-land is the margin. The border line is the hyperplane. The support villages are the support vectors.
That is a Support Vector Machine: find the boundary with the widest gap between the two classes.
SVM finds the hyperplane with the largest margin — the largest distance between the decision boundary and the nearest points of each class. A wide margin usually means better results on new, unseen data.
Try It — Margin Explorer
Drag the points and watch the street (the margin) change. Tick draw my own line and turn it: you will never beat the SVM street. Then press Keep only support vectors.
इन interactive boxes को देखिए: Margin Explorer (सेक्शन 01), Soft Margin and C (05), The Kernel Trick (06), Kernel Playground (07), Scaling Matters (08) और SVR: the Epsilon Tube (09)। इनका हर SVM आपके browser में live train होता है।
वह कहानी जो SVM को समझाती है
वह कोई भी line नहीं खींचता। वह कहता है: “मुझे वह line चाहिए जो हर तरफ़ के सबसे पास वाले गाँव को सीमा से जितना हो सके उतना दूर रखे — दोनों तरफ़ एक चौड़ी, सुरक्षित no-man’s-land।” वह सिर्फ़ सीमा के सबसे पास वाले गाँवों को देखता है, क्योंकि वही तय करते हैं कि line कहाँ जाएगी। वह उन्हें अपने support villages कहता है। बाक़ी किसी गाँव का सीमा पर कोई असर नहीं होता।
No-man’s-land जितनी चौड़ी होगी, रक्षक उतना ही पक्का होगा कि आगे आने वाले यात्री सही राज्य में रखे जाएँगे, चाहे उनकी जगह थोड़ी अनिश्चित हो। यही सबसे चौड़ी no-man’s-land है margin। सीमा की line है hyperplane। Support villages हैं support vectors।
यही है Support Vector Machine: दो classes के बीच सबसे चौड़े gap वाली boundary ढूँढो।
SVM सबसे बड़े margin वाला hyperplane ढूँढता है — यानी decision boundary और हर class के सबसे पास वाले points के बीच सबसे बड़ी दूरी। चौड़े margin का मतलब आमतौर पर नए, अनदेखे data पर बेहतर नतीजे होते हैं।
ख़ुद आज़माइए — Margin Explorer
Points को खींचिए और देखिए कि सड़क (margin) कैसे बदलती है। अपनी line ख़ुद बनाएँ पर tick कीजिए और उसे घुमाइए: आप SVM की सड़क को कभी नहीं हरा पाएँगे। फिर सिर्फ़ support vectors रखें दबाइए।
请留意这些可以互动的方框:Margin Explorer(第 01 节)、Soft Margin and C(05)、The Kernel Trick(06)、Kernel Playground(07)、Scaling Matters(08)和 SVR: the Epsilon Tube(09)。里面的每一个 SVM 都是在你的浏览器里实时训练的。
一个能解释 SVM 的故事
他不会随便画一条线。他说:“我要的那条线,要让两边离边界最近的村庄都离边界尽可能远 —— 两边都留出一片又宽又安全的无人区。”他只看离边界最近的那些村庄,因为是它们决定了线必须画在哪里。 他把它们叫作自己的支撑村庄。其他村庄对边界完全没有影响。
无人区越宽,他就越有信心:将来的旅人即使位置有一点不确定,也会被分到正确的王国。 这片最宽的无人区就是 margin。 边界线就是 hyperplane。 支撑村庄就是 support vectors。
这就是 Support Vector Machine:找到两个 class 之间空隙最宽的那条边界。
SVM 找的是margin 最大的 hyperplane —— 也就是 decision boundary 和每个 class 最近的点之间距离最大。 margin 宽,通常意味着在新的、没见过的数据上结果更好。
动手试试 —— Margin Explorer
拖动这些点,看“街道”(margin)怎样变化。勾选画我自己的线并转动它:你永远赢不了 SVM 的街道。然后按只保留 support vectors。
The Hyperplane — What SVM Is Drawing
In 2D a decision boundary is a line. In 3D it is a plane. In more dimensions it is called a hyperplane — the same idea, just harder to picture. The SVM maths is the same in any number of dimensions.
| Dimensions | Number of Features | Decision Boundary | Example |
|---|---|---|---|
| 2D | 2 features | A straight line | Height vs weight → classify sport |
| 3D | 3 features | A flat plane | Height, weight, age → classify disease |
| nD | n features | A hyperplane | 10,000 word features → classify spam |
Support Vectors — The Only Points That Matter
This is the defining property of SVM: the boundary depends only on the points closest to it (and, with a soft margin, on the points inside the margin). Points far from the boundary have no effect. That is why SVM is not disturbed by outliers that are far away on the correct side, and why a trained SVM only needs to store its support vectors to make predictions.
You can test this yourself in the Margin Explorer in Section 01: press Keep only support vectors. The other points disappear, the SVM is trained again, and the boundary stays exactly where it was.
After fitting, use clf.support_vectors_ for the support vectors, clf.support_ for their row numbers,
and clf.n_support_ for the count per class.
If almost every training point is a support vector, the margin is very wide (small C), the data overlaps a lot, or the model is too simple.
Few support vectors usually means clean, well-separated data.
The SVM Objective — What Is Being Optimised
Training an SVM is an optimisation problem. It looks for the weight vector w and bias b that give the widest margin while classifying all training points correctly.
The hard margin needs every point on the correct side with no exceptions. If the classes overlap, or just one point is mislabelled, there is no solution at all. Real data is almost never perfectly separable. The answer is the soft margin.
Hard Margin vs Soft Margin — The C Parameter
The soft-margin SVM adds slack variables ξᵢ. They let some points break the margin rule, but each violation has a cost. The hyperparameter C sets that cost.
| C Value | Margin Width | Violations Allowed | Bias–Variance | Risk |
|---|---|---|---|---|
| Very small (0.001) | Very wide | Many — very tolerant | High bias (underfitting) | Too simple, misclassifies many |
| Small (0.1) | Wide | Some violations OK | Leans towards underfitting | Smoother, more general |
| Medium (1.0) | Balanced | Moderate | Balanced ✅ | Good default starting point |
| Large (100) | Narrow | Rarely allowed | High variance (overfitting) | Can memorise training noise |
| ∞ (Hard Margin) | As narrow as needed | Zero tolerance | Extreme variance | No solution on non-separable data |
C is how much you care about mistakes on the training data. High C = “I hate mistakes — fit the training data tightly.” Low C = “A few mistakes are fine — give me a wide, simple boundary.” Always tune C with cross-validation. Start at 1.0 and search on a log scale: 0.001 → 0.01 → 0.1 → 1 → 10 → 100.
Try It — Soft Margin and C
The two classes overlap, so a hard margin is impossible. Slide C from small to large and watch the street get narrower, the number of support vectors fall, and the test accuracy change.
Hyperplane — SVM क्या बना रहा है
2D में decision boundary एक line होती है। 3D में यह एक plane होती है। और ज़्यादा dimensions में इसे hyperplane कहते हैं — वही विचार, बस कल्पना करना मुश्किल। SVM का गणित dimensions की किसी भी संख्या में एक जैसा है।
| Dimensions | Features की संख्या | Decision Boundary | उदाहरण |
|---|---|---|---|
| 2D | 2 features | एक सीधी line | लंबाई vs वज़न → खेल classify करें |
| 3D | 3 features | एक सपाट plane | लंबाई, वज़न, उम्र → बीमारी classify करें |
| nD | n features | एक hyperplane | 10,000 word features → spam classify करें |
Support Vectors — सिर्फ़ यही Points मायने रखते हैं
यही SVM की पहचान है: boundary सिर्फ़ अपने सबसे पास वाले points पर निर्भर करती है (और soft margin में, margin के अंदर वाले points पर भी)। Boundary से दूर वाले points का कोई असर नहीं होता। इसीलिए सही तरफ़ दूर पड़े outliers से SVM परेशान नहीं होता, और इसीलिए एक trained SVM को predictions के लिए सिर्फ़ अपने support vectors रखने होते हैं।
आप इसे सेक्शन 01 के Margin Explorer में ख़ुद test कर सकते हैं: सिर्फ़ support vectors रखें दबाइए। बाक़ी points ग़ायब हो जाते हैं, SVM फिर से train होता है, और boundary ठीक वहीं रहती है जहाँ थी।
Fit करने के बाद support vectors के लिए clf.support_vectors_, उनके row numbers के लिए clf.support_,
और हर class की गिनती के लिए clf.n_support_ इस्तेमाल कीजिए।
अगर लगभग हर training point support vector है, तो margin बहुत चौड़ा है (छोटा C), data बहुत ज़्यादा overlap करता है, या model बहुत simple है।
कम support vectors का मतलब आमतौर पर साफ़, अच्छी तरह अलग data होता है।
SVM का Objective — किसे Optimise किया जा रहा है
SVM को train करना एक optimisation problem है। यह ऐसा weight vector w और bias b ढूँढता है जो सबसे चौड़ा margin दे और साथ ही सारे training points को सही classify करे।
Hard margin को हर point बिना किसी छूट के सही तरफ़ चाहिए। अगर classes overlap करती हैं, या सिर्फ़ एक point का label ग़लत है, तो कोई solution ही नहीं है। असली data लगभग कभी पूरी तरह अलग नहीं होता। इसका जवाब है soft margin।
Hard Margin vs Soft Margin — C Parameter
Soft-margin SVM slack variables ξᵢ जोड़ता है। ये कुछ points को margin का नियम तोड़ने देते हैं, पर हर violation की एक cost होती है। Hyperparameter C यह cost तय करता है।
| C की Value | Margin की चौड़ाई | कितने Violations की छूट | Bias–Variance | ख़तरा |
|---|---|---|---|---|
| बहुत छोटा (0.001) | बहुत चौड़ा | बहुत — बहुत सहनशील | High bias (underfitting) | बहुत simple, बहुतों को ग़लत classify करता है |
| छोटा (0.1) | चौड़ा | कुछ violations ठीक हैं | underfitting की ओर झुका | ज़्यादा smooth, ज़्यादा general |
| मध्यम (1.0) | संतुलित | थोड़े-बहुत | संतुलित ✅ | शुरुआत के लिए अच्छा default |
| बड़ा (100) | पतला | शायद ही कभी छूट | High variance (overfitting) | Training noise को रट सकता है |
| ∞ (Hard Margin) | जितना ज़रूरी हो उतना पतला | ज़रा भी छूट नहीं | बहुत ज़्यादा variance | जो data अलग नहीं हो सकता, उस पर कोई solution नहीं |
C बताता है कि आपको training data पर ग़लतियों की कितनी परवाह है। High C = “मुझे ग़लतियों से नफ़रत है — training data पर कसकर fit करो।” Low C = “थोड़ी ग़लतियाँ चलेंगी — मुझे चौड़ी, simple boundary दो।” C को हमेशा cross-validation से tune कीजिए। 1.0 से शुरू कीजिए और log scale पर खोजिए: 0.001 → 0.01 → 0.1 → 1 → 10 → 100।
ख़ुद आज़माइए — Soft Margin and C
दोनों classes overlap करती हैं, इसलिए hard margin मुमकिन नहीं है। C को छोटे से बड़े की ओर खिसकाइए और देखिए कि सड़क पतली होती है, support vectors की संख्या घटती है, और test accuracy बदलती है।
Hyperplane —— SVM 画的是什么
在 2D 中,decision boundary 是一条直线。在 3D 中,它是一个平面。 在更多的 dimension 中,它叫作 hyperplane —— 思想一样,只是更难想象。 不管有多少个 dimension,SVM 的数学都是一样的。
| Dimension | Feature 数量 | Decision Boundary | 例子 |
|---|---|---|---|
| 2D | 2 个 feature | 一条直线 | 身高 vs 体重 → 判断运动项目 |
| 3D | 3 个 feature | 一个平的平面 | 身高、体重、年龄 → 判断疾病 |
| nD | n 个 feature | 一个 hyperplane | 10,000 个词 feature → 判断 spam |
Support Vectors —— 唯一重要的点
这是 SVM 最关键的性质:边界只取决于离它最近的点(如果用 soft margin,还取决于 margin 里面的点)。 离边界远的点没有任何影响。所以,在正确一边、离得很远的 outlier 不会干扰 SVM; 训练好的 SVM 也只需要保存它的 support vectors 就能做预测。
你可以在第 01 节的 Margin Explorer 里自己验证:按只保留 support vectors。其他点会消失,SVM 重新训练,而边界一点都不动。
fit 之后,用 clf.support_vectors_ 查看 support vectors,用 clf.support_ 查看它们的行号,
用 clf.n_support_ 查看每个 class 的数量。
如果几乎每个训练点都是 support vector,说明 margin 很宽(C 很小)、数据重叠很多,或者 model 太简单。
support vectors 少,通常说明数据干净、分得很开。
SVM 的目标 —— 到底在优化什么
训练 SVM 是一个优化问题。 它要找到 weight vector w 和 bias b,让 margin 最宽,同时把所有训练点都分对。
hard margin 要求每个点都在正确的一边,没有任何例外。 如果两个 class 有重叠,或者哪怕只有一个点标错了,就根本没有解。 真实数据几乎从来不能被完美分开。解决办法就是 soft margin。
Hard Margin vs Soft Margin —— 参数 C
soft-margin SVM 加入了 slack 变量 ξᵢ。它们允许一些点违反 margin 规则,但每次违反都有代价。 hyperparameter C 决定这个代价有多大。
| C 的值 | Margin 宽度 | 允许的违反 | Bias–Variance | 风险 |
|---|---|---|---|---|
| 很小(0.001) | 非常宽 | 很多 —— 非常宽容 | 高 bias(underfitting) | 太简单,分错很多 |
| 小(0.1) | 宽 | 可以有一些违反 | 偏向 underfitting | 更平滑,更通用 |
| 中等(1.0) | 平衡 | 适中 | 平衡 ✅ | 很好的默认起点 |
| 大(100) | 窄 | 很少允许 | 高 variance(overfitting) | 可能把 training data 里的噪声也记住 |
| ∞(Hard Margin) | 需要多窄就多窄 | 零容忍 | 极高的 variance | 数据不可分时没有解 |
C 表示你有多在乎 training data 上的错误。 C 大 =“我讨厌错误 —— 把 training data 拟合得紧紧的。” C 小 =“错几个没关系 —— 给我一条又宽又简单的边界。” 一定要用 cross-validation 来调 C。从 1.0 开始,在 log 刻度上搜索:0.001 → 0.01 → 0.1 → 1 → 10 → 100。
动手试试 —— Soft Margin and C
两个 class 有重叠,所以不可能用 hard margin。把 C 从小滑到大,看街道变窄、support vectors 的数量减少,以及 test accuracy 的变化。
The Kernel Trick — Handling Non-Linear Data
The kernel trick does exactly this. It maps the data into a higher-dimensional space where a flat hyperplane can separate it. The clever part: the SVM never computes the new coordinates. It only needs dot products between points, and a kernel function K(xᵢ, xⱼ) gives those directly. Fast, exact and elegant.
Try It — The Kernel Trick
Press Lift into 3D. Each point gets a height z = x² + y². Watch a flat plane separate the classes, and see what that plane looks like back in 2D.
Kernel Trick — Non-Linear Data को संभालना
Kernel trick ठीक यही करता है। यह data को एक ज़्यादा dimensions वाले space में ले जाता है, जहाँ एक सपाट hyperplane उसे अलग कर सके। चालाकी यह है: SVM नए coordinates कभी calculate नहीं करता। उसे सिर्फ़ points के बीच dot products चाहिए, और एक kernel function K(xᵢ, xⱼ) वे सीधे दे देता है। तेज़, सटीक और सुंदर।
ख़ुद आज़माइए — The Kernel Trick
3D में उठाएँ दबाइए। हर point को एक ऊँचाई z = x² + y² मिलती है। देखिए कि एक सपाट plane classes को कैसे अलग करता है, और वह plane वापस 2D में कैसा दिखता है।
Kernel Trick —— 处理非线性数据
kernel trick 做的正是这件事。它把数据映射到一个 dimension 更高的空间,在那里一个平的 hyperplane 就能把数据分开。 巧妙的地方在于:SVM 从来不计算新的坐标。它只需要点与点之间的 dot product, 而 kernel 函数 K(xᵢ, xⱼ) 能直接给出这些值。快速、精确又优雅。
动手试试 —— The Kernel Trick
按抬升到 3D。每个点会得到一个高度 z = x² + y²。看一个平的平面怎样把两个 class 分开,再看这个平面回到 2D 时是什么样子。
The Four Kernels — Choosing the Right One
| Kernel | Key Parameters | Effect of High Value | Effect of Low Value | Best For |
|---|---|---|---|---|
| Linear | C only | High C → tighter fit to the training data | Low C → wider margin, more regularised | Text, sparse high-dimensional data |
| RBF | C and γ (gamma) | High γ → wiggly boundary, overfits | Low γ → smooth boundary, can underfit | General purpose, most datasets |
| Polynomial | C, degree d, γ, r | High d → very complex boundary | d = 1 → essentially linear | Problems with feature interactions |
| Sigmoid | C, γ, r | Unstable, unpredictable behaviour | Behaves close to linear | Rarely used — prefer RBF or linear |
In the RBF kernel, γ controls how far each training point’s influence reaches.
High γ → each point only affects its close neighbours → a jagged boundary around single points → overfitting.
Low γ → each point affects a large area → a very smooth boundary → underfitting.
In scikit-learn, gamma='scale' (the default) sets γ = 1 / (n_features × X.var()) — it adapts to the spread of your data.
It is usually a better start than gamma='auto' (γ = 1 / n_features).
Try It — Kernel Playground
Pick a dataset and a kernel. Move C and γ and watch the boundary, the support vectors, and the gap between train and test accuracy. Click on the chart to add your own points.
चार Kernels — सही Kernel कैसे चुनें
| Kernel | मुख्य Parameters | बड़ी Value का असर | छोटी Value का असर | किसके लिए सबसे अच्छा |
|---|---|---|---|---|
| Linear | सिर्फ़ C | High C → training data पर ज़्यादा कसा fit | Low C → चौड़ा margin, ज़्यादा regularised | Text, sparse high-dimensional data |
| RBF | C और γ (gamma) | High γ → टेढ़ी-मेढ़ी boundary, overfit करता है | Low γ → smooth boundary, underfit कर सकता है | आम इस्तेमाल, ज़्यादातर datasets |
| Polynomial | C, degree d, γ, r | High d → बहुत जटिल boundary | d = 1 → लगभग linear | Feature interactions वाली problems |
| Sigmoid | C, γ, r | Unstable, अनिश्चित व्यवहार | लगभग linear जैसा व्यवहार | शायद ही इस्तेमाल होता है — RBF या linear चुनिए |
RBF kernel में γ तय करता है कि हर training point का असर कितनी दूर तक पहुँचता है।
High γ → हर point सिर्फ़ अपने पास के पड़ोसियों पर असर डालता है → अकेले points के चारों ओर दाँतेदार boundary → overfitting।
Low γ → हर point एक बड़े इलाक़े पर असर डालता है → बहुत smooth boundary → underfitting।
scikit-learn में gamma='scale' (default) γ = 1 / (n_features × X.var()) रखता है — यह आपके data के फैलाव के हिसाब से ढल जाता है।
शुरुआत के लिए यह आमतौर पर gamma='auto' (γ = 1 / n_features) से बेहतर है।
ख़ुद आज़माइए — Kernel Playground
एक dataset और एक kernel चुनिए। C और γ को खिसकाइए और boundary, support vectors, और train व test accuracy के बीच के gap को देखिए। अपने points जोड़ने के लिए chart पर click कीजिए।
四种 Kernel —— 怎样选对
| Kernel | 主要参数 | 值大时的效果 | 值小时的效果 | 最适合 |
|---|---|---|---|---|
| Linear | 只有 C | C 大 → 更紧地拟合 training data | C 小 → margin 更宽,regularisation 更强 | 文本、稀疏的高 dimension 数据 |
| RBF | C 和 γ(gamma) | γ 大 → 边界弯弯曲曲,overfitting | γ 小 → 边界平滑,可能 underfitting | 通用,适合大多数 dataset |
| Polynomial | C、degree d、γ、r | d 大 → 边界非常复杂 | d = 1 → 基本上就是 linear | 有 feature 相互作用的问题 |
| Sigmoid | C、γ、r | 不稳定,行为难以预料 | 表现接近 linear | 很少使用 —— 优先用 RBF 或 linear |
在 RBF kernel 中,γ 控制每个训练点的影响能延伸多远。
γ 大 → 每个点只影响它附近的邻居 → 边界围着单个点弯来弯去,参差不齐 → overfitting。
γ 小 → 每个点影响很大一片区域 → 边界非常平滑 → underfitting。
在 scikit-learn 中,gamma='scale'(默认值)设定 γ = 1 / (n_features × X.var()) —— 它会根据数据的分散程度自动调整。
它通常比 gamma='auto'(γ = 1 / n_features)更适合作为起点。
动手试试 —— Kernel Playground
选一个 dataset 和一个 kernel。移动 C 和 γ,观察边界、support vectors,以及 train 和 test accuracy 之间的差距。点击图表可以加入你自己的点。
Python Implementation
SVC on the Iris Dataset — All Four Kernels
Python Implementation
Iris Dataset पर SVC — चारों Kernels
Python 实现
在 Iris Dataset 上用 SVC —— 全部四种 Kernel
from sklearn.svm import SVC
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y)
# Always scale features before an SVM: it works with distances
for kernel in ["linear", "rbf", "poly", "sigmoid"]:
pipe = Pipeline([
("scaler", StandardScaler()),
("svc", SVC(kernel=kernel, C=1.0, gamma="scale")), # gamma = 1 / (n_features * X.var())
])
pipe.fit(X_train, y_train)
acc = pipe.score(X_test, y_test)
nsv = pipe["svc"].n_support_.sum() # total number of support vectors
print(f"Kernel: {kernel:8s} | Test accuracy: {acc:.4f} | Support vectors: {nsv}")
On this small test set (30 flowers) the linear kernel gets every flower right, and RBF misses one. With only 30 test points, one flower is 3.3% — so do not choose a kernel from one split. Use cross-validation, as in the grid search below.
Inspecting the Fitted Model
इस छोटे test set (30 फूल) पर linear kernel हर फूल को सही पहचानता है, और RBF एक से चूक जाता है। सिर्फ़ 30 test points में एक फूल 3.3% है — इसलिए एक split देखकर kernel मत चुनिए। Cross-validation इस्तेमाल कीजिए, जैसे नीचे के grid search में।
Fit किए गए Model को देखना
在这个很小的 test set(30 朵花)上,linear kernel 把每一朵花都分对了,RBF 错了一朵。 只有 30 个 test 点时,一朵花就是 3.3% —— 所以不要只凭一次划分来选 kernel。要用 cross-validation,就像下面的 grid search 那样。
查看训练好的 Model
pipe = Pipeline([
("scaler", StandardScaler()),
("svc", SVC(kernel="rbf", C=1.0, gamma="scale", probability=True, random_state=42)),
])
pipe.fit(X_train, y_train)
svc = pipe["svc"]
print("Support vectors per class:", svc.n_support_)
print("Total support vectors: ", svc.n_support_.sum(), "of", len(X_train), "training points")
print("Support vector shape: ", svc.support_vectors_.shape)
# predict_proba needs probability=True when the model is created
y_prob = pipe.predict_proba(X_test)
y_pred = pipe.predict(X_test)
print("\nSample predictions:")
for i in range(4):
print(f" Predicted: {iris.target_names[y_pred[i]]:12s} ({y_prob[i].max()*100:.1f}% probability)")
47 of the 120 training flowers are support vectors — mostly versicolor and virginica, the two species that overlap.
Setosa is easy to separate, so it needs only 10.
Note: predict_proba uses an extra calibration step (Platt scaling with internal cross-validation),
so its most likely class can occasionally disagree with predict.
Hyperparameter Tuning — GridSearchCV
120 training फूलों में से 47 support vectors हैं — ज़्यादातर versicolor और virginica, वे दो species जो overlap करती हैं।
Setosa को अलग करना आसान है, इसलिए उसे सिर्फ़ 10 चाहिए।
ध्यान दीजिए: predict_proba एक extra calibration step इस्तेमाल करता है (internal cross-validation के साथ Platt scaling),
इसलिए इसकी सबसे संभावित class कभी-कभी predict से अलग हो सकती है।
Hyperparameter Tuning — GridSearchCV
120 朵训练花里有 47 朵是 support vectors —— 大多是 versicolor 和 virginica,这两个品种有重叠。
Setosa 很容易分开,所以只需要 10 个。
注意:predict_proba 用了一个额外的校准步骤(Platt scaling,内部带 cross-validation),
所以它给出的最可能的 class 偶尔会和 predict 不一致。
Hyperparameter 调参 —— GridSearchCV
from sklearn.model_selection import GridSearchCV
import pandas as pd
pipe = Pipeline([("scaler", StandardScaler()), ("svc", SVC())])
param_grid = [
{"svc__kernel": ["rbf"], "svc__C": [0.01, 0.1, 1, 10, 100],
"svc__gamma": ["scale", 0.001, 0.01, 0.1, 1]},
{"svc__kernel": ["linear"], "svc__C": [0.01, 0.1, 1, 10, 100]}, # linear has no gamma
]
grid = GridSearchCV(pipe, param_grid, cv=5, scoring="accuracy", n_jobs=-1)
grid.fit(X_train, y_train)
print("Best parameters: ", grid.best_params_)
print(f"Best CV accuracy: {grid.best_score_:.4f}")
print(f"Test accuracy: {grid.score(X_test, y_test):.4f}\n")
results = pd.DataFrame(grid.cv_results_)
top5 = results.nsmallest(5, "rank_test_score")[
["param_svc__kernel", "param_svc__C", "param_svc__gamma", "mean_test_score"]]
print(top5.to_string(index=False))
Notice that many settings tie at 97.5%. Also notice the pattern: a larger C paired with a smaller γ gives the same score — C and γ work together, so always tune them together. The linear kernel has no γ, so it gets its own small grid.
LinearSVC — Fast for Large Datasets and Text
देखिए कि कई settings 97.5% पर बराबर हैं। Pattern पर भी ध्यान दीजिए: बड़ा C और साथ में छोटा γ वही score देता है — C और γ साथ मिलकर काम करते हैं, इसलिए इन्हें हमेशा साथ tune कीजिए। Linear kernel में γ नहीं होता, इसलिए उसका अपना छोटा grid है।
LinearSVC — बड़े Datasets और Text के लिए तेज़
注意,很多设置都并列 97.5%。还要注意这个规律:更大的 C 配上更小的 γ会得到同样的分数 —— C 和 γ 是一起起作用的,所以一定要一起调。linear kernel 没有 γ,所以它有自己的一个小 grid。
LinearSVC —— 适合大 Dataset 和文本的快速方法
import pandas as pd
from sklearn.svm import LinearSVC
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report
# 20 Newsgroups (training part), 4 topics
url = "https://raw.githubusercontent.com/selva86/datasets/master/newsgroups.json"
news = pd.read_json(url)
topics = ["sci.space", "comp.graphics", "rec.sport.hockey", "talk.politics.guns"]
news = news[news["target_names"].isin(topics)]
X_train, X_test, y_train, y_test = train_test_split(
news["content"], news["target_names"], test_size=0.25, random_state=42,
stratify=news["target_names"])
text_pipeline = Pipeline([
("tfidf", TfidfVectorizer(sublinear_tf=True, ngram_range=(1, 2),
max_features=50000, stop_words="english")),
("clf", LinearSVC(C=1.0)), # liblinear: fast on sparse, high-dimensional data
])
text_pipeline.fit(X_train, y_train)
y_pred = text_pipeline.predict(X_test)
print(f"Test accuracy: {text_pipeline.score(X_test, y_test):.4f}\n")
print(classification_report(y_test, y_pred, digits=3))
98.3% accuracy on four newsgroups, using up to 50,000 word and word-pair features. The linear kernel is enough here: in such a high-dimensional space, the topics are already almost linearly separable.
Use LinearSVC when the data is large (more than about 10,000 rows), high-dimensional and sparse (text),
or when you need fast training. It uses the liblinear library, which scales roughly linearly with the number of rows.
Use SVC(kernel='linear') for small data, or when you need predict_proba() or the support vectors.
For curved boundaries you need a kernel, so use SVC(kernel='rbf') — or an approximation such as Nystroem + LinearSVC for large data.
Why Scaling Is Not Optional
चार newsgroups पर 98.3% accuracy, 50,000 तक word और word-pair features के साथ। यहाँ linear kernel काफ़ी है: इतने high-dimensional space में topics पहले से ही लगभग linearly separable हैं।
LinearSVC तब इस्तेमाल कीजिए जब data बड़ा हो (लगभग 10,000 rows से ज़्यादा), high-dimensional और sparse हो (text),
या जब आपको तेज़ training चाहिए। यह liblinear library इस्तेमाल करता है, जो rows की संख्या के साथ लगभग linearly बढ़ती है।
SVC(kernel='linear') छोटे data के लिए इस्तेमाल कीजिए, या जब आपको predict_proba() या support vectors चाहिए।
मुड़ी हुई boundaries के लिए kernel चाहिए, तो SVC(kernel='rbf') इस्तेमाल कीजिए — या बड़े data के लिए Nystroem + LinearSVC जैसा approximation।
Scaling ज़रूरी क्यों है
在四个新闻组上达到 98.3% 的 accuracy,最多用了 50,000 个单词和词对 feature。这里用 linear kernel 就够了:在这么高 dimension 的空间里,各个主题本来就几乎可以线性分开。
当数据很大(超过大约 10,000 行)、dimension 很高又稀疏(文本),
或者你需要快速训练时,用 LinearSVC。它用的是 liblinear 库,耗时大致随行数线性增长。
用 SVC(kernel='linear') 的情况是:数据小,或者你需要 predict_proba() 或 support vectors。
要画弯曲的边界就需要 kernel,所以用 SVC(kernel='rbf') —— 数据很大时,也可以用近似方法,比如 Nystroem + LinearSVC。
为什么 Scaling 不是可有可无的
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC
X, y = load_breast_cancer(return_X_y=True)
print(f"Feature ranges: {X.min(axis=0).min():.3f} ... {X.max(axis=0).max():.0f}")
raw = SVC(kernel="rbf")
scaled = Pipeline([("scaler", StandardScaler()), ("svc", SVC(kernel="rbf"))])
for name, model in [("Without scaling", raw), ("With StandardScaler", scaled)]:
acc = cross_val_score(model, X, y, cv=5).mean()
print(f"{name:20s}: CV accuracy = {acc:.4f}")
The same SVM, the same data: 91.2% without scaling and 97.4% with it. The breast cancer features range from about 0.001 to 4,254, so without scaling the largest features control every distance.
Try It — Scaling Matters
Risk depends on both income and age. Untick and tick StandardScaler first and watch the boundary turn.
वही SVM, वही data: scaling के बिना 91.2% और scaling के साथ 97.4%। Breast cancer features लगभग 0.001 से 4,254 तक जाते हैं, इसलिए scaling के बिना सबसे बड़े features हर distance पर हावी हो जाते हैं।
ख़ुद आज़माइए — Scaling Matters
Risk income और age दोनों पर निर्भर है। पहले StandardScaler को untick और tick कीजिए और boundary को घूमते हुए देखिए।
同样的 SVM,同样的数据:不做 scaling 是 91.2%,做了 scaling 是 97.4%。乳腺癌数据的 feature 范围从大约 0.001 到 4,254,所以不做 scaling 的话,最大的 feature 会控制每一个距离。
动手试试 —— Scaling Matters
风险同时取决于收入和年龄。取消勾选、再勾选先用 StandardScaler,看边界怎样转动。
SVM for Regression — SVR
SVM can also do regression. Instead of a street that separates classes, SVR (Support Vector Regression) fits a tube of width 2ε around the prediction, while keeping the function as flat as possible. Points inside the tube cost nothing. Only points outside the tube are penalised.
Try It — SVR: the Epsilon Tube
Make the tube wider and watch the support vectors disappear. Make it very narrow and almost every point becomes a support vector.
Regression के लिए SVM — SVR
SVM regression भी कर सकता है। Classes को अलग करने वाली सड़क की जगह, SVR (Support Vector Regression) prediction के चारों ओर 2ε चौड़ाई की एक tube fit करता है, और function को जितना हो सके सपाट रखता है। Tube के अंदर वाले points की कोई cost नहीं। सिर्फ़ tube के बाहर वाले points पर penalty लगती है।
ख़ुद आज़माइए — SVR: the Epsilon Tube
Tube को चौड़ा कीजिए और support vectors को ग़ायब होते देखिए। इसे बहुत पतला कीजिए और लगभग हर point support vector बन जाता है।
用 SVM 做 Regression —— SVR
SVM 也能做 regression。它不再用一条街道把 class 分开, 而是用 SVR(Support Vector Regression)在预测线周围拟合一条宽度为 2ε 的 tube,同时让函数尽可能平。 tube 里面的点没有代价。只有 tube 外面的点才会受到惩罚。
动手试试 —— SVR: the Epsilon Tube
把 tube 调宽,看 support vectors 消失。把它调得很窄,几乎每个点都会变成 support vector。
Now a real dataset — California housing, 16,512 training rows:
अब एक असली dataset — California housing, 16,512 training rows:
现在来看一个真实的 dataset —— California 房价,16,512 行 training data:
import pandas as pd
from sklearn.svm import SVR
from sklearn.impute import SimpleImputer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.metrics import r2_score, mean_absolute_error
# California housing (1990 census), 20,640 districts
url = "https://raw.githubusercontent.com/ageron/handson-ml2/master/datasets/housing/housing.csv"
df = pd.read_csv(url)
X = df.drop(columns=["median_house_value", "ocean_proximity"])
y = df["median_house_value"] / 100_000 # target in units of $100,000
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
svr_pipe = Pipeline([
("impute", SimpleImputer(strategy="median")), # SVR cannot handle missing values
("scaler", StandardScaler()), # SVR always needs scaling
("svr", SVR(kernel="rbf", C=10, epsilon=0.1, gamma="scale")),
])
svr_pipe.fit(X_train, y_train)
y_pred = svr_pipe.predict(X_test)
print(f"R² score: {r2_score(y_test, y_pred):.4f}")
print(f"MAE: ${mean_absolute_error(y_test, y_pred) * 100_000:,.0f}")
print(f"Support vectors: {len(svr_pipe['svr'].support_):,} of {len(X_train):,} training rows")
R² = 0.758, with a typical error of about $37,000. But look at the last line: 12,512 of 16,512 rows are support vectors. The target is in units of $100,000, so ε = 0.1 means a tube of only ±$10,000 — most houses fall outside it. A larger ε would give fewer support vectors and faster predictions. This fit also took minutes, while a Random Forest on the same data takes seconds.
ε (epsilon): half-width of the no-penalty tube, in the same units as y. Larger ε → fewer support vectors, smoother fit, less sensitive to noise. Smaller ε → more support vectors, tighter fit. C: penalty for points outside the tube. High C → the curve chases every point → overfitting risk. kernel and γ: the same as for classification.
Feature Importance with a Linear SVM
A linear SVM has a weight vector w with one number per feature. After scaling, the size of each weight shows how strongly that feature pushes a prediction towards one class, and its sign shows which class.
R² = 0.758, और आम error लगभग $37,000। पर आख़िरी line देखिए: 16,512 में से 12,512 rows support vectors हैं। Target $100,000 की units में है, इसलिए ε = 0.1 का मतलब है सिर्फ़ ±$10,000 की tube — ज़्यादातर घर इसके बाहर पड़ते हैं। बड़ा ε कम support vectors और तेज़ predictions देता। इस fit में minutes भी लगे, जबकि उसी data पर Random Forest seconds लेता है।
ε (epsilon): no-penalty tube की आधी चौड़ाई, y की ही units में। बड़ा ε → कम support vectors, ज़्यादा smooth fit, noise से कम असर। छोटा ε → ज़्यादा support vectors, ज़्यादा कसा fit। C: tube के बाहर वाले points की penalty। High C → curve हर point के पीछे भागता है → overfitting का ख़तरा। kernel और γ: वही जो classification में है।
Linear SVM से Feature Importance
Linear SVM में एक weight vector w होता है, जिसमें हर feature का एक number होता है। Scaling के बाद, हर weight का size बताता है कि वह feature prediction को किसी class की ओर कितनी ज़ोर से धकेलता है, और उसका sign बताता है कि किस class की ओर।
R² = 0.758,典型误差大约是 $37,000。 但看看最后一行:16,512 行里有 12,512 行是 support vectors。 目标值的单位是 $100,000,所以 ε = 0.1 意味着 tube 只有 ±$10,000 —— 大多数房子都落在 tube 外面。 更大的 ε 会带来更少的 support vectors 和更快的预测。这次拟合还花了好几分钟,而在同样的数据上,Random Forest 只要几秒。
ε(epsilon):无惩罚 tube 的半宽,单位和 y 相同。ε 更大 → support vectors 更少,拟合更平滑,对噪声更不敏感。ε 更小 → support vectors 更多,拟合更紧。 C:对 tube 外面的点的惩罚。C 大 → 曲线去追每一个点 → 有 overfitting 的风险。 kernel 和 γ:和 classification 中一样。
用 Linear SVM 看 Feature 的重要性
linear SVM 有一个 weight vector w,每个 feature 对应一个数。 做完 scaling 后,每个 weight 的大小表示这个 feature 把预测推向某个 class 的力度有多大, 而它的正负号表示推向哪个 class。
import pandas as pd
from sklearn.svm import LinearSVC
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X, y = cancer.data, cancer.target
print("Class names:", dict(enumerate(cancer.target_names))) # 0 = malignant, 1 = benign
pipe = Pipeline([
("scaler", StandardScaler()), # coefficients are comparable only after scaling
("svm", LinearSVC(C=1.0, max_iter=10000)),
])
pipe.fit(X, y)
# Positive coefficient -> pushes towards class 1 (BENIGN)
# Negative coefficient -> pushes towards class 0 (MALIGNANT)
coef = pd.Series(pipe["svm"].coef_[0], index=cancer.feature_names)
print("\nTop features pushing towards MALIGNANT (most negative):")
print(coef.sort_values().head(5).round(3).to_string())
print("\nTop features pushing towards BENIGN (most positive):")
print(coef.sort_values(ascending=False).head(5).round(3).to_string())
1. Check the class order. In this dataset class 1 is benign, so positive weights point towards benign — easy to get backwards.
2. Correlated features share and swap weight. Radius, perimeter and area measure almost the same thing.
That is why “worst area” pushes strongly towards malignant while “mean radius” gets a small positive weight — the model splits the effect between them.
Do not read one coefficient alone when features are correlated.
3. coef_ exists only for LinearSVC and SVC(kernel='linear'). Kernel SVMs have no weight per original feature —
use permutation_importance instead.
SVM vs Other Classifiers — Comparison
| Property | SVM (RBF) | Random Forest | Logistic Reg. | Neural Net |
|---|---|---|---|---|
| Training speed | Slow: about O(n²) to O(n³) | Fast (parallel) | Very fast | Slow |
| Prediction speed | O(n_SV × features) | Moderate | Fastest | Fast |
| Scales to large N | Poorly (> 100k rows is painful) | Well | Very well | Very well |
| High-dimensional sparse data | Excellent (linear kernel) | Poor | Excellent | Moderate |
| Feature scaling needed | Essential | No | Recommended | Yes |
| Probability outputs | Only via extra calibration (Platt) | Yes (average of tree votes) | Yes, usually well calibrated | Yes (softmax) |
| Non-linear boundaries | Excellent (kernels) | Excellent | Linear only (unless you add features) | Excellent |
| Hyperparameter tuning | C + γ — sensitive | Robust defaults | Simple (C) | Many — very sensitive |
| Interpretability | Linear: moderate; RBF: low | Feature importance | High — coefficients | Black box |
When to Use SVM
Strengths vs Weaknesses
| Maximum margin — strong generalisation theory |
| Excellent on high-dimensional sparse data (text) |
| Works when features > samples |
| Not disturbed by points far from the boundary |
| The model only needs its support vectors |
| Kernels give flexible non-linear boundaries |
| Convex optimisation — one global best solution |
| Same idea works for regression (SVR) and outliers (One-Class SVM) |
| Kernel SVM training is slow: about O(n²) to O(n³) |
| Feature scaling is essential — easy to forget |
| No built-in probabilities — Platt scaling adds cost |
| Sensitive to C and γ |
| Hard to interpret with non-linear kernels |
| Painful above ~100k rows |
| Multi-class is built from many binary SVMs (one-vs-one in SVC) |
| No incremental learning in SVC (SGDClassifier can) |
For data too large for SVC, use SGDClassifier(loss='hinge'). It trains a linear SVM with stochastic gradient descent,
scales to millions of rows, and supports online learning with partial_fit.
Use loss='modified_huber' if you also need probability estimates.
1. Class का क्रम जाँचिए। इस dataset में class 1 benign है, इसलिए positive weights benign की ओर इशारा करते हैं — इसे उल्टा समझना आसान है।
2. Correlated features weight को बाँटते और अदल-बदल करते हैं। Radius, perimeter और area लगभग एक ही चीज़ नापते हैं।
इसीलिए “worst area” ज़ोर से malignant की ओर धकेलता है, जबकि “mean radius” को एक छोटा positive weight मिलता है — model असर को इनके बीच बाँट देता है।
जब features correlated हों, तो एक coefficient को अकेले मत पढ़िए।
3. coef_ सिर्फ़ LinearSVC और SVC(kernel='linear') में होता है। Kernel SVMs में हर original feature का weight नहीं होता —
उनके लिए permutation_importance इस्तेमाल कीजिए।
SVM vs दूसरे Classifiers — तुलना
| गुण | SVM (RBF) | Random Forest | Logistic Reg. | Neural Net |
|---|---|---|---|---|
| Training की speed | धीमा: लगभग O(n²) से O(n³) | तेज़ (parallel) | बहुत तेज़ | धीमा |
| Prediction की speed | O(n_SV × features) | मध्यम | सबसे तेज़ | तेज़ |
| बड़े N तक scale | ख़राब (> 100k rows पर तकलीफ़) | अच्छा | बहुत अच्छा | बहुत अच्छा |
| High-dimensional sparse data | बेहतरीन (linear kernel) | ख़राब | बेहतरीन | मध्यम |
| Feature scaling ज़रूरी | बेहद ज़रूरी | नहीं | सलाह दी जाती है | हाँ |
| Probability outputs | सिर्फ़ extra calibration से (Platt) | हाँ (trees के votes का average) | हाँ, आमतौर पर अच्छी तरह calibrated | हाँ (softmax) |
| Non-linear boundaries | बेहतरीन (kernels) | बेहतरीन | सिर्फ़ linear (जब तक आप features न जोड़ें) | बेहतरीन |
| Hyperparameter tuning | C + γ — sensitive | मज़बूत defaults | आसान (C) | बहुत सारे — बहुत sensitive |
| समझने में आसानी | Linear: मध्यम; RBF: कम | Feature importance | ज़्यादा — coefficients | Black box |
SVM कब इस्तेमाल करें
ख़ूबियाँ vs कमियाँ
| Maximum margin — generalisation की मज़बूत theory |
| High-dimensional sparse data (text) पर बेहतरीन |
| तब भी काम करता है जब features > samples |
| Boundary से दूर वाले points से परेशान नहीं होता |
| Model को सिर्फ़ अपने support vectors चाहिए |
| Kernels से flexible non-linear boundaries मिलती हैं |
| Convex optimisation — एक ही global सबसे अच्छा solution |
| यही विचार regression (SVR) और outliers (One-Class SVM) के लिए भी काम करता है |
| Kernel SVM की training धीमी है: लगभग O(n²) से O(n³) |
| Feature scaling बेहद ज़रूरी — भूलना आसान |
| Built-in probabilities नहीं — Platt scaling से cost बढ़ती है |
| C और γ के प्रति sensitive |
| Non-linear kernels के साथ समझना मुश्किल |
| ~100k rows से ऊपर तकलीफ़देह |
| Multi-class कई binary SVMs से बनता है (SVC में one-vs-one) |
| SVC में incremental learning नहीं (SGDClassifier कर सकता है) |
जो data SVC के लिए बहुत बड़ा है, उसके लिए SGDClassifier(loss='hinge') इस्तेमाल कीजिए। यह stochastic gradient descent से linear SVM train करता है,
लाखों rows तक scale करता है, और partial_fit से online learning को support करता है।
अगर आपको probability estimates भी चाहिए, तो loss='modified_huber' इस्तेमाल कीजिए।
1. 检查 class 的顺序。在这个 dataset 里,class 1 是良性,所以正的 weight 指向良性 —— 很容易弄反。
2. 相关的 feature 会分享、互换 weight。radius、perimeter 和 area 量的几乎是同一样东西。
所以“worst area”强烈地推向恶性,而“mean radius”却得到一个小的正 weight —— model 把效果分摊到了它们之间。
feature 之间相关时,不要单独解读一个系数。
3. coef_ 只有 LinearSVC 和 SVC(kernel='linear') 才有。kernel SVM 没有对应每个原始 feature 的 weight ——
请改用 permutation_importance。
SVM 和其他分类器 —— 对比
| 性质 | SVM (RBF) | Random Forest | Logistic Reg. | Neural Net |
|---|---|---|---|---|
| 训练速度 | 慢:大约 O(n²) 到 O(n³) | 快(可并行) | 非常快 | 慢 |
| 预测速度 | O(n_SV × features) | 中等 | 最快 | 快 |
| 能否扩展到很大的 N | 差(> 100k 行就很痛苦) | 好 | 非常好 | 非常好 |
| 高 dimension 稀疏数据 | 非常好(linear kernel) | 差 | 非常好 | 中等 |
| 需要 feature scaling | 必须 | 不需要 | 推荐 | 需要 |
| Probability 输出 | 只能通过额外校准(Platt) | 有(树投票的平均) | 有,通常校准得很好 | 有(softmax) |
| 非线性边界 | 非常好(kernel) | 非常好 | 只能线性(除非你加 feature) | 非常好 |
| Hyperparameter 调参 | C + γ —— 很敏感 | 默认值就很稳 | 简单(C) | 很多 —— 非常敏感 |
| 可解释性 | Linear:中等;RBF:低 | Feature importance | 高 —— 系数 | 黑箱 |
什么时候用 SVM
优点 vs 缺点
| Margin 最大 —— 有很强的泛化理论支持 |
| 在高 dimension 稀疏数据(文本)上非常好 |
| feature > 样本时也能用 |
| 不受离边界很远的点干扰 |
| model 只需要保存它的 support vectors |
| kernel 带来灵活的非线性边界 |
| 凸优化 —— 只有一个全局最优解 |
| 同样的思想也能用于 regression(SVR)和 outlier(One-Class SVM) |
| kernel SVM 训练很慢:大约 O(n²) 到 O(n³) |
| feature scaling 必不可少 —— 很容易忘 |
| 没有内置的 probability —— Platt scaling 会增加开销 |
| 对 C 和 γ 很敏感 |
| 用非线性 kernel 时很难解释 |
| 超过约 100k 行就很痛苦 |
| 多分类是由很多个二分类 SVM 拼成的(SVC 里是 one-vs-one) |
| SVC 不支持增量学习(SGDClassifier 可以) |
数据太大、SVC 处理不了时,用 SGDClassifier(loss='hinge')。它用随机梯度下降来训练一个 linear SVM,
能扩展到几百万行,还可以用 partial_fit 做在线学习。
如果你还需要 probability 估计,就用 loss='modified_huber'。
import time
from sklearn.datasets import make_classification
from sklearn.linear_model import SGDClassifier
from sklearn.svm import LinearSVC, SVC
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
X, y = make_classification(n_samples=200_000, n_features=50, n_informative=20, random_state=0)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.2, random_state=0)
for name, model in [
("LinearSVC ", LinearSVC(C=1.0)),
("SGDClassifier(hinge) ", SGDClassifier(loss="hinge", alpha=1e-4, random_state=0)),
("SVC(kernel='linear')* ", SVC(kernel="linear", C=1.0)),
]:
pipe = Pipeline([("scaler", StandardScaler()), ("m", model)])
n = 20_000 if name.startswith("SVC") else len(Xtr) # * SVC only gets 20k rows
t0 = time.perf_counter()
pipe.fit(Xtr[:n], ytr[:n])
print(f"{name} rows={n:>7,} fit={time.perf_counter()-t0:6.1f}s test acc={pipe.score(Xte, yte):.4f}")
All three reach about 80% accuracy. LinearSVC and SGDClassifier train on 160,000 rows in about one second. Kernel-solver SVC needed a full minute for just 20,000 rows — and the time grows much faster than the number of rows.
Real-World Applications
- Cancer classification from gene expression
- Protein function and structure prediction
- Works when genes ≫ patients
- One of the early ML successes in genomics
- Handwritten digit recognition (MNIST)
- Pedestrian detection with HOG features
- Classic computer vision before deep learning
- Still useful for small image datasets
- Fraud detection and anomaly scoring
- Credit risk classification
- Intrusion detection systems
- One-Class SVM for outlier detection
Golden Rules
StandardScaler inside a Pipeline, so the scaler is fitted only on training data (no data leakage).
In Section 08 this alone raised accuracy from 91.2% to 97.4%.
GridSearchCV with, for example, C ∈ {0.01, 0.1, 1, 10, 100} and γ ∈ {'scale', 0.001, 0.01, 0.1, 1}.
Never tune one while keeping the other fixed.
gamma='scale'.
It sets γ = 1 / (n_features × X.var()), so it adapts to how spread out your (scaled) data is.
'auto' (γ = 1 / n_features) ignores the spread. After StandardScaler the two are almost the same, but 'scale' is the safer default.
LinearSVC (liblinear) scales roughly linearly with the number of rows.
SVC(kernel='linear') (libsvm) grows much faster — in Section 13 it took a minute for 20,000 rows.
probability=True when you create the model.
It cannot be switched on after fitting — the model must be trained again.
It runs an internal 5-fold cross-validation for Platt scaling, so training is much slower,
and predict_proba can occasionally disagree with predict. Use it only when you really need probabilities.
SGDClassifier(loss='hinge') or LinearSVC.
Both train a linear SVM in roughly linear time. SGD gives an approximate solution, but usually very close to the exact one.
Keep StandardScaler in the pipeline as always.
sklearn.svm.OneClassSVM learns the boundary of normal data without any examples of the other class.
It predicts −1 for outliers and +1 for normal points.
Set nu (roughly the expected fraction of outliers) instead of C. Scale the features first.
तीनों लगभग 80% accuracy तक पहुँचते हैं। LinearSVC और SGDClassifier 160,000 rows पर लगभग एक second में train होते हैं। Kernel-solver वाले SVC को सिर्फ़ 20,000 rows के लिए पूरा एक minute लगा — और समय rows की संख्या से कहीं ज़्यादा तेज़ी से बढ़ता है।
असल दुनिया में इस्तेमाल
- Gene expression से cancer classification
- Protein के function और structure का prediction
- तब भी काम करता है जब genes ≫ मरीज़
- Genomics में ML की शुरुआती सफलताओं में से एक
- हाथ से लिखे अंकों की पहचान (MNIST)
- HOG features से पैदल यात्रियों की पहचान
- Deep learning से पहले का classic computer vision
- छोटे image datasets के लिए आज भी काम का
- Fraud detection और anomaly scoring
- Credit risk classification
- Intrusion detection systems
- Outlier detection के लिए One-Class SVM
सुनहरे नियम
StandardScaler को एक Pipeline के अंदर रखिए, ताकि scaler सिर्फ़ training data पर fit हो (कोई data leakage नहीं)।
सेक्शन 08 में सिर्फ़ इसी से accuracy 91.2% से 97.4% हो गई।
GridSearchCV इस्तेमाल कीजिए, जैसे C ∈ {0.01, 0.1, 1, 10, 100} और γ ∈ {'scale', 0.001, 0.01, 0.1, 1}।
एक को fixed रखकर दूसरे को कभी tune मत कीजिए।
gamma='scale' से शुरू कीजिए।
यह γ = 1 / (n_features × X.var()) रखता है, इसलिए यह आपके (scaled) data के फैलाव के हिसाब से ढल जाता है।
'auto' (γ = 1 / n_features) फैलाव को नज़रअंदाज़ करता है। StandardScaler के बाद दोनों लगभग एक जैसे हैं, पर 'scale' ज़्यादा सुरक्षित default है।
LinearSVC (liblinear) rows की संख्या के साथ लगभग linearly बढ़ता है।
SVC(kernel='linear') (libsvm) बहुत तेज़ी से बढ़ता है — सेक्शन 13 में इसे 20,000 rows के लिए एक minute लगा।
probability=True रखिए।
Fit करने के बाद इसे चालू नहीं किया जा सकता — model को फिर से train करना पड़ता है।
यह Platt scaling के लिए एक internal 5-fold cross-validation चलाता है, इसलिए training बहुत धीमी हो जाती है,
और predict_proba कभी-कभी predict से अलग जवाब दे सकता है। इसे तभी इस्तेमाल कीजिए जब सच में probabilities चाहिए।
SGDClassifier(loss='hinge') या LinearSVC पर जाइए।
दोनों लगभग linear समय में linear SVM train करते हैं। SGD एक अनुमानित solution देता है, पर आमतौर पर exact वाले के बहुत क़रीब।
हमेशा की तरह StandardScaler को pipeline में रखिए।
sklearn.svm.OneClassSVM दूसरी class के किसी उदाहरण के बिना normal data की boundary सीखता है।
यह outliers के लिए −1 और normal points के लिए +1 predict करता है।
C की जगह nu रखिए (मोटे तौर पर outliers का अपेक्षित हिस्सा)। पहले features को scale कीजिए।
三者的 accuracy 都在 80% 左右。LinearSVC 和 SGDClassifier 在 160,000 行上训练只要大约一秒。 用 kernel 求解器的 SVC 只训练 20,000 行就花了整整一分钟 —— 而且时间增长得比行数快得多。
真实世界中的应用
- 根据基因表达对癌症分类
- 预测蛋白质的功能和结构
- 在基因数 ≫ 病人数时也能用
- ML 在基因组学中最早的成功案例之一
- 手写数字识别(MNIST)
- 用 HOG feature 检测行人
- deep learning 出现之前的经典计算机视觉
- 对小型图像 dataset 仍然有用
- 欺诈检测和异常评分
- 信用风险分类
- 入侵检测系统
- 用 One-Class SVM 做 outlier 检测
黄金法则
StandardScaler 放进一个 Pipeline 里,这样 scaler 只在 training data 上 fit(没有数据泄漏)。
在第 08 节,仅仅这一步就把 accuracy 从 91.2% 提高到了 97.4%。
GridSearchCV,比如 C ∈ {0.01, 0.1, 1, 10, 100},γ ∈ {'scale', 0.001, 0.01, 0.1, 1}。
千万不要固定一个、只调另一个。
gamma='scale' 开始。
它设定 γ = 1 / (n_features × X.var()),所以会根据你(scaling 之后的)数据有多分散来自动调整。
'auto'(γ = 1 / n_features)不考虑分散程度。用了 StandardScaler 之后,两者几乎一样,但 'scale' 是更安全的默认值。
LinearSVC(liblinear)的耗时大致随行数线性增长。
SVC(kernel='linear')(libsvm)增长得快得多 —— 在第 13 节,它训练 20,000 行就花了一分钟。
probability=True。
fit 之后就不能再打开它了 —— 必须重新训练 model。
它会为 Platt scaling 在内部运行一次 5-fold cross-validation,所以训练会慢很多,
而且 predict_proba 偶尔会和 predict 不一致。只有真正需要 probability 时才用它。
SGDClassifier(loss='hinge') 或 LinearSVC。
两者都能在大致线性的时间内训练一个 linear SVM。SGD 给出的是近似解,但通常和精确解非常接近。
像往常一样,把 StandardScaler 留在 pipeline 里。
sklearn.svm.OneClassSVM 学习正常数据的边界,完全不需要另一个 class 的例子。
它对 outlier 预测 −1,对正常的点预测 +1。
设置 nu(大致是预期的 outlier 比例),而不是 C。先对 feature 做 scaling。