সরাসরি পর্বে যান
পর্ব ২৯ · ৭৭-এর মধ্যে · মডিউল ৬

Kernel trick — RBF, polynomial আর Mercer-এর অন্তর্দৃষ্টি

The Kernel Trick — Feature Maps, Polynomial and RBF Kernels, Gram Matrices and Mercer's Condition

Taught in Bangla, this lesson shows why SVMs need only dot products: lifting data with a feature map, expanding the polynomial kernel by hand, RBF similarity and gamma, Mercer's condition with eigenvalue checks, building new kernels, and a gamma–C grid search for SVC. Real in-browser scikit-learn runs on fictional fraud data, plus the representer theorem and string kernels.

এই পর্বে যা শিখবেন

  • Feature map দিয়ে ডেটা উঁচু মাত্রায় তুলে সরল সমতলে বাঁকা সীমানা পাওয়া, আর কেন dual-এ শুধু dot product লাগে
  • (x·z + 1)² হাতে খুলে স্পষ্ট feature বের করা, আর মাত্রা বাড়লে স্পষ্ট feature বনাম kernel-এর খরচ মাপা
  • RBF kernel-এর মান হাতে হিসাব, γ কী করে, আর scikit-learn-এর gamma="scale" কোথা থেকে আসে
  • Gram matrix কেন PSD হতে হয়, Mercer-এর শর্ত সহজ ভাষায়, eigenvalue দিয়ে যাচাই আর নতুন kernel বানানোর নিয়ম
  • SVC-তে linear, polynomial আর RBF তুলনা, γ–C grid-এ underfitting আর overfitting চেনা, আর representer theorem ও string kernel-এর ধারণা

পর্ব ২৭ (Support Vector Machine — margin, support vector আর hard margin) আর পর্ব ২৮ (Soft margin — hinge loss, C আর dual problem)-এ SVM একটি সরল রেখা বা সমতল টানে, যার দুই পাশে সবচেয়ে চওড়া ফাঁক। কিন্তু বাস্তবের অনেক ডেটা কোনো সরলরেখায় ভাগ হয় না। এই পর্বের প্রশ্ন: সরল সমতলের সব সুবিধা (convex সমস্যা, একটিই সেরা উত্তর, margin) রেখে কীভাবে বাঁকা সীমানা পাবেন? উত্তরের নাম kernel trick. এর গণিত আপনি আগেই আংশিক দেখেছেন: পর্ব ১০-এ Gram matrix PSD, পর্ব ১৬-এ Lagrange আর dual, আর পর্ব ২৩-এ RBF basis function. চালানো যায় এমন চারটি ব্লক পাতাতেই চলে (ব্রাউজারের Python, scikit-learn 1.8.0); প্রথমবার scikit-learn নামতে প্রায় দশ সেকেন্ড লাগে।

১ · সরলরেখা যেখানে হার মানে — feature map দিয়ে উঁচু মাত্রায় তোলা

বিছানায় একটি চাদর পাতা। মাঝখানে কয়েকটি নীল মার্বেল, চারপাশে গোল করে লাল মার্বেল। চাদরের ওপর একটি সোজা কাঠি রেখে নীল আর লাল আলাদা করতে পারবেন না: কাঠি যেদিকেই রাখুন, দুই পাশেই লাল থাকে। এবার চাদরের চারকোনা ধরে ওপরে তুলুন। মাঝখান নিচে ঝুলে পড়ে, নীল মার্বেল নিচে, লালগুলো ওপরে। এখন একটি সমান পাটাতন আড়াআড়ি ঢুকিয়ে দুই দল আলাদা করা যায়। পাটাতনটি সমতল, কিন্তু চাদরের ওপর তার ছাপ একটি বৃত্ত। Kernel পদ্ধতির পুরো ভাবনা এটুকুই।

গণিতের ভাষায়, একটি feature map φ প্রতিটি ইনপুট x-কে নতুন একটি vector φ(x)-এ নেয়, সাধারণত বেশি মাত্রায়। তারপর সেই নতুন জগতে সাধারণ linear model: f(x) = w·φ(x) + b. w-এর দিক থেকে model linear, তাই শেখানোর সব সুবিধা থাকে; কিন্তু x-এর দিক থেকে f বাঁকা। পর্ব ২৩-এর basis expansion ঠিক এই কাজ করেছিল; পার্থক্য আসবে অংশ ২-এ, যখন φ আর বানাতেই হবে না।

সবচেয়ে ছোট উদাহরণ এক মাত্রায়। নিচের ছবিতে সংখ্যারেখার মাঝখানে নীল, দুই প্রান্তে লাল। একটি বিন্দু (threshold) দিয়ে ভাগ অসম্ভব। কিন্তু φ(x) = (x, x²) নিলে প্রতিটি বিন্দু একটি parabola-র ওপর ওঠে, আর একটি অনুভূমিক রেখা x² = ১.৮ দুই দল আলাদা করে। মূল রেখায় তার মানে “|x| < ১.৩৪ হলে নীল”, অর্থাৎ দুটি threshold.

φ(x) = (x, x²): এক মাত্রায় অসম্ভব, দুই মাত্রায় একটি সরলরেখা

Lifting 1-D data with a feature map makes it linearly separable

Feature map x to (x, x squared) separates a 1-D pattern ১-মাত্রা: একটি threshold-এ ভাগ হয় না −3 0 3 φ(x) = (x, x²) x² = 1.8 অনুভূমিক: x · উল্লম্ব: x² ২-মাত্রা: একটি সরলরেখাই যথেষ্ট
ছবি ২৯.১ — সবুজ রেখা φ-এর জগতে সরল, কিন্তু মূল রেখায় তার মানে দুটি কাটা দাগ, x = −১.৩৪ আর x = ১.৩৪. নতুন মাত্রা x² “কেন্দ্র থেকে কত দূরে” মাপে, তাই কাজ করে।

দুই মাত্রার বিখ্যাত উদাহরণ XOR: (১, ১) আর (−১, −১) এক দল, (১, −১) আর (−১, ১) আরেক দল। কোনো সরলরেখা কাজ করে না, কিন্তু একটি নতুন feature x₁x₂ যোগ করলে প্রথম দলে x₁x₂ = ১, দ্বিতীয় দলে −১: একটি threshold-ই যথেষ্ট। Thomas Cover ১৯৬৫ সালে (IEEE Transactions on Electronic Computers) একটি গণনা দেন যার সারকথা: অনেক বেশি মাত্রায় এলোমেলো বিন্যাসের বিন্দুও সরলরেখায় ভাগ হওয়ার সম্ভাবনা বাড়ে। এর বিপদও আছে, যা অংশ ৬-এ দেখবেন: বেশি মাত্রায় সবকিছু ভাগ করা যায়, noise-ও।

বাজারঘরের সন্দেহজনক অর্ডার

এই পর্বের ডেটা কাল্পনিক, seed দিয়ে বানানো। বাজারঘরের প্রতিটি অর্ডারের দুটি সংখ্যা: x₁ = দামের বিচ্যুতি (গ্রাহকের সাধারণ অর্ডারের তুলনায়, standardize করা), x₂ = সময়ের বিচ্যুতি (তিনি সাধারণত যে সময়ে কেনেন তার তুলনায়)। সাধারণ অর্ডার (০) কেন্দ্রের কাছে জড়ো; প্রতারণার অর্ডার (১) কেন্দ্র থেকে দূরে, যেকোনো দিকে: অস্বাভাবিক বেশি বা কম দাম, রাত তিনটায় বা ভোরে। ফলে প্রতারণার অর্ডার একটি বলয় বানায়, যা কোনো সরলরেখা আলাদা করতে পারে না। ব্লক ১, ৩ আর ৪ এই module থেকে ডেটা নেয়।

# bazar_fraud.py — বাজারঘরের কাল্পনিক সন্দেহজনক অর্ডার (seed দিয়ে বানানো)
import numpy as np

def make_fraud(n=300, seed=29, spread=0.35):
    rng = np.random.default_rng(seed)
    y = (rng.random(n) < 0.4).astype(int)              # 1 = প্রতারণার অর্ডার
    r = np.where(y == 1, rng.normal(2.2, spread, n),   # প্রতারণা: স্বাভাবিক থেকে দূরে, যেকোনো দিকে
                 np.abs(rng.normal(0, 0.8, n)))        # সাধারণ: কেন্দ্রের কাছে
    angle = rng.uniform(0, 2 * np.pi, n)
    X = np.column_stack([r * np.cos(angle),            # x1: দামের বিচ্যুতি (z-score)
                         r * np.sin(angle)])           # x2: সময়ের বিচ্যুতি (z-score)
    return X, y

প্রথম ব্লক তিনটি model তুলনা করে: মূল দুই মাত্রায় linear SVM; φ(x) = (x₁, x₂, x₁² + x₂²) বানিয়ে তিন মাত্রায় linear SVM; আর φ না বানিয়ে SVC(kernel="rbf"). তারপর বাঁ দিকে মূল ডেটা, ডান দিকে “তোলা” ডেটা আঁকে।

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from bazar_fraud import make_fraud

X, y = make_fraud()
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0, stratify=y)
lift = lambda A: np.column_stack([A, (A ** 2).sum(axis=1)])   # φ(x) = (x1, x2, x1²+x2²)

flat = SVC(kernel="linear").fit(Xtr, ytr)                     # মূল ২-মাত্রায় সরলরেখা
lifted = SVC(kernel="linear").fit(lift(Xtr), ytr)             # ৩-মাত্রায় সমতল
rbf = SVC(kernel="rbf").fit(Xtr, ytr)                         # φ না বানিয়ে, kernel দিয়ে
print(f"orders: train {len(ytr)}, test {len(yte)}, fraud rate {y.mean():.2f}")
print(f"linear on (x1, x2)        test acc {flat.score(Xte, yte):.3f}")
print(f"linear on (x1, x2, r^2)   test acc {lifted.score(lift(Xte), yte):.3f}")
print(f"SVC rbf on (x1, x2)       test acc {rbf.score(Xte, yte):.3f}")
w, b = lifted.coef_[0], lifted.intercept_[0]
print(f"plane: {w[0]:+.3f} x1 {w[1]:+.3f} x2 {w[2]:+.3f} r^2 {b:+.3f} = 0")
print(f"boundary in x-space: circle r = {np.sqrt(-b / w[2]):.3f} (x1, x2 weights ~ 0)")

