Support Vector Machines — تعلم الآلة
آلات المتجهات الداعمة (SVM)
من بين كل الخطوط التي تفصل فئتين، أيها الأفضل؟ SVM يختار الخط الذي يترك أوسع شارع بين الفئتين.
الهامش الأقصى
○ ○ | ● ●
○ ○ · | · ● ●
○ · | · ●
←هامش→- الهامش (margin): المسافة بين الخط وأقرب النقاط من الفئتين.
- المتجهات الداعمة (support vectors): هذه النقاط الأقرب. هي وحدها التي تحدد الخط؛ حذف أي نقطة أخرى لا يغيّر شيئاً.
- الهامش الأوسع = تعميم أفضل على البيانات الجديدة.
البيانات ليست مثالية: المعامل C
في الواقع تتداخل الفئات. SVM يسمح ببعض الأخطاء، و C يتحكم في التوازن:
| C | السلوك |
|---|---|
| صغير | هامش واسع ويتسامح مع الأخطاء ← تعميم أفضل، قد يصل لـ Underfitting |
| كبير | يحاول تصنيف كل نقطة تدريب صحيحاً ← هامش ضيق، خطر Overfitting |
Kernel Trick: حدود منحنية
ماذا لو كانت فئة في دائرة داخل الأخرى؟ لا خط مستقيم يفصلهما. الحيلة: تحويل البيانات إلى بعد أعلى حيث يصبح الفصل خطياً — دون حساب التحويل فعلياً.
| النواة | الشكل |
|---|---|
| linear | خط/مستوى — سريع، جيد للبيانات النصية عالية الأبعاد |
| rbf (الافتراضي) | حدود مرنة منحنية — معامل gamma يحدد مدى تأثير كل نقطة |
| poly | حدود متعددة الحدود |
from sklearn.datasets import make_circles
from sklearn.model_selection import cross_val_score
from sklearn.svm import SVC
X, y = make_circles(n_samples=300, noise=0.1, factor=0.4, random_state=0)
for kernel in ["linear", "rbf"]:
print(kernel, round(cross_val_score(SVC(kernel=kernel), X, y, cv=5).mean(), 2))النواة الخطية تفشل (قرابة 50%) والـ rbf تنجح — لأن الحد الحقيقي دائرة.
ملاحظات عملية
- التقييس ضروري (مسافات وهوامش).
- اضبط C و gamma معاً بـ GridSearchCV على مقياس لوغاريتمي (0.01، 0.1، 1، 10، 100).
- بطيء مع مئات الآلاف من العينات؛ هناك LinearSVC الأسرع للحالة الخطية.
- لا يعطي احتمالات افتراضياً؛ probability=True يضيفها بكلفة تدريب إضافية.
تمرين
في المثال الكامل استبدل حلقتي kernel و C بـ GridSearchCV على C و gamma، واطبع أفضل معاملات ودقتها.
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
import matplotlib.pyplot as plt
import numpy as np
# إنشاء بيانات
X, y = make_classification(n_samples=100, n_features=2,
n_redundant=0, n_clusters_per_class=1, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Scaling
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# تجربة Kernels مختلفة
kernels = ['linear', 'rbf', 'poly']
for kernel in kernels:
model = SVC(kernel=kernel)
model.fit(X_train, y_train)
acc = model.score(X_test, y_test)
print(f"{kernel}: {acc:.2%}")
# RBF مع C مختلفة
for c in [0.1, 1, 10]:
model = SVC(kernel='rbf', C=c)
model.fit(X_train, y_train)
acc = model.score(X_test, y_test)
print(f"C={c}: {acc:.2%}")
# النموذج النهائي
final_model = SVC(kernel='rbf', C=1, probability=True)
final_model.fit(X_train, y_train)
# التنبؤ مع الاحتمالية
proba = final_model.predict_proba(X_test[:1])
print(f"احتمالية الفئات: {proba}")اختبر فهمك