Support Vector Machine (SVM)
Support Vector Machine क्या है?
Support Vector Machine (SVM) एक classification algorithm है जो दो classes के बीच की सीमा सबसे चौड़े संभव फ़ासले (margin) के साथ खींचता है। दो गाँवों के बीच सड़क सोचिए: SVM सबसे चौड़ी सड़क बनाता है जिससे हर घर अपनी तरफ़ रहे। सड़क के किनारों को छूने वाले घर ही support vectors हैं – सड़क कहाँ जाएगी, सिर्फ़ वही तय करते हैं।
| शब्द | अर्थ |
|---|---|
| Hyperplane | Decision boundary – 2-D में line, 3-D में plane |
| Margin | Boundary से हर class के सबसे पास वाले points की दूरी |
| Support vectors | Boundary के सबसे पास वाले training points |
| C | ग़लतियों की सज़ा: छोटा C = चौड़ा, नरम margin; बड़ा C = training data पर कसकर fit |
| Kernel | घुमावदार boundaries बनाने की तरकीब (RBF, polynomial) |
| gamma | RBF में: एक point का असर कितनी दूर तक; बड़ा gamma = टेढ़ी-मेढ़ी boundary |
Step 1: दिखने वाला linear SVM
बारह students: पढ़ाई के घंटे और पिछली रात की नींद के घंटे, और वे pass हुए या नहीं। Linear SVM boundary ढूँढता है और बताता है कि कौन से students support vectors हैं।
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVC
X = np.array([[1, 5], [2, 4], [2, 6], [3, 3], [3, 5], [4, 2], # failed
[5, 7], [6, 6], [6, 8], [7, 5], [8, 7], [8, 6]]) # passed
y = np.array([0] * 6 + [1] * 6)
model = SVC(kernel="linear", C=1.0).fit(X, y)
print("support vectors:\n", model.support_vectors_)
print("prediction for 4.5 h study, 6 h sleep:", ["fail", "pass"][model.predict([[4.5, 6]])[0]])
# draw points, boundary and margins
xx, yy = np.meshgrid(np.linspace(0, 9, 200), np.linspace(1, 9, 200))
zz = model.decision_function(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
fig, ax = plt.subplots(figsize=(7, 4.2), dpi=110)
ax.contour(xx, yy, zz, levels=[-1, 0, 1], linestyles=["--", "-", "--"], colors="#334155")
ax.scatter(X[:, 0], X[:, 1], c=np.where(y == 1, "#16a34a", "#dc2626"), s=60, edgecolor="k")
ax.scatter(*model.support_vectors_.T, s=220, facecolors="none", edgecolors="#2563eb", linewidths=2, label="support vectors")
ax.set_xlabel("hours studied"); ax.set_ylabel("hours slept"); ax.legend(loc="lower right")
ax.set_title("Linear SVM: solid = boundary, dashed = margin")
fig.tight_layout(); fig.savefig("svm_margin.png")
सिर्फ़ घेरे वाले points मायने रखते हैं। कोई और point हटाकर दोबारा train करें – boundary नहीं हिलेगी।
Step 2: घुमावदार boundaries के लिए kernels
असली data शायद ही सीधी line से अलग होता है। RBF kernel से SVM, आपके हाथ से नए features बनाए बिना, curves बना सकता है।
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
X, y = make_moons(n_samples=300, noise=0.2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
fig, axes = plt.subplots(1, 2, figsize=(9, 3.6), dpi=110)
xx, yy = np.meshgrid(np.linspace(-1.5, 2.5, 300), np.linspace(-1, 1.5, 300))
for ax, kernel in zip(axes, ["linear", "rbf"]):
m = SVC(kernel=kernel, C=1, gamma="scale").fit(X_train, y_train)
print(f"{kernel:<6} test accuracy: {m.score(X_test, y_test):.2f}")
zz = m.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)
ax.contourf(xx, yy, zz, alpha=0.25, cmap="RdYlGn")
ax.scatter(X[:, 0], X[:, 1], c=y, cmap="RdYlGn", s=12, edgecolor="k", linewidths=0.3)
ax.set_title(f"kernel = {kernel}")
fig.tight_layout(); fig.savefig("kernels.png")
Step 3: C और gamma क्या करते हैं
from sklearn.datasets import make_moons
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
X, y = make_moons(n_samples=300, noise=0.25, random_state=1)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=1)
print(f"{'C':>6} {'gamma':>6} {'train':>6} {'test':>6} {'#SV':>5}")
for C, gamma in [(0.1, 0.5), (1, 0.5), (1, 5), (100, 50)]:
m = SVC(kernel="rbf", C=C, gamma=gamma).fit(X_tr, y_tr)
print(f"{C:>6} {gamma:>6} {m.score(X_tr, y_tr):>6.2f} {m.score(X_te, y_te):>6.2f} {len(m.support_):>5}")आख़िरी row training data पर लगभग 100% पर test data पर कम – उसने noise रट लिया (overfitting)। C और gamma cross-validation से चुनें, training accuracy देखकर कभी नहीं।
Step 4: असली medical dataset (scaling के साथ)
scikit-learn में Wisconsin breast-cancer dataset है: 569 tumour samples, हर एक के 30 measurements, malignant या benign label के साथ। SVM दूरियाँ नापता है, इसलिए बड़े numbers वाले features (area ≈ 1000) छोटे वालों (smoothness ≈ 0.1) पर हावी हो जाते। हमेशा पहले features scale करें – Pipeline इसे सुरक्षित करता है।
from sklearn.datasets import load_breast_cancer
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
data = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(
data.data, data.target, test_size=0.25, stratify=data.target, random_state=42)
unscaled = SVC().fit(X_train, y_train)
print("without scaling:", round(unscaled.score(X_test, y_test), 3))
pipe = make_pipeline(StandardScaler(), SVC())
grid = GridSearchCV(pipe, {"svc__C": [0.1, 1, 10], "svc__gamma": ["scale", 0.01, 0.1]}, cv=5)
grid.fit(X_train, y_train)
print("best params :", grid.best_params_)
print("with scaling :", round(grid.score(X_test, y_test), 3))
pred = grid.predict(X_test)
print(confusion_matrix(y_test, pred))
print(classification_report(y_test, pred, target_names=data.target_names, digits=3))Confusion matrix row-by-row पढ़ें: पहली row असली malignant tumours, दूसरी असली benign। Medicine में malignant tumour छूट जाना (ऊपर-दाएँ cell) सबसे महँगी ग़लती है, इसलिए सिर्फ़ accuracy नहीं, malignant recall देखें।
SVM कब इस्तेमाल करें
| अच्छा | कम उपयुक्त |
|---|---|
| छोटे से मध्यम datasets (सैकड़ों से दसियों हज़ार rows) | करोड़ों rows – training धीमी |
| बहुत सारे features, जैसे हज़ारों शब्दों वाला text | जब probabilities या आसान explanation चाहिए |
| Classes के बीच साफ़ margin | बिना tuning के बहुत noisy, overlapping classes |
असली business समस्या पर दूसरे classifiers से तुलना के लिए Data Science course का churn project देखें।
अभ्यास
- Step 1 में C को 0.01 और 100 करके बताइए कि margin कैसे बदलता है।
- Moons data पर
kernel="poly", degree=3आज़माकर test accuracy की तुलना करें। - Step 4 में
class_weight="balanced"जोड़कर malignant recall की तुलना करें। SVC(probability=True)से पहले 5 test samples की probability छापें।
सारांश
- SVM सबसे चौड़े margin वाली boundary ढूँढता है; support vectors उसे तय करते हैं।
- C चौड़े margin और training ग़लतियों के बीच संतुलन रखता है।
- Kernels (RBF, poly) घुमावदार boundaries बनाते हैं; gamma घुमाव तय करता है।
- हमेशा features scale करें (Pipeline में StandardScaler) और C/gamma cross-validation से tune करें।
- सिर्फ़ accuracy नहीं, confusion matrix और recall से परखें।