fig, ax = plt.subplots(1, 2, figsize=(9, 4))
for k, c in [(0, "tab:blue"), (1, "tab:red")]:
    m = y == k
    ax[0].scatter(X[m, 0], X[m, 1], s=10, c=c, label=["normal", "fraud"][k])
    ax[1].scatter(X[m, 0], (X[m] ** 2).sum(axis=1), s=10, c=c)
ax[0].add_patch(plt.Circle((0, 0), np.sqrt(-b / w[2]), fill=False, ls="--"))
ax[0].set(title="original space: no line works", xlabel="x1 (price deviation)",
          ylabel="x2 (time deviation)", aspect="equal")
ax[1].axhline(-b / w[2], color="k", ls="--", label="separating plane")
ax[1].set(title="lifted: r^2 = x1^2 + x2^2", xlabel="x1", ylabel="r^2")
ax[0].legend(fontsize=8); ax[1].legend(fontsize=8)

আসল আউটপুট (ব্রাউজারের Python), নিচে দুটি ছবি:

orders: train 210, test 90, fraud rate 0.43
linear on (x1, x2)        test acc 0.578
linear on (x1, x2, r^2)   test acc 0.989
SVC rbf on (x1, x2)       test acc 0.989
plane: -0.103 x1 -0.035 x2 +1.345 r^2 -3.010 = 0
boundary in x-space: circle r = 1.496 (x1, x2 weights ~ 0)

মূল জগতে linear SVM-এর accuracy ০.৫৭৮, প্রায় “সবাইকে সাধারণ বলা”-র সমান (প্রতারণার হার ০.৪৩)। একটিমাত্র নতুন feature r² = x₁² + x₂² যোগ করতেই ০.৯৮৯. শেখা সমতলে x₁ আর x₂-এর ওজন প্রায় শূন্য (−০.১০৩, −০.০৩৫), প্রায় সব ওজন r²-এ: model শিখেছে “কেন্দ্র থেকে দূরত্ব ১.৫-এর বেশি হলে সন্দেহ”. বাঁ ছবির ড্যাশ বৃত্তটিই সেই সমতলের ছাপ। আর RBF SVC কোনো φ না বানিয়েই একই ০.৯৮৯ পেয়েছে। কীভাবে, সেটিই পরের অংশ।

২ · Dual শুধু dot product চায় — kernel trick-এর মূল চাল

ব্লক ১-এ φ হাতে বানানো সহজ ছিল, কারণ আমরা জানতাম দূরত্বই আসল কথা। সাধারণভাবে জানা থাকে না, তাই অনেক feature একসঙ্গে চাই: সব দ্বিঘাত পদ, সব ত্রিঘাত পদ… মাত্রা দ্রুত বিস্ফোরিত হয়। এখানেই SVM-এর dual problem সাহায্য করে। পর্ব ২৮-এ soft-margin SVM-এর dual পুরো হিসাবসহ দেখেছেন; এখানে শুধু তার আকারটি দরকার (Lagrange আর dual-এর ভিত্তি পর্ব ১৬-এ):

সর্বোচ্চ করুন ∑i αi − ½ ∑i ∑j αi αj yi yj (xi · xj)
শর্ত: ০ ≤ αi ≤ C, ∑i αi yi = ০

অনুমান: f(x) = ∑i αi yi (xi · x) + b

এখানে αi প্রতিটি train বিন্দুর Lagrange multiplier, yi তার শ্রেণি (+১ বা −১), C হলো ভুলের শাস্তির মাপ, আর b সমতলের সরণ। যেসব বিন্দুর αi > ০, তারাই support vector; বাকিরা অনুমানে কোনো ভূমিকা রাখে না।

লক্ষ করুন: শেখা আর অনুমান, দুই জায়গাতেই ডেটা ঢোকে শুধু জোড়ায় জোড়ায় dot product হিসেবে, কোথাও আলাদা করে xi-এর কোনো স্থানাঙ্ক লাগে না। তাই φ-এর জগতে কাজ করতে চাইলে xi·xj-এর জায়গায় φ(xi)·φ(xj) বসালেই হলো। এখন যদি এমন একটি function k পাওয়া যায় যে

k(x, z) = φ(x) · φ(z)

আর k সরাসরি x আর z থেকে সস্তায় হিসাব করা যায়, তবে φ কখনো বানাতে হয় না। এই k-ই kernel, আর বদলটিই kernel trick. শেখার সময় লাগে সব জোড়ার kernel মান, একটি n × n টেবিল Kij = k(xi, xj), যার নাম Gram matrix বা kernel matrix. অনুমানে লাগে নতুন x আর প্রতিটি support vector-এর kernel মান।

ইতিহাস: ধারণাটি SVM-এর চেয়ে পুরোনো। মস্কোর Mark Aizerman, Emmanuel Braverman আর Lev Rozonoer ১৯৬৪ সালে “potential function” পদ্ধতিতে perceptron-কে একটি feature space-এ dot product হিসেবে ব্যাখ্যা করেন। Bernhard Boser, Isabelle Guyon আর Vladimir Vapnik ১৯৯২ সালের COLT সম্মেলনে এই কৌশল maximum-margin classifier-এ বসান; Corinna Cortes আর Vapnik ১৯৯৫ সালে soft margin যোগ করেন। গাণিতিক ভিত্তি আরও পুরোনো: James Mercer-এর ১৯০৯ সালের integral equation-এর প্রবন্ধ আর Nachman Aronszajn-এর ১৯৫০ সালের reproducing kernel-এর তত্ত্ব।

একটি সূক্ষ্ম বিষয়: kernel SVM-এ w = ∑αiyiφ(xi) কখনো হাতে আসে না, কারণ φ নেই। তাই linear kernel ছাড়া scikit-learn-এর SVC-তে coef_ পাওয়া যায় না; আছে dual_coef_ (αiyi), support_vectors_ আর intercept_. অনুমানের খরচ তাই support vector-এর সংখ্যার সমানুপাতিক।

৩ · Polynomial kernel হাতে খুলে দেখা

সবচেয়ে সহজে যাচাইযোগ্য kernel হলো polynomial kernel: k(x, z) = (x·z + 1)². দাবি: এটি কোনো একটি φ-এর dot product. দুই মাত্রার দুটি vector নিয়ে হাতে খুলে দেখুন:

দুই মাত্রার polynomial kernel, degree 2φ খুঁজে বের করা

            
  1. Kernel-এর পথ। সরাসরি হিসাব: x·z = ৫, তার সঙ্গে ১ যোগ করে বর্গ, ফল ৩৬. কোনো নতুন feature বানানো হয়নি।
  2. বীজগণিতে খোলা। (a + b + ১)² খুললে ছয়টি পদ: দুটি বর্গ, একটি গুণফল-পদ, দুটি রৈখিক পদ আর ধ্রুবক ১.
  3. φ পড়ে নেওয়া। প্রতিটি পদকে “x-এর একটি অংশ × z-এর একই অংশ” হিসেবে লিখলে φ বেরিয়ে আসে। √2 আসে কারণ ২-কে দুই পাশে ভাগ করতে হয়।
  4. দুটি φ. x = (১, ২) আর z = (৩, ১) বসিয়ে দুটি ছয়-মাত্রার vector.
  5. যাচাই। ছয়টি গুণফলের যোগ ১ + ৬ + ৪ + ৯ + ৪ + ১২ = ৩৬, kernel-এর মানের হুবহু সমান। তাই (x·z + ১)² সত্যিই একটি dot product.
  6. খরচের পার্থক্য। ১০০টি feature আর degree ৪ হলে স্পষ্ট φ-এ প্রায় ৪৬ লাখ কলাম; kernel-এ শুধু ১০০টি গুণ আর একটি ঘাত।

সাধারণ রূপে scikit-learn লেখে k(x, z) = (γ·x·z + r)d, যেখানে d = degree, r = coef0, γ = gamma. r > ০ হলে φ-এ শূন্য থেকে d পর্যন্ত সব ঘাতের পদ থাকে; r = ০ হলে শুধু ঠিক d ঘাতের পদ (homogeneous). মনে রাখার বিষয়: SVC(kernel="poly")-এ ডিফল্ট coef0=0 আর degree=3, তাই ডিফল্ট poly kernel-এ রৈখিক আর দ্বিঘাত পদ নেই। নিচের ব্লক দুটি কাজ করে: হাতের হিসাবটি সংখ্যায় মেলায় (২০০টি বিন্দুর পুরো Gram matrix-সহ), তারপর ২০০টি অর্ডার আর ২০টি feature-এ স্পষ্ট feature বনাম kernel-এর আকার আর সময় মাপে।

import time
import numpy as np
from sklearn.metrics.pairwise import polynomial_kernel
from sklearn.preprocessing import PolynomialFeatures

def phi(v):                                   # (x·z + 1)²-এর ৬টি স্পষ্ট feature
    a, b = v
    r2 = np.sqrt(2)
    return np.array([1, r2 * a, r2 * b, a * a, b * b, r2 * a * b])

x, z = np.array([1.0, 2.0]), np.array([3.0, 1.0])
print("kernel (x.z + 1)^2 =", (x @ z + 1) ** 2)
print("phi(x) . phi(z)    =", round(phi(x) @ phi(z), 10))
rng = np.random.default_rng(29)
X2 = rng.normal(size=(200, 2))
K = polynomial_kernel(X2, degree=2, gamma=1, coef0=1)
P = np.array([phi(v) for v in X2])
print("200 x 200 Gram, max |K - P P^T| =", f"{np.abs(K - P @ P.T).max():.1e}")

def best_ms(f):                               # ৩ বার চালিয়ে সবচেয়ে কম সময়
    out = []
    for _ in range(3):
        t = time.perf_counter(); f(); out.append(time.perf_counter() - t)
    return 1000 * min(out)

