By the end of this lecture, you should be able to:
| Step | Idea | Name |
|---|---|---|
| 1 | Separate two classes with the widest possible gap | Maximal margin classifier |
| 2 | Allow a few mistakes so outliers don’t ruin it | Support Vector Classifier (soft margin) |
| 3 | If no straight line works, add dimensions until one does | Support Vector Machine (kernels) |
Running example
A doctor gives patients different doses of a drug (mg). We want to predict whether a new patient will be cured (blue) or not cured (orange).
Key insight
Only the support vectors matter. Move any other point (without crossing the margin) and the threshold does not change.
Important
A classifier that uses a soft margin is called a Support Vector Classifier (SVC). How many mistakes to allow is a hyperparameter, so we pick it with cross-validation.
| Number of features | Data lives in … | The Support Vector Classifier is a … |
|---|---|---|
| 1 (dose) | a number line | point |
| 2 (dose, age) | a plane | line |
| 3 (dose, age, weight) | 3-D space | plane |
| 4 or more | can’t draw it! | hyperplane |
The idea is always the same: find the boundary with the biggest (soft) margin.
CIn scikit-learn, C controls how much mistakes are punished.
C: mistakes are cheap, giving a wide margin, more support vectors, and simpler models (risk of underfitting).C: mistakes are expensive, giving a narrow margin and models that chase every point (risk of overfitting).C from 1 to 1000. Does the margin get wider or narrower?Back in the original space …
A straight line in \((x, x^2)\) space becomes two thresholds on the original number line: “cured” if the dose is in the middle. That’s a non-linear boundary.
But how do we choose the new dimensions? \(x^2\)? \(x^3\)? \(\sqrt{x}\)? This is where kernels come in.
A kernel is a function \(K(a, b)\) that takes two data points and returns a number that measures how they relate in a higher dimension.
Two popular kernels:
| Kernel | Formula | Hyperparameters |
|---|---|---|
| Polynomial | \(K(a, b) = (a \times b + r)^d\) | \(r\) (coef0), \(d\) (degree) |
| Radial Basis Function (RBF) | \(K(a, b) = e^{-\gamma (a - b)^2}\) | \(\gamma\) (gamma) |
Both are chosen with cross-validation, along with C.
Take \(r = \tfrac{1}{2}\) and \(d = 2\):
\[ \begin{aligned} \left(ab + \tfrac{1}{2}\right)^2 &= a^2b^2 + ab + \tfrac{1}{4} \\[4pt] &= \underbrace{a \cdot b}_{\text{1st}} + \underbrace{a^2 \cdot b^2}_{\text{2nd}} + \underbrace{\tfrac{1}{2} \cdot \tfrac{1}{2}}_{\text{3rd}} \\[4pt] &= \left(a,\ a^2,\ \tfrac{1}{2}\right) \cdot \left(b,\ b^2,\ \tfrac{1}{2}\right) \end{aligned} \]
Two patients received doses \(a = 2\) and \(b = 3\). Use \(r = \tfrac{1}{2}\), \(d = 2\).
Same answer, and we never had to build the new coordinates! 🎉
The kernel trick
SVMs only need the relationships between pairs of points (dot products in the high-dimensional space), and a kernel computes those directly from the original data. This makes high (even infinite!) dimensions affordable.
The actual optimization (finding which points are support vectors) uses a method called Lagrange multipliers; we let scikit-learn handle it.
\[ K(a, b) = e^{-\gamma\,(a - b)^2} \]
gammagamma controls how far the influence of one training point reaches.
gamma: each point influences a wide area, so the boundary is smooth (risk: underfit).gamma: each point influences only its neighborhood, so the boundary is wiggly (risk: overfit).from sklearn.svm import SVC
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
svm = make_pipeline(
StandardScaler(), # SVMs are distance-based → ALWAYS scale!
SVC(kernel="rbf", C=1.0, gamma="scale")
)
svm.fit(X_train, y_train)
print("Test accuracy:", svm.score(X_test, y_test))| Argument | Meaning | Typical values to try |
|---|---|---|
kernel |
"linear", "poly", "rbf" |
start with "rbf" |
C |
penalty for mistakes | 0.01, 0.1, 1, 10, 100 |
gamma |
reach of each point (RBF / poly) | 0.001 … 10, or "scale" |
degree, coef0 |
\(d\) and \(r\) of the polynomial kernel | 2, 3 / 0, 1 |
StandardScaler inside a pipeline so that cross-validation scales correctly (no data leakage).Warning
An unscaled SVM can perform much worse than a scaled one on the same data. You’ll see this in the practice notebook.
C and gamma with Cross-Validationfrom sklearn.model_selection import GridSearchCV
param_grid = {
"svc__C": [0.01, 0.1, 1, 10, 100],
"svc__gamma": [0.001, 0.01, 0.1, 1, 10],
}
search = GridSearchCV(svm, param_grid, cv=5)
search.fit(X_train, y_train)
print(search.best_params_)
print("Best CV accuracy:", search.best_score_)
print("Test accuracy: ", search.score(X_test, y_test))svc__C means “the C of the step named svc in the pipeline”.decision_function > 0 → one class, < 0 → the other; the size tells you how confident the model is.SVC does not give probabilities by default. Use SVC(probability=True) if you need predict_proba (slower).| 👍 Strengths | 👎 Weaknesses |
|---|---|
| Works well with many features, even more features than samples | Slow on large datasets (training grows quickly with the number of rows) |
| Kernels capture non-linear patterns | Must scale features and tune C / gamma |
| Only the support vectors matter, so the model is memory efficient | Hard to interpret (no feature importances for RBF) |
| Soft margin is robust to outliers | No probabilities by default |
Match each change to its effect:
| Change | Effect? |
|---|---|
A. Increase C |
1. Boundary becomes smoother |
B. Decrease gamma |
2. Margin becomes narrower |
| C. Switch from linear to RBF kernel | 3. Model can learn curved boundaries |
| D. Forget to scale features | 4. Large-valued features dominate the distances |
A → 2, B → 1, C → 3, D → 4
C) trades a few training mistakes for better generalization.gamma controls each point’s reach.C and gamma with cross-validation.Open the practice notebook and work through it with a partner:
You will:
SVC.C changes the margin and the number of support vectors.gamma.GridSearchCV.