X = rng.normal(size=(200, 20))                # ২০০টি অর্ডার, ২০টি feature
print("\ndegree  features  feature MB  explicit ms  kernel ms")
for p in (2, 3, 4):
    F = PolynomialFeatures(degree=p).fit_transform(X)
    t_exp = best_ms(lambda: PolynomialFeatures(degree=p).fit_transform(X) @ F.T)
    t_ker = best_ms(lambda: polynomial_kernel(X, degree=p, gamma=1, coef0=1))
    print(f"{p:6d}  {F.shape[1]:8d}  {F.nbytes / 1e6:10.1f}  {t_exp:11.1f}  {t_ker:9.1f}")

আসল আউটপুট (ব্রাউজারের Python; সময়ের সংখ্যা যন্ত্র আর run ভেদে বদলাবে):

kernel (x.z + 1)^2 = 36.0
phi(x) . phi(z)    = 36.0
200 x 200 Gram, max |K - P P^T| = 2.8e-14

degree  features  feature MB  explicit ms  kernel ms
     2       231         0.4          8.6        1.2
     3      1771         2.8         62.9        2.6
     4     10626         17.0        401.3        2.5

হাতের ৩৬ মিলেছে, আর ২০০ × ২০০ = ৪০,০০০টি ঘরের সবচেয়ে বড় পার্থক্য ২.৮ × ১০⁻¹⁴, শুধু floating-point-এর গোলমাল। নিচের টেবিলে কলামের সংখ্যা C(২০ + p, p): ২৩১, ১,৭৭১, ১০,৬২৬. স্পষ্ট feature-এর মেমরি ০.৪ থেকে ১৭ MB-তে লাফায়, আর সময় ৮.৬ থেকে প্রায় ৪০০ ms; kernel-এর সময় ১ থেকে ৩ ms-এর মধ্যেই থাকে, কারণ সে শুধু ২০০ × ২০০ টেবিল বানায় (আমাদের বিন্দুর সংখ্যার ওপর নির্ভর, feature-এর সংখ্যার ওপর প্রায় নয়)। একটি সতর্কতা: PolynomialFeatures-এর কলামে √2-এর মতো ওজন নেই, তাই degree ৩ আর ৪-এ তার dot product kernel-এর মানের সমান নয়; এখানে তুলনা শুধু কাজের পরিমাণের। Kernel-এর নিজের দামও আছে: n × n টেবিল, যা n বড় হলে সমস্যা। সেই গল্প পর্ব ৩১ (বড় ডেটায় kernel — Nyström, random features আর কখন SVM নয়)-এ।

৪ · RBF kernel আর γ — মিল মানে কাছাকাছি থাকা

মহল্লার চায়ের দোকানে খবর ছড়ায় দূরত্ব মেনে: পাশের বাড়ি পুরো খবর পায়, দুই গলি দূরে আধাআধি, পাশের পাড়ায় প্রায় কিছুই না। খবর কত দূর যাবে, তা নির্ভর করে লোকটি কতটা জোরে বলেন। RBF kernel ঠিক এভাবে মিল মাপে, আর γ ঠিক করে “গলা কতটা নিচু”: γ বড় মানে খবর শুধু একেবারে পাশের বাড়িতে।

সবচেয়ে জনপ্রিয় kernel হলো RBF kernel (Gaussian kernel নামেও পরিচিত):

k(x, z) = exp(−γ ‖x − z‖²),   γ > ০

‖x − z‖² হলো দুই বিন্দুর দূরত্বের বর্গ। একই বিন্দুতে k = ১, দূরে গেলে মান শূন্যের দিকে নামে। তাই RBF আসলে “কতটা কাছে” মাপে, AI-এর ভিত্তি কোর্সের পর্ব ৫৭-এর k-NN-এর মতো দূরত্বের ভাবনা। পার্থক্য: k-NN কাছের কয়েকজনের ভোট নেয়, RBF SVM সব support vector-এর ওজনযুক্ত মিল যোগ করে: f(x) = ∑αiyi·exp(−γ‖xi − x‖²) + b. প্রতিটি support vector-এর চারপাশে একটি ঘণ্টার মতো ঢিবি; পর্ব ২৩-এর radial basis function যেমন, তফাত শুধু এই যে কেন্দ্রগুলো এখানে ডেটার বিন্দু নিজেই, আর কোনগুলো থাকবে তা SVM ঠিক করে।

k(x, z) = exp(−γ‖x − z‖²)γ বদলালে কী হয়

            
  1. দূরত্ব। পার্থক্য (−১, ২), দূরত্বের বর্গ ৫. RBF-এর সব হিসাব এই একটি সংখ্যা থেকে।
  2. γ = ০.১. exp(−০.৫) ≈ ০.৬০৬৫: পাঁচ একক বর্গ-দূরত্বেও মিল ৬০% এর বেশি। প্রভাবের এলাকা চওড়া।
  3. γ = ১. exp(−৫) ≈ ০.০০৬৭৪: একই জোড়া এখন প্রায় অচেনা।
  4. γ = ১০. exp(−৫০) ≈ ১.৯ × ১০⁻²², কার্যত শূন্য। প্রতিটি বিন্দুর প্রভাব একটি ছোট্ট বৃত্তে।
  5. দুই চরম। নিজের সঙ্গে মিল সবসময় ১. γ খুব বড় হলে Gram matrix প্রায় একক matrix: model প্রতিটি train বিন্দুর চারপাশে আলাদা দ্বীপ আঁকে। γ খুব ছোট হলে সব মিল প্রায় ১, model প্রায় সরল সীমানায় নামে।
  6. ডিফল্ট γ. scikit-learn-এর gamma='scale' হলো ১/(feature সংখ্যা × X-এর সব মানের variance). Standardize করা দুটি feature-এ γ = ০.৫, আর এই জোড়ায় মিল ≈ ০.০৮২১.

অসীম মাত্রার feature space — কেন বলা হয়

RBF-এর φ কেমন? ধরুন এক মাত্রায় x আর z. exp(−γ(x − z)²) = exp(−γx²) · exp(−γz²) · exp(২γxz). শেষ অংশটি Taylor series-এ খুললে ∑n (২γ)n xn zn / n!, অর্থাৎ সব ঘাতের polynomial পদ, প্রতিটি ওজনসহ। তাই φ(x)-এর অসীমসংখ্যক উপাদান: exp(−γx²)·√((২γ)n/n!)·xn, n = ০, ১, ২, … . কোনো কম্পিউটার এই φ বানাতে পারে না, কিন্তু kernel-এর মান একটি exp. এজন্যই বলা হয় RBF-এর feature space অসীম মাত্রার। এর একটি পরিণতি (Ingo Steinwart ২০০১ সালে এই ধরনের kernel-কে “universal” বলে প্রমাণ দেন, নির্দিষ্ট শর্তে): যথেষ্ট ডেটা আর ঠিক γ হলে RBF প্রায় যেকোনো মসৃণ সীমানার কাছাকাছি যেতে পারে। একই কারণে সাবধানতা: সে noise-এর চারপাশেও সীমানা আঁকতে পারে।

Scaling ছাড়া RBF বিপজ্জনক। RBF দূরত্বের ওপর চলে, তাই একটি feature টাকায় (হাজারের ঘরে) আর আরেকটি দিনে (একের ঘরে) মাপা হলে দূরত্বে প্রায় শুধু টাকাই থাকে। SVC-এর আগে StandardScaler দিন, আর তা Pipeline-এর ভেতরে, যাতে cross-validation-এ scaling-এর হিসাব শুধু train ভাগ থেকে আসে (AI-এর ভিত্তি কোর্সের পর্ব ৬৪)। এই পর্বের ডেটা আগে থেকেই z-score, তাই ব্লকগুলোতে scaler নেই।

৫ · Mercer-এর শর্ত — কোন “মিল” সত্যিই kernel

এবার উল্টো প্রশ্ন। যেকোনো “মিল”-এর function লিখে SVC-তে দিলেই কি চলবে? না। k(x, z) = φ(x)·φ(z) হলে Gram matrix K = ΦΦᵀ, যেখানে Φ-এর সারিগুলো φ(xi). পর্ব ১০-এ দেখেছেন, এমন matrix সবসময় positive semidefinite (PSD): যেকোনো c-এর জন্য cᵀKc = ‖Φᵀc‖² ≥ ০. তিনটি কারণে এই শর্ত অপরিহার্য:

  • জ্যামিতি: φ-এর জগতে দূরত্বের বর্গ ‖φ(x) − φ(z)‖² = k(x, x) + k(z, z) − ২k(x, z). PSD না হলে কোনো জোড়ায় এটি ঋণাত্মক হতে পারে, যা অসম্ভব দূরত্ব।
  • Optimization: Dual-এর দ্বিঘাত অংশ αᵀ(yyᵀ ∘ K)α (∘ মানে ঘরে ঘরে গুণ)। K PSD হলে সমস্যাটি convex, একটিই সেরা উত্তর (পর্ব ১২)। না হলে solver আটকে যেতে পারে বা যেকোনো একটি উত্তর দেয়।
  • Margin: ‖w‖² = αᵀ(yyᵀ ∘ K)α. PSD না হলে “margin”-এর বর্গ ঋণাত্মক হওয়া সম্ভব, তখন পুরো ধারণাটিই ভাঙে।
Mercer-এর শর্ত, সহজ ভাষায়

একটি প্রতিসম function k(x, z) = k(z, x) তখনই কোনো একটি φ-এর dot product (Mercer-এর শর্ত) (অর্থাৎ বৈধ kernel), যখন যেকোনো সংখ্যক যেকোনো বিন্দু নিলে তাদের Gram matrix PSD হয়। একে positive definite kernel-ও বলে। James Mercer ১৯০৯ সালে এর integral-এর রূপ দেন (একটি সীমাবদ্ধ এলাকায় ∫∫ k(x, z) g(x) g(z) dx dz ≥ ০ সব g-এর জন্য), যা থেকে k = ∑λiψi(x)ψi(z) আকারের ভাঙন আসে। ব্যবহারিক কাজে finite সেটের সংস্করণটিই যথেষ্ট, তবে মনে রাখবেন: কয়েকটি সেটে PSD দেখা প্রমাণ নয়, একটি সেটে PSD না হওয়াই অবৈধতার প্রমাণ।

২ × ২ matrix-এ যাচাই খুব সহজ, তাই পরীক্ষায় প্রায়ই আসে। নিচে একটি বৈধ kernel আর একটি অবৈধ “মিল”:

প্রতিসম K = [a b; b c]PSD ⇔ a ≥ 0, c ≥ 0, ac − b² ≥ 0

            
  1. নিয়ম। ২ × ২ প্রতিসম matrix PSD হয় যদি দুটি কর্ণের ঘর অঋণাত্মক আর determinant অঋণাত্মক হয়। এটি দুটি eigenvalue অঋণাত্মক হওয়ার সমান কথা।
  2. RBF matrix. দুটি বিন্দুর দূরত্বের বর্গ ২, γ = ০.৫, তাই বাইরের ঘর e−১ ≈ ০.৩৬৭৯; কর্ণে ১.
  3. RBF যাচাই। det ≈ ০.৮৬৪৭, eigenvalue ১ ± ০.৩৬৭৯, দুটিই ধনাত্মক। RBF-এ বাইরের ঘর সবসময় ০ আর ১-এর মাঝে, তাই এই জোড়ায় কখনো ব্যর্থ হয় না।
  4. tanh “মিল”. Neural network-এর activation থেকে আসা tanh(x·z − ১), যা scikit-learn-এ kernel="sigmoid" নামে আছে; একে sigmoid kernel বলে। দুটি এক-মাত্রার বিন্দুতে তিনটি মান।
  5. ব্যর্থতা। det ≈ −০.৫৮০০, ঋণাত্মক; একটি eigenvalue −০.৪১২২. মাত্র দুটি বিন্দুতেই PSD ভেঙেছে, তাই এই প্যারামিটারে এটি বৈধ kernel নয়।
  6. অর্থ। v = (১, −১) দিলে vᵀSv ≈ −০.৫২৮১. Kernel হলে এটিই φ-এর জগতে দুই বিন্দুর দূরত্বের বর্গ হতো; ঋণাত্মক দূরত্ব হয় না, তাই এমন φ থাকতেই পারে না।

নতুন kernel বানানোর নিয়ম

প্রতিবার Mercer প্রমাণ না করে, জানা kernel থেকে নতুন kernel বানানো যায়। k₁ আর k₂ বৈধ হলে নিচেরগুলোও বৈধ:

নিয়মকেন PSD থাকেব্যবহার
c · k₁, যেখানে c > ০সব eigenvalue c গুণমাপ বদলানো
k₁ + k₂cᵀ(K₁ + K₂)c = cᵀK₁c + cᵀK₂c ≥ ০; φ দুটি পাশাপাশি জোড়াদুই ধরনের মিল একসঙ্গে
k₁ · k₂ (ঘরে ঘরে গুণ)Schur product theorem; φ হলো দুই φ-এর সব জোড়ার গুণফল“দুটিতেই মিল” চাইলে
f(x) k₁(x, z) f(z)Φ-এর প্রতিটি সারি f(x) দিয়ে গুণওজন দেওয়া
exp(k₁), ধনাত্মক সহগের polynomial(k₁)যোগ আর গুণের সীমাRBF আর poly এভাবেই আসে
k₁ − k₂ ✗সাধারণত PSD থাকে নাএড়িয়ে চলুন

নিচের ব্লক বাজারঘরের ৪০টি অর্ডারে তিনটি পরিচিত kernel, দুটি অবৈধ “মিল” (ঋণাত্মক দূরত্ব আর tanh), আর যোগ, গুণ, গুণিতক ও বিয়োগে বানানো kernel-এর সবচেয়ে ছোট eigenvalue দেখে। প্রতিসম matrix-এর জন্য scipy.linalg.eigh ব্যবহার করা হয়েছে, যা eigenvalue ছোট থেকে বড় ক্রমে দেয়।

import numpy as np
from scipy.linalg import eigh
from sklearn.metrics.pairwise import (euclidean_distances, linear_kernel,
                                      polynomial_kernel, rbf_kernel, sigmoid_kernel)
from bazar_fraud import make_fraud

X, _ = make_fraud(n=40)                       # ৪০টি অর্ডার, ২টি feature

def check(name, K):                           # প্রতিসম? সবচেয়ে ছোট eigenvalue কত?
    lam = eigh(K, eigvals_only=True)          # ছোট থেকে বড় ক্রমে
    sym = np.allclose(K, K.T)
    verdict = "PSD" if lam[0] > -1e-9 * lam[-1] else "NOT PSD"
    print(f"{name:22s} symmetric={sym}  min eig {lam[0]:+.2e}  {verdict}")

K_lin = linear_kernel(X)
K_poly = polynomial_kernel(X, degree=3, gamma=1, coef0=1)
K_rbf = rbf_kernel(X, gamma=0.5)
check("linear  x.z", K_lin)
check("poly    (x.z + 1)^3", K_poly)
check("rbf     gamma=0.5", K_rbf)
print("-- not kernels --")
check("minus distance", -euclidean_distances(X))
check("tanh(2 x.z - 1)", sigmoid_kernel(X, gamma=2, coef0=-1))
print("-- building new kernels --")
check("rbf + poly", K_rbf + K_poly)
check("rbf * linear (entry)", K_rbf * K_lin)
check("3 * rbf", 3 * K_rbf)
check("rbf - poly", K_rbf - K_poly)
print("rank of linear Gram:", np.linalg.matrix_rank(K_lin), "of", len(X))

আসল আউটপুট (ব্রাউজারের Python):

linear  x.z            symmetric=True  min eig -1.63e-14  PSD
poly    (x.z + 1)^3    symmetric=True  min eig -5.79e-13  PSD
rbf     gamma=0.5      symmetric=True  min eig +6.50e-10  PSD
-- not kernels --
minus distance         symmetric=True  min eig -8.58e+01  NOT PSD
tanh(2 x.z - 1)        symmetric=True  min eig -1.79e+01  NOT PSD
-- building new kernels --
rbf + poly             symmetric=True  min eig +7.41e-10  PSD
rbf * linear (entry)   symmetric=True  min eig +6.31e-10  PSD
3 * rbf                symmetric=True  min eig +1.95e-09  PSD
rbf - poly             symmetric=True  min eig -1.82e+03  NOT PSD
rank of linear Gram: 2 of 40

ছোট ঋণাত্মক সংখ্যা ভুল নয়। Linear kernel-এর সবচেয়ে ছোট eigenvalue −১.৬৩ × ১০⁻¹⁴: গণিতে শূন্য, কম্পিউটারে গোলমাল। কারণ: ৪০ × ৪০ linear Gram matrix-এর rank মাত্র ২, কারণ ডেটা দুই মাত্রার, তাই ৩৮টি eigenvalue আসলে শূন্য। এজন্য যাচাইয়ে একটি সহনশীলতা লাগে (এখানে সবচেয়ে বড় eigenvalue-এর ১০⁻⁹ গুণ)। অবৈধ “মিল” দুটি বড় ব্যবধানে ব্যর্থ: ঋণাত্মক দূরত্বের কর্ণ পুরো শূন্য, তাই eigenvalue-এর যোগফল (trace) শূন্য, কিছু ঋণাত্মক হতেই হবে; tanh-এর −১৭.৯. যোগ, ঘরে ঘরে গুণ আর ৩ গুণ PSD রেখেছে, যেমন টেবিল বলেছিল; বিয়োগ ভেঙেছে, −১,৮২০. লক্ষ করুন, RBF × linear-এর মতো kernel-এ linear অংশের rank ২ হলেও গুণফলের matrix আর নিম্ন-rank নয়।

৬ · বাজারঘরের ডেটায় তিন kernel আর γ–C-এর ছক

এবার একটু কঠিন ডেটা: একই কাল্পনিক বাজারঘর, কিন্তু প্রতারণার বলয় চওড়া (spread=0.7), তাই কিছু প্রতারণা সাধারণ অর্ডারের মধ্যে ঢুকে পড়েছে। নিচের ব্লক পাঁচটি SVC-র decision boundary আঁকে (linear, degree ২-এর poly, আর তিনটি γ-তে RBF), তারপর RBF-এর জন্য γ আর C-এর ৬ × ৬ grid search চালায়, ৫-fold cross-validation-এ, শুধু train ভাগে (AI-এর ভিত্তি কোর্সের পর্ব ৬৬)। C ছোট মানে ভুলের শাস্তি কম, তাই চওড়া margin আর সরল সীমানা; C বড় মানে প্রায় প্রতিটি train বিন্দু ঠিক করার চেষ্টা।

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.svm import SVC
from bazar_fraud import make_fraud

X, y = make_fraud(n=300, seed=7, spread=0.7)          # এবার দুই দল খানিকটা মেশানো
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, random_state=0, stratify=y)
g = np.linspace(-3.5, 3.5, 150)
xx, yy = np.meshgrid(g, g)
grid_pts = np.c_[xx.ravel(), yy.ravel()]
models = {"linear": SVC(kernel="linear"), "poly d=2": SVC(kernel="poly", degree=2, coef0=1),
          "rbf gamma=0.01": SVC(gamma=0.01), "rbf gamma=1": SVC(gamma=1), "rbf gamma=100": SVC(gamma=100)}
fig, axes = plt.subplots(2, 3, figsize=(11, 7))
for ax, (name, m) in zip(axes.ravel(), models.items()):
    m.fit(Xtr, ytr)
    ax.contourf(xx, yy, m.decision_function(grid_pts).reshape(xx.shape) > 0, alpha=0.25, cmap="coolwarm")
    ax.scatter(Xtr[:, 0], Xtr[:, 1], c=ytr, s=6, cmap="coolwarm")
    ax.set_title(f"{name}: train {m.score(Xtr, ytr):.2f}, test {m.score(Xte, yte):.2f}", fontsize=9)
    print(f"{name:14s} train {m.score(Xtr, ytr):.3f}  test {m.score(Xte, yte):.3f}  SV {m.n_support_.sum()}")

gammas, Cs = np.logspace(-2, 3, 6), np.logspace(-2, 3, 6)
gs = GridSearchCV(SVC(kernel="rbf"), {"gamma": gammas, "C": Cs}, cv=5).fit(Xtr, ytr)
S = gs.cv_results_["mean_test_score"].reshape(len(Cs), len(gammas))   # সারি = C, কলাম = gamma
ax = axes[1, 2]
im = ax.imshow(S, origin="lower", cmap="viridis", vmin=0.5, vmax=1)
ax.set(xticks=range(6), xticklabels=[f"{v:g}" for v in gammas], yticks=range(6),
       yticklabels=[f"{v:g}" for v in Cs], xlabel="gamma", ylabel="C", title="5-fold CV accuracy")
fig.colorbar(im, ax=ax); fig.subplots_adjust(wspace=0.35, hspace=0.35)
best = {k: float(v) for k, v in gs.best_params_.items()}
print("best", best, f"CV {gs.best_score_:.3f}  test {gs.score(Xte, yte):.3f}")
print("CV rows=C, cols=gamma:\n", np.round(S, 2))

আসল আউটপুট (ব্রাউজারের Python), নিচে পাঁচটি সীমানা আর একটি heatmap:

linear         train 0.600  test 0.600  SV 171
poly d=2       train 0.886  test 0.956  SV 66
rbf gamma=0.01 train 0.610  test 0.611  SV 168
rbf gamma=1    train 0.914  test 0.878  SV 78
rbf gamma=100  train 0.995  test 0.856  SV 189
best {'C': 0.1, 'gamma': 1.0} CV 0.876  test 0.878
CV rows=C, cols=gamma:
 [[0.6  0.6  0.6  0.6  0.6  0.6 ]
 [0.6  0.78 0.88 0.6  0.6  0.6 ]
 [0.6  0.83 0.86 0.87 0.83 0.6 ]
 [0.8  0.86 0.84 0.86 0.84 0.59]
 [0.84 0.84 0.81 0.87 0.84 0.59]
 [0.85 0.83 0.84 0.87 0.84 0.59]]

সীমানা। Linear SVM পুরো ছবিকে “সাধারণ” রঙে রাঙিয়েছে: train আর test দুই জায়গাতেই ০.৬০০, যা ঠিক সাধারণ অর্ডারের অনুপাত, আর ২১০টির ১৭১টি support vector. RBF γ = ০.০১-ও প্রায় একই (০.৬১০): প্রভাব এত চওড়া যে সীমানা প্রায় সরল, ক্লাসিক underfitting. γ = ১ একটি মসৃণ গোল দাগ আঁকে, test ০.৮৭৮. γ = ১০০ train-এ ০.৯৯৫ কিন্তু test-এ ০.৮৫৬, আর support vector ১৮৯টি: প্রায় প্রতিটি বিন্দু নিজেই একটি ছোট দ্বীপ, এটি overfitting.

Heatmap. সারি C (নিচে ০.০১), কলাম γ (বাঁয়ে ০.০১)। নিচের সারি পুরো ০.৬: C = ০.০১-এ শাস্তি এত কম যে model শুধু বড় দলটিই বলে। ডান কলাম ০.৫৯–০.৬: γ = ১০০০-এ প্রতিটি বিন্দু একা, নতুন বিন্দুর সঙ্গে কোনো মিল নেই। ভালো অঞ্চলটি একটি তির্যক ফিতা: γ বাড়ালে সাধারণত C কম লাগে আর উল্টোটাও, কারণ দুটিই নমনীয়তা বাড়ায়। সেরা (C = ০.১, γ = ১) ফিতার ভেতরে, কিনারায় নয়; কিনারায় হলে grid চওড়া করতে হতো। শিক্ষণীয় চমক: degree ২-এর poly test-এ ০.৯৫৬, সেরা RBF-এর চেয়ে ভালো। কারণ সত্যিকারের সীমানা একটি বৃত্ত, যা ঠিক দ্বিঘাত: ডেটার আকার সম্পর্কে সঠিক অনুমান সবচেয়ে নমনীয় kernel-কেও হারাতে পারে। তবে ৯০টি test অর্ডার আর একটি split; সিদ্ধান্তের আগে কয়েকটি seed আর fold-এ দেখুন (পর্ব ২২)।

Chih-Wei Hsu, Chih-Chung Chang আর Chih-Jen Lin (LIBSVM-এর লেখকরা) তাঁদের বহুল ব্যবহৃত “A Practical Guide to Support Vector Classification” নির্দেশিকায় ঠিক এই ক্রম সুপারিশ করেন: feature scale করুন, প্রথমে RBF চেষ্টা করুন, C আর γ সূচকীয় ধাপে (যেমন C-এর জন্য ২−৫ থেকে ২১৫, γ-এর জন্য ২−১৫ থেকে ২৩) cross-validation-এ খুঁজুন, তারপর সেরার চারপাশে সূক্ষ্ম grid. Feature অনেক বেশি হলে (যেমন লেখার শব্দ) linear kernel প্রায়ই সমান ভালো আর অনেক দ্রুত।

৭ · Representer theorem আর vector ছাড়া ডেটার kernel

অংশ ২-এ দেখেছেন, SVM-এর উত্তর f(x) = ∑αiyik(xi, x) + b, অর্থাৎ train বিন্দুগুলোর kernel-এর একটি ওজনযুক্ত যোগফল। এটি SVM-এর কাকতালীয় গুণ নয়। Representer theorem বলে: যদি loss শুধু train বিন্দুতে f-এর মানের ওপর নির্ভর করে, আর তার সঙ্গে ‖f‖²-এর মতো একটি বাড়ন্ত regularization শাস্তি থাকে, তবে kernel-এর feature space-এ সেরা f সবসময় f(x) = ∑i ci k(xi, x) আকারের। George Kimeldorf আর Grace Wahba ১৯৭১ সালে spline-এর প্রসঙ্গে এর একটি রূপ দেন; Bernhard Schölkopf, Ralf Herbrich আর Alex Smola ২০০১ সালে সাধারণ রূপটি প্রকাশ করেন।

এর মানে বিশাল: অসীম মাত্রার জগতেও খুঁজতে হয় শুধু n টি সংখ্যা c1 … cn. Hinge loss দিলে SVM (অনেক c শূন্য, তাই sparse); বর্গ-ভুল দিলে kernel ridge regression, যার উত্তর c = (K + λI)⁻¹y একটি linear system থেকে আসে (পর্ব ৩০, SVR আর kernel ridge regression); PCA-তে বসালে kernel PCA (পর্ব ৪১); আর Gaussian process-এর গড় অনুমানও একই আকারের (পর্ব ৪৬)। পর্ব ১৭-এর ridge-এর সঙ্গে সম্পর্কও এখানেই।

যেখানে vector-ই নেই — string আর graph kernel

Kernel trick-এর একটি কম আলোচিত শক্তি: ডেটা সংখ্যার vector না হলেও চলে, শুধু দুটি বস্তুর মধ্যে একটি বৈধ মিলের function লাগে। বাজারঘরের পণ্যের বর্ণনা ধরুন, যেমন “সুতি শাড়ি লাল” আর “লাল সুতি থ্রি-পিস”. একটি সহজ string kernel: দুটি লেখায় সাধারণ অক্ষর-ত্রয়ী (character 3-gram) কতবার আছে, তার গণনার dot product. এটি বৈধ, কারণ φ হলো “প্রতিটি সম্ভাব্য ৩-অক্ষরের টুকরো কতবার আছে” তার vector; তবে kernel সেই বিশাল vector না বানিয়ে শুধু দুটি লেখার মিলে যাওয়া টুকরো গোনে। David Haussler ১৯৯৯ সালে গঠনযুক্ত ডেটার জন্য convolution kernel-এর কাঠামো দেন, আর Huma Lodhi ও সহকর্মীরা ২০০২ সালে (JMLR) ফাঁক রেখে মেলানো subsequence kernel দিয়ে লেখার শ্রেণিবিভাগ দেখান। Protein-এর ক্রম আর অণুর graph-এর জন্যও এমন kernel আছে। scikit-learn-এ SVC(kernel="precomputed")-এ নিজের Gram matrix দেওয়া যায়, শুধু তখন PSD-এর দায় আপনার।

আরও গভীরে: প্রতিটি বৈধ kernel একটি নির্দিষ্ট function-এর জগৎ ঠিক করে, যার নাম reproducing kernel Hilbert space (RKHS); Aronszajn ১৯৫০ সালে দেখান kernel আর এই জগৎ এক-এক মেলে (Moore–Aronszajn theorem). এই জগতের norm ‖f‖ মাপে f কতটা “অমসৃণ”, আর SVM-এর ½‖w‖² আসলে এই norm. Bernhard Schölkopf আর Alex Smola-র ২০০২ সালের বই Learning with Kernels পুরো তত্ত্বের মানক সূত্র। একটি আধুনিক যোগসূত্র: Arthur Jacot, Franck Gabriel আর Clément Hongler ২০১৮ সালে (NeurIPS) দেখান, অসীম চওড়া neural network-এর প্রশিক্ষণ একটি নির্দিষ্ট kernel (neural tangent kernel) দিয়ে বর্ণনা করা যায়।

পরীক্ষা ও ইন্টারভিউতে:

  • Kernel trick এক বাক্যে? যে algorithm শুধু dot product ব্যবহার করে, সেখানে x·z-এর বদলে k(x, z) = φ(x)·φ(z) বসিয়ে φ না বানিয়েই উঁচু মাত্রায় linear model শেখা।
  • (x·z + ১)² দুই মাত্রায় খুলুন। φ(x) = (১, √২x₁, √২x₂, x₁², x₂², √২x₁x₂); ছয়টি feature.
  • γ বাড়ালে RBF SVM-এ কী হয়? প্রতিটি বিন্দুর প্রভাব ছোট এলাকায়, সীমানা আঁকাবাঁকা, support vector বাড়ে, overfitting-এর ঝুঁকি।
  • একটি function kernel কি না কীভাবে বুঝবেন? প্রতিসম আর সব finite সেটে Gram matrix PSD (Mercer); বা জানা kernel থেকে যোগ, গুণ, ধনাত্মক গুণিতকে বানানো। একটি সেটে ঋণাত্মক eigenvalue পেলেই অবৈধ।
  • Representer theorem কী বলে? Regularized loss-এর সেরা f = ∑cik(xi, x), তাই অসীম মাত্রাতেও শুধু n টি সহগ খুঁজতে হয়।

৮ · AI-এর যুগে — kernel-এর কোড আর দাবি যাচাই

AI assistant-কে “SVM দিয়ে classifier বানাও” বললে সে প্রায় নিশ্চিতভাবে চলনসই কোড দেয়। সমস্যা থাকে সূক্ষ্ম জায়গায়: scaling, grid-এর পরিসর, কোন ডেটায় মাপা হলো, আর kernel সম্পর্কে আত্মবিশ্বাসী কিন্তু ভুল কথা। পরিচিত ভুলগুলো:

AI প্রায়ই যা করেকেন ভুলকীভাবে ধরবেন
Scaling ছাড়া RBF, বা পুরো ডেটায় scaler fit করে তারপর splitদূরত্ব একটি feature-এ আটকায়; বা leakagemake_pipeline(StandardScaler(), SVC()), CV-র ভেতরে
γ আর C-এর grid রৈখিক ধাপে (০.১, ০.২, ০.৩)এদের প্রভাব সূচকীয়; সেরা অঞ্চল বাদ পড়েlog-মাপের grid; সেরা কিনারায় হলে grid বাড়ান
Test ডেটায় grid search, বা train accuracy রিপোর্টγ বড় হলে train প্রায় ১.০ (অংশ ৬-এ ০.৯৯৫)তালাবন্ধ test; CV score আর test আলাদা লিখুন
“poly kernel-এ সব দ্বিঘাত পদ আছে” বলে ডিফল্ট SVC(kernel="poly") চালায়ডিফল্ট coef0=0, degree=3: শুধু ঠিক তৃতীয় ঘাতdocs-এ সূত্র মিলিয়ে degree, coef0 স্পষ্ট দিন
নিজে বানানো “similarity” kernel="precomputed"-এ দেয়, PSD যাচাই ছাড়াঅবৈধ kernel-এ convexity নেই; scikit-learn সাধারণত সতর্ক করে নাscipy.linalg.eigh-এ সবচেয়ে ছোট eigenvalue দেখুন
Kernel SVC-র coef_ দিয়ে “feature importance” দেখাতে চায়Linear ছাড়া coef_ নেই; w অসীম মাত্রায় থাকতে পারেdual_coef_ আর support vector; বা permutation importance

AI-কে শুধু কোড নয়, কারণ আর যাচাইও চাইতে বলুন:

আমার কাছে বাজারঘরের ৩০০টি অর্ডারের দুটি সংখ্যাগত feature আর প্রতারণার লেবেল আছে (scikit-learn 1.8.0). Kernel SVM দিয়ে classifier বানাতে চাই। ১. প্রথমে ডেটা train আর test-এ ভাগ করো (stratify আর random_state দিয়ে); test শুধু শেষে একবার ব্যবহার করবে। ২. StandardScaler আর SVC একটি Pipeline-এ রাখো, যাতে CV-র প্রতিটি fold-এ scaling শুধু train অংশে শেখে। ৩. linear, poly (degree আর coef0 স্পষ্ট লিখে) আর rbf তুলনা করো; rbf-এর জন্য C আর gamma log-মাপে, যেমন 10^-2 থেকে 10^3. ৪. 5-fold CV-র পুরো score-এর ছক heatmap-এ দেখাও, আর সেরা মান grid-এর কিনারায় পড়লে বলো। ৫. train accuracy, CV accuracy আর test accuracy আলাদা করে দাও, আর support vector-এর সংখ্যা। ৬. যে argument ব্যবহার করছ সেগুলো 1.8.0-এর docs-এ আছে কি না কীভাবে মিলাব বলো; কোনো warning চাপা দিও না।

AI-এর দেওয়া kernel কোড হাতে পেলে — যাচাইয়ের চেকলিস্ট

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।

প্র ০১১৯৯০ আর ২০০০-এর দশকে kernel SVM কেন machine learning-এর প্রধান হাতিয়ার হয়ে উঠেছিল, আর পরে deep learning কেন অনেক কাজে তার জায়গা নিল?

১৯৯২ সালে Boser, Guyon আর Vapnik kernel trick-কে maximum-margin classifier-এ বসানোর পর কয়েকটি গুণ একসঙ্গে এল, যা তখনকার neural network-এ ছিল না। প্রথম, প্রশিক্ষণ একটি convex quadratic program: একটিই সেরা উত্তর, শুরুর মান বা learning rate নিয়ে দুশ্চিন্তা নেই। দ্বিতীয়, margin আর VC-ধাঁচের তত্ত্ব (পর্ব ০৩) একটি ব্যাখ্যা দিত কেন অনেক মাত্রাতেও model সাধারণীকরণ করতে পারে। তৃতীয়, kernel বদলেই নতুন ধরনের ডেটায় যাওয়া যেত: লেখা, ক্রম, graph. John Platt-এর SMO (১৯৯৮) আর পরে LIBSVM-এর মতো সফটওয়্যার প্রশিক্ষণকে ব্যবহারিক করে তোলে।

হাতে লেখা অঙ্কের MNIST ডেটায় Dennis DeCoste আর Bernhard Schölkopf ২০০২ সালে invariance-যুক্ত SVM দিয়ে প্রায় ০.৫৬% ভুলের হার জানান, যা তখনকার সেরা ফলগুলোর মধ্যে ছিল। লেখার শ্রেণিবিভাগে Thorsten Joachims ১৯৯৮ সালে দেখান linear SVM অত্যন্ত শক্তিশালী। ফলে দুই দশক ধরে অনেক গবেষণাপত্রে SVM ছিল প্রথম তুলনার মানদণ্ড।

দুটি সীমা পরে গুরুত্বপূর্ণ হয়ে ওঠে। এক, খরচ: Gram matrix n × n, আর প্রশিক্ষণ সাধারণত n² থেকে n³-এর মতো বাড়ে, তাই লাখ লাখ ছবিতে সরাসরি kernel SVM কঠিন (পর্ব ৩১)। দুই, kernel আগে থেকে ঠিক করা: RBF জানে না যে ছবিতে পাশাপাশি pixel সম্পর্কিত বা একটি বস্তু সরে গেলেও একই বস্তু। ২০১২ সালে AlexNet-এর পর convolutional network ডেটা থেকেই feature শেখার সুবিধা দেখায়, আর বড় ডেটা ও GPU সেই সুবিধা কাজে লাগায়।

তবু kernel হারিয়ে যায়নি। ছোট আর মাঝারি tabular বা বৈজ্ঞানিক ডেটায়, যেখানে নমুনা কয়েকশো থেকে কয়েক হাজার, kernel পদ্ধতি এখনো শক্ত প্রতিযোগী; Gaussian process-এর মধ্য দিয়ে Bayesian optimization-এ kernel কেন্দ্রীয়; আর neural tangent kernel-এর মতো তত্ত্ব deep learning বোঝার কাজে kernel-এর ভাষাই ব্যবহার করে। কোন পদ্ধতি “জিতেছে”, তা ডেটার আকার আর ধরনের ওপর নির্ভর করে, একটি সার্বজনীন রায় নয়।

মূল উপলব্ধি: kernel SVM convexity, তত্ত্ব আর নমনীয়তার জন্য জনপ্রিয় হয়; বড় ডেটায় খরচ আর স্থির feature-এর সীমা deep learning-কে জায়গা করে দেয়, কিন্তু ছোট ডেটায় kernel এখনো কাজের।

প্র ০২RBF kernel-এর feature space অসীম মাত্রার। তাহলে SVM overfit করে না কেন, অন্তত সবসময় কেন করে না?

পুরোনো পরিসংখ্যানের সহজ নিয়ম বলে, parameter যত বেশি, overfitting তত সহজ। অসীম মাত্রার জগতে linear model-এর parameter অসীম, তাই প্রশ্নটি স্বাভাবিক। উত্তরের তিনটি স্তর আছে।

প্রথম, model-এর জটিলতা মাত্রা দিয়ে নয়, regularization দিয়ে নিয়ন্ত্রিত। SVM ½‖w‖² কমায়, যা RKHS-এর norm, আর C ঠিক করে ভুল আর মসৃণতার মধ্যে কোনটি কতটা গুরুত্ব পাবে। Vapnik-এর তত্ত্বে margin-ভিত্তিক সীমা দেখায়, ডেটা যদি একটি নির্দিষ্ট ব্যাসার্ধের বলের ভেতরে থাকে আর margin চওড়া হয়, তবে সাধারণীকরণের সীমা মাত্রার ওপর নির্ভর না-ও করতে পারে। এই সীমাগুলো প্রায়ই ঢিলেঢালা, তাই বাস্তব সংখ্যার পূর্বাভাস হিসেবে নয়, অন্তর্দৃষ্টি হিসেবে নেওয়া ভালো।

দ্বিতীয়, representer theorem: অসীম মাত্রা সত্ত্বেও খোঁজা হয় n টি সহগ, আর SVM-এ তাদের অনেকগুলো শূন্য। কার্যকর স্বাধীনতা তাই ডেটার সংখ্যা আর kernel-এর মসৃণতা দিয়ে সীমিত।

তৃতীয়, এবং সবচেয়ে ব্যবহারিক: SVM সত্যিই overfit করে, যদি γ আর C ভুল হয়। অংশ ৬-এ γ = ১০০-এ train ০.৯৯৫ আর test ০.৮৫৬, support vector ২১০টির মধ্যে ১৮৯টি। γ খুব বড় হলে Gram matrix প্রায় একক matrix, তখন model প্রতিটি train বিন্দু মুখস্থ করতে পারে। অর্থাৎ অসীম মাত্রা মানে সম্ভাবনা, নিয়তি নয়; নিয়ন্ত্রণ দুটি hyperparameter-এ, যা cross-validation দিয়ে বাছতে হয়। Support vector-এর অনুপাতও একটি সংকেত: leave-one-out error-এর একটি পরিচিত ঊর্ধ্বসীমা হলো support vector-এর সংখ্যা ভাগ n, তাই প্রায় সব বিন্দু support vector হলে সাবধান হওয়ার কারণ আছে।

এই প্রশ্নের আধুনিক রূপ deep learning-এও আছে: খুব বড় network train ডেটা পুরো মুখস্থ করেও ভালো সাধারণীকরণ করে, যা নিয়ে এখনো গবেষণা চলছে। Kernel-এর ভাষা সেখানেও ব্যবহার হয়, তবে পুরো ব্যাখ্যা এখনো সর্বসম্মত নয়।

মূল উপলব্ধি: জটিলতা মাপে norm আর margin, মাত্রা নয়; তবু γ আর C ভুল হলে RBF SVM মুখস্থ করে, তাই CV আর support vector-এর অনুপাত দেখা জরুরি।

প্র ০৩scikit-learn-এ kernel="sigmoid" আছে, অথচ tanh সব প্যারামিটারে বৈধ kernel নয়। অবৈধ বা “indefinite” kernel ব্যবহার করলে আসলে কী ঘটে?

Sigmoid kernel tanh(γ·x·z + r) জনপ্রিয় হয়েছিল কারণ এটি দুই স্তরের neural network-এর মতো দেখায়। কিন্তু অংশ ৫-এর stepper আর ব্লকে দেখেছেন, কয়েকটি বিন্দুতেই এর Gram matrix PSD থাকে না। Hsuan-Tien Lin আর Chih-Jen Lin ২০০৩ সালের একটি প্রতিবেদনে বিশ্লেষণ করেন কোন γ আর r-এ এটি PSD-এর কাছাকাছি আচরণ করে, আর দেখান যে অনেক প্যারামিটারে এটি conditionally positive definite-ও নয়। তাঁদের ব্যবহারিক পরামর্শ ছিল, এটি সাধারণত RBF-এর চেয়ে ভালো ফল দেয় না।

অবৈধ kernel-এ গাণিতিকভাবে তিনটি সমস্যা হয়। Dual-এর quadratic অংশ আর convex নয়, তাই একাধিক local সমাধান থাকতে পারে, আর solver যেটিতে থামে সেটি শুরুর অবস্থার ওপর নির্ভর করে। “Margin” আর “দূরত্ব”-এর জ্যামিতিক অর্থ হারায়, কারণ কোনো Hilbert space-এ এই মিল dot product নয়। আর representer theorem-এর নিশ্চয়তাও আর খাটে না। তবু SMO-ধরনের solver প্রায়ই কোনো একটি উত্তরে থামে, আর scikit-learn সাধারণত কোনো সতর্কবার্তা দেয় না, তাই ব্যবহারকারী সমস্যাটি টেরই পান না।

বাস্তবে indefinite মিল প্রায়ই আসে: দুটি লেখার edit distance থেকে বানানো মিল, বা মানুষের দেওয়া মিলের নম্বর। সমাধানের কয়েকটি পথ গবেষণায় আছে: সবচেয়ে ছোট ঋণাত্মক eigenvalue-কে শূন্য করে দেওয়া (clip), কর্ণে একটি ধনাত্মক সংখ্যা যোগ করা (shift), eigenvalue-এর পরম মান নেওয়া (flip), বা Cheng Soon Ong ও সহকর্মীদের ২০০৪ সালের ICML প্রবন্ধের মতো Kreĭn space-এ শেখা। প্রথম তিনটিতে train আর নতুন ডেটায় একই সংশোধন কীভাবে দেবেন, সেটিও একটি সমস্যা।

বাজারঘরের দৃষ্টিতে নিয়ম সরল: নিজের মিল বানালে আগে ছোট নমুনায় eigenvalue দেখুন, আর সম্ভব হলে এমনভাবে বানান যাতে বৈধতা নির্মাণেই নিশ্চিত হয়, যেমন n-gram গণনার dot product.

মূল উপলব্ধি: অবৈধ kernel-এ কোড চলে কিন্তু convexity আর জ্যামিতি হারায়; তাই PSD যাচাই আপনার দায়িত্ব, লাইব্রেরির নয়।

প্র ০৪বাজারঘর বাংলা পণ্যের বর্ণনা দিয়ে শ্রেণি (শাড়ি, থ্রি-পিস, পাঞ্জাবি…) অনুমান করতে চায়। TF-IDF + linear SVM, না string kernel? কীভাবে ঠিক করবেন?

দুটিই আসলে kernel পদ্ধতি। TF-IDF (AI-এর ভিত্তি কোর্সে বাংলা লেখার জন্য দেখেছেন) প্রতিটি বর্ণনাকে শব্দ বা n-gram-এর একটি বিশাল কিন্তু বেশিরভাগ শূন্য vector বানায়; তার ওপর linear SVM মানে linear kernel. String kernel একই রকম φ ধরে, কিন্তু vector না বানিয়ে সরাসরি দুটি লেখার মিল গোনে, আর Lodhi ও সহকর্মীদের subsequence kernel-এর মতো রূপে ফাঁক রেখেও মেলাতে পারে।

খরচের দিক থেকে পার্থক্য বড়। Thorsten Joachims ১৯৯৮ সালে দেখান লেখার শ্রেণিবিভাগে উচ্চ মাত্রার sparse feature-এ linear SVM খুব শক্তিশালী, আর LIBLINEAR-এর মতো solver লাখো নথিতে দ্রুত চলে। String kernel-এ প্রতিটি জোড়ার জন্য dynamic programming লাগে, আর n × n Gram matrix, তাই কয়েক হাজার নথির পর ধীর হয়।

বাংলার জন্য একটি বিশেষ বিবেচনা: যুক্তাক্ষর, বানানের বৈচিত্র্য (“শাড়ী” বনাম “শাড়ি”), আর বাংলা-ইংরেজি মেশানো বর্ণনা। অক্ষর-স্তরের n-gram এই বৈচিত্র্য সামলাতে সাহায্য করে, আর তা TF-IDF-এর character n-gram দিয়েও পাওয়া যায়, string kernel ছাড়াই। Unicode normalization আগে করা দরকার, কারণ একই অক্ষর একাধিক কোডে লেখা যায়।

সিদ্ধান্তের পদ্ধতি: প্রথমে character আর word n-gram-এর TF-IDF + linear SVM একটি baseline; তারপর একটি ছোট নমুনায় (কয়েক হাজার) string kernel বা n-gram kernel চেষ্টা; দুটি cross-validation-এ, একই fold-এ, কয়েকটি seed-এ তুলনা (পর্ব ২২)। পার্থক্য ছোট হলে দ্রুত আর সহজ পদ্ধতিটি রাখুন। পরে বাংলা লেখার জন্য প্রশিক্ষিত embedding model-ও প্রতিযোগী হবে, যা পরের কোর্সে NLP-র অংশে আসবে।

মূল উপলব্ধি: লেখার জন্য প্রথমে sparse feature আর linear kernel; string kernel তখনই, যখন ছোট ডেটায় মাপা উন্নতি তার খরচের যোগ্য।

প্র ০৫“RBF সবসময় নিরাপদ পছন্দ” — এই পরামর্শ কতটা সত্য? কখন অন্য kernel, বা kernel ছাড়া model ভালো?

পরামর্শটির উৎস যুক্তিসঙ্গত। Hsu, Chang আর Lin-এর ব্যবহারিক নির্দেশিকা RBF-কে প্রথম পছন্দ বলে: এটি linear kernel-কে সীমায় ধরে ফেলে (খুব ছোট γ আর বড় C-তে প্রায় linear-এর মতো আচরণ, যা S. Sathiya Keerthi আর Chih-Jen Lin ২০০৩ সালে বিশ্লেষণ করেন), মাত্র দুটি hyperparameter, আর polynomial-এর মতো বড় ঘাতে সংখ্যাগত সমস্যা নেই। তাই অপরিচিত ছোট ডেটায় শুরুর জায়গা হিসেবে RBF ভালো।

কিন্তু “সবসময়” নয়। প্রথম, ডেটার আকার সম্পর্কে জ্ঞান থাকলে মেলানো kernel ভালো: অংশ ৬-এ বৃত্তাকার সীমানায় degree ২-এর poly test-এ ০.৯৫৬, সেরা RBF ০.৮৭৮ (একটি split, কাল্পনিক ডেটা)। সময়ক্রমের ডেটায় পর্যায়বৃত্ত kernel, লেখায় n-gram kernel, graph-এ graph kernel. দ্বিতীয়, feature খুব বেশি আর নমুনা তুলনায় কম হলে (লেখা, জিনের ডেটা) linear kernel প্রায়ই সমান ভালো, অনেক দ্রুত, আর ব্যাখ্যাযোগ্য। তৃতীয়, n বড় হলে exact kernel ধীর; তখন Nyström বা random feature (পর্ব ৩১)।

চতুর্থ, অনেক tabular ব্যবসায়িক ডেটায়, যেখানে categorical feature, অনুপস্থিত মান আর ভিন্ন ভিন্ন মাপের কলাম মেশানো, gradient boosting ধরনের tree model প্রায়ই কম ঝামেলায় ভালো ফল দেয় বলে অনেক তুলনায় দেখা গেছে, যদিও এটি ডেটাভেদে বদলায় (মডিউল ৭)। RBF দূরত্ব চায়, তাই categorical কলাম আর scaling-এর সিদ্ধান্ত সেখানে ঝামেলা বাড়ায়। পঞ্চম, সম্ভাবনা দরকার হলে SVM-এর score আলাদা করে calibrate করতে হয় (পর্ব ২৬)।

তাই কাজের নিয়ম: একটি সরল baseline (logistic বা linear SVM), তারপর RBF, আর ডেটার জ্ঞান থাকলে একটি মেলানো kernel; সবগুলো একই CV fold-এ তুলনা, আর খরচ ও ব্যাখ্যার প্রয়োজনও বিবেচনায়।

মূল উপলব্ধি: RBF ভালো শুরুর বিন্দু, শেষ কথা নয়; ডেটার গঠন, আকার আর সিদ্ধান্তের প্রয়োজন kernel বাছাই ঠিক করে।

অনুশীলন

হিসাবগুলো খাতায় করুন, তারপর উত্তর মেলান। চাইলে অংশ ৩ আর ৫-এর ব্লক বদলে যাচাই করুন।

  1. পূর্ণ numerical: x = (২, ১), z = (১, ৩). (ক) homogeneous kernel (x·z)² খুলে তার φ বের করুন আর দেখান φ(x)·φ(z) = k(x, z). (খ) γ = ০.৫-এ RBF kernel-এর মান কত? (গ) ১০টি feature-এ (x·z + ১)³-এর স্পষ্ট φ-এ কতটি কলাম?

    (ক) (x₁z₁ + x₂z₂)² = x₁²z₁² + x₂²z₂² + ২x₁x₂z₁z₂, তাই φ(x) = (x₁², x₂², √২x₁x₂). φ(x) = (৪, ১, ২√২), φ(z) = (১, ৯, ৩√২). Dot product = ৪ + ৯ + ২√২ × ৩√২ = ৪ + ৯ + ১২ = ২৫. সরাসরি: x·z = ২ + ৩ = ৫, ৫² = ২৫ ✓.

    (খ) ‖x − z‖² = (২ − ১)² + (১ − ৩)² = ১ + ৪ = ৫. k = exp(−০.৫ × ৫) = exp(−২.৫) ≈ ০.০৮২১.

    (গ) C(১০ + ৩, ৩) = C(১৩, ৩) = (১৩ × ১২ × ১১)/৬ = ২৮৬টি কলাম (ধ্রুবক ১ সহ)। Kernel-এ শুধু ১০টি গুণ, একটি যোগ আর একটি ঘন।

  2. সমালোচনা ও নকশা: একজন সহকর্মী AI-এর সাহায্যে লিখেছেন: “পুরো ৫,০০০ অর্ডারে StandardScaler fit করে তারপর ৮০/২০ split করেছি। SVC(kernel="rbf")-এ gamma = [০.১, ০.৫, ১] আর C = [১, ২, ৩] দিয়ে test ভাগে সেরা খুঁজেছি; সেরা gamma = ১, C = ৩, test accuracy ০.৯৭. আমাদের নিজের ‘গ্রাহক-মিল’ score-ও আছে, পরের ধাপে kernel="precomputed"-এ দেব।” কী কী সমস্যা, আর সঠিক নকশা কী?

    সমস্যা: (১) Split-এর আগে পুরো ডেটায় scaler: test-এর গড় আর variance train-এ ঢুকেছে, ছোট কিন্তু বাস্তব leakage. (২) Grid রৈখিক আর সরু; γ আর C-এর প্রভাব সূচকীয়, আর সেরা মান দুটিই grid-এর কিনারায় (γ = ১, C = ৩), তাই আসল সেরা হয়তো বাইরে। (৩) Test ভাগে tuning: ০.৯৭ আশাবাদী, কারণ test-ই বাছাইয়ে ব্যবহার হয়েছে। (৪) কোনো baseline নেই। (৫) নিজের “মিল” score PSD কি না যাচাইয়ের কথা নেই; অবৈধ হলে convexity হারাবে আর scikit-learn সাধারণত সতর্ক করবে না।

    সঠিক নকশা: আগে split (stratify), test তালাবন্ধ; Pipeline(StandardScaler, SVC); γ আর C ১০−৩ থেকে ১০৩ log-মাপে, ৫-fold GridSearchCV শুধু train-এ; সেরা কিনারায় পড়লে grid বাড়ানো; linear SVM বা logistic baseline; শেষে test-এ একবার। নিজের মিলের জন্য একটি নমুনায় scipy.linalg.eigh দিয়ে সবচেয়ে ছোট eigenvalue দেখা, আর ঋণাত্মক হলে নির্মাণ বদলানো।

  3. আউটপুট অনুমান করুন: চালানোর আগে লিখে ফেলুন নিচের কোড কী ছাপবে।
    import numpy as np
    from sklearn.metrics.pairwise import polynomial_kernel, rbf_kernel
    X = np.array([[1.0, 0.0], [0.0, 2.0]])
    print(polynomial_kernel(X, degree=2, gamma=1, coef0=1))
    print(np.round(rbf_kernel(X, gamma=0.5), 4))
    [[ 4.  1.]
     [ 1. 25.]]
    [[1.     0.0821]
     [0.0821 1.    ]]

    Poly: x₁·x₁ = ১ → (১ + ১)² = ৪; x₁·x₂ = ০ → (০ + ১)² = ১; x₂·x₂ = ৪ → (৪ + ১)² = ২৫. RBF: কর্ণে সবসময় ১; ‖x₁ − x₂‖² = ১ + ৪ = ৫, exp(−২.৫) ≈ ০.০৮২১. ছাপার ধরন (“4.”, ফাঁকা জায়গা) NumPy-র; ডেস্কটপে scikit-learn 1.8.0-এ মেলানো।

  4. অনুমান হাতে, representer-এর রূপে: একটি RBF SVM (γ = ১) তিনটি support vector শিখেছে: x₁ = (০, ০), y₁ = −১, α₁ = ০.৮; x₂ = (১, ০), y₂ = +১, α₂ = ০.৫; x₃ = (০, ১), y₃ = +১, α₃ = ০.৩; আর b = −০.২. (ক) শর্ত ∑αiyi = ০ মেলে কি? (খ) নতুন অর্ডার x = (১, ১)-এর f(x) কত, আর কোন শ্রেণি?

    (ক) −০.৮ + ০.৫ + ০.৩ = ০ ✓.

    (খ) দূরত্বের বর্গ: x₁ থেকে ২, x₂ থেকে ১, x₃ থেকে ১. Kernel: e−২ ≈ ০.১৩৫৩, e−১ ≈ ০.৩৬৭৯, ০.৩৬৭৯. f(x) = −০.৮ × ০.১৩৫৩ + ০.৫ × ০.৩৬৭৯ + ০.৩ × ০.৩৬৭৯ − ০.২ = −০.১০৮৩ + ০.১৮৩৯ + ০.১১০৪ − ০.২ ≈ −০.০১৪০. চিহ্ন ঋণাত্মক, তাই শ্রেণি −১, কিন্তু সীমানার একেবারে কাছে। লক্ষ করুন, হিসাবে কোনো w বা φ লাগেনি, শুধু তিনটি kernel মান।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি নতুন classification ডেটায় kernel SVM বানানোর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. ডেটা train আর test-এ ভাগ করা, test তালাবন্ধ রাখা
  2. StandardScaler আর SVC একটি Pipeline-এ রাখা
  3. একটি সরল baseline আর RBF kernel দিয়ে শুরু করা
  4. C আর γ log-মাপের grid-এ cross-validation দিয়ে খোঁজা
  5. সেরা মান grid-এর কিনারায় কি না দেখে দরকারে grid বাড়ানো
  6. শেষে তালাবন্ধ test-এ একবার মেপে রিপোর্ট করা

একটি RBF SVM-এ γ অনেক বাড়ালে (অন্য সব একই রেখে) সাধারণত কী দেখা যায়?

  • সীমানা প্রায় সরলরেখা হয়ে যায়
  • Support vector কমে যায়, model সরল হয়
  • Train accuracy বাড়ে, test accuracy কমতে পারে
  • Gram matrix-এর সব ঘর ১-এর দিকে যায়

k₁ আর k₂ দুটি বৈধ kernel হলে নিচের কোনটি সাধারণভাবে বৈধ kernel নয়?

  • k₁ + k₂
  • k₁ · k₂
  • ৫ · k₁
  • k₁ − k₂

দুটি বিন্দুর একটি প্রস্তাবিত “মিল”-এর matrix হলো [[১, ২], [২, ১]]. এটি কি কোনো বৈধ kernel-এর Gram matrix হতে পারে?

  • না, একটি eigenvalue ঋণাত্মক (−১)
  • হ্যাঁ, কারণ matrix প্রতিসম
  • হ্যাঁ, কারণ সব ঘর ধনাত্মক
  • না, কারণ কর্ণ ১ হতে পারে না

তিনটি feature-এ polynomial kernel (x·z + ১)²-এর স্পষ্ট feature map-এ কতটি উপাদান (ধ্রুবকসহ)?

  • ৬
  • ১০
  • ৯
  • ৮

Representer theorem অনুযায়ী, ‖f‖²-এর শাস্তিসহ একটি kernel model-এর সেরা function কোন আকারের?

  • f(x) = w·x + b, যেখানে w মূল feature-এর ওজন
  • কয়েকটি এলোমেলো কেন্দ্রের RBF-এর যোগফল
  • f(x) = ∑i ci k(xi, x), যেখানে xi train বিন্দু
  • সর্বোচ্চ দ্বিঘাত একটি polynomial

একটি γ–C grid search-এ সেরা CV score পাওয়া গেল সবচেয়ে বড় γ আর সবচেয়ে বড় C-এর কোণে। সবচেয়ে যুক্তিসঙ্গত পরের কাজ কী?

  • সেই মানগুলোই চূড়ান্ত ধরে test-এ মাপা
  • Test ডেটায় grid search আবার চালানো
  • RBF বাদ দিয়ে linear kernel নেওয়া
  • ওই দিকে log-মাপে grid বাড়িয়ে আবার CV চালানো

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. Feature map: φ-এর জগতে সরল সমতল = মূল জগতে বাঁকা সীমানা। বৃত্তাকার ডেটায় r² = x₁² + x₂² যোগ করতেই ০.৫৭৮ থেকে ০.৯৮৯.
  2. Kernel trick: dual আর অনুমান শুধু xi·xj চায়; তার জায়গায় k(xi, xj) = φ(xi)·φ(xj). অনুমান f(x) = ∑αiyik(xi, x) + b.
  3. দুটি kernel: (x·z + ১)² = ছয়টি feature-এর dot product (দুই মাত্রায়); RBF exp(−γ‖x − z‖²), অসীম মাত্রা, γ বড় = ছোট প্রভাব-এলাকা = overfitting-এর ঝুঁকি।
  4. Mercer: বৈধ kernel ⇔ যেকোনো সেটে Gram matrix PSD. যোগ, ঘরে ঘরে গুণ, ধনাত্মক গুণিতক বৈধতা রাখে; বিয়োগ, ঋণাত্মক দূরত্ব আর tanh প্রায়ই ভাঙে। যাচাই: scipy.linalg.eigh, সহনশীলতাসহ।
  5. ব্যবহার: scale করুন (Pipeline-এ), RBF দিয়ে শুরু, γ আর C log-মাপে CV-তে; representer theorem সব kernel model-কে n টি সহগে নামায়, আর string বা graph-এর মতো vector-হীন ডেটাতেও kernel চলে।

পরের পর্বে: পর্ব ৩০ (SVR আর kernel ridge regression — kernel দিয়ে সংখ্যার অনুমান): একই kernel এবার শ্রেণি নয়, সংখ্যা অনুমানে, যেমন বাজারঘরের ডেলিভারির সময়; ε-এর নল আর বর্গ-ভুলের closed form পাশাপাশি।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান