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

SVR আর kernel ridge regression — kernel দিয়ে সংখ্যার অনুমান

Support Vector Regression and Kernel Ridge Regression — epsilon-insensitive Loss, Sparse vs Dense Solutions and Hyperparameter Search

Taught in Bangla, this lesson predicts delivery times with kernels: the epsilon-insensitive loss, the SVR primal, dual and KKT conditions that decide support vectors, the kernel ridge closed form worked on three points and coded with SciPy, KRR versus SVR on error, sparsity and time, the Gaussian process link, and tuning with pipelines. Real in-browser scikit-learn runs.

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

  • ε-insensitive loss হাতে হিসাব করা, আর squared, absolute ও Huber loss-এর সঙ্গে তুলনা করা
  • SVR-এর primal আর dual লেখা, C আর ε-এর ভূমিকা বোঝা, আর KKT দিয়ে বলা কোন বিন্দু support vector
  • Kernel ridge regression-এর বন্ধ রূপ derive করা, তিনটি বিন্দুতে হাতে করা, আর SciPy দিয়ে বানিয়ে KernelRidge-এর সঙ্গে মেলানো
  • KRR আর SVR-কে ভুল, sparse বনাম dense সমাধান আর সময় দিয়ে তুলনা করা, আর Gaussian process-এর সঙ্গে যোগসূত্র জানা
  • Pipeline আর GridSearchCV দিয়ে hyperparameter বাছাই করা, আর test set তালাবদ্ধ রাখা

পর্ব ২৭ থেকে ২৯-এ (Support Vector Machine, Soft margin, Kernel trick) margin, hinge loss, dual problem আর kernel দিয়ে শ্রেণি আলাদা করা দেখেছেন। এই পর্বে লক্ষ্য শ্রেণি নয়, একটি সংখ্যা: বাজারঘরের একটি অর্ডার hub থেকে কত km দূরে, তা দেখে ডেলিভারিতে কত মিনিট লাগবে। AI-এর ভিত্তি কোর্সের পর্ব ৫৮-এ সরলরেখা টেনেছেন, আর এই কোর্সের পর্ব ২৩-এ RBF basis দিয়ে বাঁকা রেখা বানিয়েছেন, কিন্তু basis-এর কেন্দ্র আপনাকে বাছতে হয়েছিল। Kernel সেই বাছাই ডেটার বিন্দুগুলোর হাতেই ছেড়ে দেয়। চালানো যায় এমন চারটি ব্লক পাতাতেই চলে (ব্রাউজারের Python, NumPy, SciPy, scikit-learn আর matplotlib); প্রথমবার scikit-learn নামতে প্রায় দশ সেকেন্ড লাগে।

১ · Kernel দিয়ে regression — এক আকার, দুই পথ

নতুন একটি ঠিকানায় ডেলিভারিতে কত সময় লাগবে, অভিজ্ঞ কুরিয়ার কীভাবে আন্দাজ করেন? তিনি মনে করেন কাছাকাছি দূরত্বের আগের অর্ডারগুলো, আর যে অর্ডার যত কাছের, তার কথায় তত বেশি ভরসা। এটিই kernel regression-এর মূল কথা: অনুমান হলো আগের অর্ডারগুলোর “মিল”-এর ওজনে মেশানো যোগফল। পার্থক্য শুধু কোন অর্ডারকে কতটা ওজন দেওয়া হবে, সেই হিসাবে।

বাজারঘরের ডেটায় দূরত্ব বনাম সময় সরলরেখা নয়: শহরের ভেতরের কয়েক km-এ জ্যামে সময় দ্রুত বাড়ে, তারপর বড় রাস্তায় ঢাল কমে, আর কিছু দূরত্বে সেতু বা বাজারের ভিড়ে ঢেউ ওঠে। এমন বাঁকা ধারা ধরতে দুটি পরিচিত পথ আছে। প্রথমটি পর্ব ২৩-এর মতো নিজে feature বানানো, যেমন কয়েকটি RBF কেন্দ্র। দ্বিতীয়টি kernel: দুটি ইনপুটের মিল k(x, z) সরাসরি মাপা, যেখানে k হলো কোনো feature map φ-এর dot product, φ(x)·φ(z). এই পর্বের প্রধান kernel হলো RBF kernel k(x, z) = exp(−γ(x − z)²), যেখানে γ ঠিক করে কত দূর পর্যন্ত দুটি অর্ডারকে “কাছের” ধরা হবে। γ বড় হলে মিল দ্রুত শূন্যে নামে, রেখা আঁকাবাঁকা হয়; ছোট হলে রেখা মসৃণ।

একটি গুরুত্বপূর্ণ ফল দুটি model-কে একই ছাঁচে ফেলে। Representer theorem (Kimeldorf আর Wahba, ১৯৭১; Schölkopf, Herbrich আর Smola ২০০১ সালে আরও সাধারণ রূপ দেন) বলে: kernel-এর function space-এ “training-এর loss + ‖f‖²-এর শাস্তি” কমালে সেরা f সবসময় এই আকারের:

f(x) = Σi βi k(xi, x) (+ b)

অর্থাৎ প্রতিটি training অর্ডার i একটি “ঢিবি” k(xi, ·) রাখে, আর তার উচ্চতা βi. Loss বদলালে শুধু β-গুলো বদলায়। এই পর্বের দুই model দুই loss নেয়:

Support vector regression (SVR)

Loss: ε-insensitive, max(০, ∣r∣ − ε). সমাধান একটি quadratic program. ভেতরের বিন্দুর β = ০, তাই সমাধান sparse: অনুমানে শুধু support vector লাগে। Intercept b আছে।

Kernel ridge regression (KRR)

Loss: squared, r². সমাধান একটি linear system, α = (K + λI)−1y. প্রায় সব α শূন্য নয়, তাই সমাধান dense. scikit-learn-এর রূপে intercept নেই।

২ · ε-insensitive loss — ছোট ভুলে শাস্তি নেই

অ্যাপে লেখা “৪৫ মিনিটে পৌঁছাবে”, পার্সেল এল ৪৮ মিনিটে। কেউ অভিযোগ করেন না। ৭০ মিনিটে এলে করেন, আর যত দেরি, তত রাগ। ক্রেতার এই আচরণ ঠিক একটি “মরা অঞ্চল” (dead zone)-সহ loss: কয়েক মিনিটের ভুল মাফ, তার বাইরে প্রতিটি বাড়তি মিনিট সমান দামি।

Residual r = y − f(x) হলে ε-insensitive loss (Vladimir Vapnik তাঁর ১৯৯৫ সালের বই The Nature of Statistical Learning Theory-তে এটি দেন):

Lε(r) = max(০, ∣r∣ − ε)

∣r∣ ≤ ε হলে loss শূন্য; বাইরে loss বাড়ে সরলরেখায়, ঢাল ১. পর্ব ০২-এ squared, absolute, Huber আর hinge loss দেখেছেন। ε-insensitive loss আসলে absolute loss-এর মাঝখানটা কেটে সমতল করা। আর পর্ব ০২-এর hinge loss max(০, ১ − yf)-এর সঙ্গে তার মিল স্পষ্ট: দুটিই “যথেষ্ট ভালো হলে শাস্তি শূন্য” বলে, একটি শ্রেণির জন্য, অন্যটি সংখ্যার জন্য। পর্ব ২৪-এর Huber loss-এর মতো এরও বাইরের দিকটা সরলরৈখিক, তাই একটি অনেক দেরির অর্ডার রেখাকে বর্গের জোরে টানতে পারে না। নিচের stepper চারটি residual-এ তিনটি loss পাশাপাশি হিসাব করে।

r = আসল − অনুমান (মিনিট); ε = 5; Huber-এ δ = 5
অর্ডার
ε-insensitive
squared r²
Huber
ε-loss-এর ঢাল
  1. tube-এর ভেতরে। r = +২, ∣r∣ < ε = ৫: ε-insensitive loss শূন্য। Squared loss কিন্তু ৪ শাস্তি দেয়, Huber ২. এই অর্ডার SVR-এর কাছে “যথেষ্ট ঠিক”, তাকে আর ঠেলার কিছু নেই।
  2. ঠিক কিনারায়। r = −৫, ∣r∣ = ε: loss এখনও শূন্য, কিন্তু এখানে বক্ররেখায় কোণ আছে, ঢাল ০ থেকে ১-এর যেকোনো মান (subgradient). পরে দেখবেন, এই বিন্দুগুলোর dual coefficient ০ আর C-এর মাঝামাঝি।
  3. বাইরে। r = +৮: loss ৮ − ৫ = ৩, অর্থাৎ শুধু tube-এর বাইরের অংশটুকু। Squared ৬৪, Huber ২৭.৫.
  4. অনেক দূরে। r = −১৫ (বৃষ্টিতে আটকে যাওয়া অর্ডার): ε-loss ১০, squared ২২৫. বর্গের কারণে squared loss এই একটি অর্ডারকে বাকিদের চেয়ে বহু গুণ গুরুত্ব দেয়।
  5. মোট আর টান। মোট loss: ε-insensitive ১৩, Huber ১০৪.৫, squared ৩১৮. ε-loss-এর ঢাল বাইরের যেকোনো বিন্দুতে ১, দূরত্ব যতই হোক: গ আর ঘ রেখাকে সমান জোরে টানে, ভেতরের ক টানেই না।

এই আকারের দুটি ফল আছে। প্রথম, ভেতরের অর্ডার উত্তরে কোনো ভূমিকা রাখে না, তাই সমাধান sparse হয় (অংশ ৩). দ্বিতীয়, ε নিজেই একটি hyperparameter, আর তার একক y-এর একক: মিনিটে মাপা সময়ে ε = ৫ মানে ৫ মিনিট, ঘণ্টায় মাপলে একই ε মানে ৫ ঘণ্টা। নিচের ছবিতে tube, তার কিনারা আর বাইরের বিন্দুর slack দেখুন।

SVR-এর tube আর তিন ধরনের বিন্দু

সবুজ রেখা অনুমান f(x); নীল ছায়া ±ε চওড়া tube

SVR epsilon tube with points inside, on the edge and outside ξ ξ* 2ε f + ε f − ε দূরত্ব km → মিনিট ভেতরে: loss ০, coefficient ০ কিনারায়: ০ < ∣coefficient∣ < C বাইরে: ∣coefficient∣ = C, loss = ξ
ছবি ২.১ — হলুদ আর লাল বিন্দুগুলোই support vector. নীল বিন্দু সরিয়ে দিলেও, যতক্ষণ সেগুলো tube-এর ভেতরে থাকে, সবুজ রেখা একটুও বদলায় না।

৩ · SVR-এর optimization — primal, dual আর support vector

SVR-এর আধুনিক রূপ প্রকাশ করেন Harris Drucker, Chris Burges, Linda Kaufman, Alex Smola আর Vladimir Vapnik (“Support Vector Regression Machines”, NIPS ১৯৯৬-এর কার্যবিবরণী, ১৯৯৭ সালে প্রকাশিত). প্রথমে linear রূপ f(x) = w·x + b দেখি; kernel পরে বসবে। প্রতিটি বিন্দুর জন্য দুটি slack variable: ξi (বিন্দু tube-এর ওপরে কতটা বাইরে) আর ξi* (নিচে কতটা বাইরে)।

min ½‖w‖² + C Σi (ξi + ξi*)
শর্ত: yi − w·xi − b ≤ ε + ξi,   w·xi + b − yi ≤ ε + ξi*,   ξi, ξi* ≥ ০

½‖w‖² রেখাকে যতটা সম্ভব সমতল (flat) রাখতে চায়, যা regularization (পর্ব ১৭)। C বলে tube-এর বাইরের প্রতি মিনিটের দাম কত: C বড় হলে model প্রায় সব বিন্দুকে tube-এ ঢোকাতে চায়, রেখা আঁকাবাঁকা হয়; C ছোট হলে সমতলতা জেতে। slack বাদ দিয়ে লিখলে সমস্যাটি হুবহু ½‖w‖² + C Σ Lε(yi − f(xi)), অর্থাৎ “ε-insensitive loss + L2 শাস্তি”, ঠিক soft margin SVM-এর “hinge loss + L2”-এর মতো।

পর্ব ১৬-এর Lagrange multiplier দিয়ে প্রতিটি শর্তে একটি করে multiplier বসান: ওপরের শর্তে αi, নিচেরটিতে αi*. w আর b-এ derivative শূন্য করলে পাওয়া যায় w = Σ(αi − αi*)xi আর Σ(αi − αi*) = ০. ফিরিয়ে বসালে dual problem:

max −½ Σi,j(αi − αi*)(αj − αj*) k(xi, xj) − ε Σ(αi + αi*) + Σ yi(αi − αi*)
শর্ত: Σ(αi − αi*) = ০,   ০ ≤ αi, αi* ≤ C

এখানে xi·xj-এর জায়গায় সরাসরি k(xi, xj) বসানো হয়েছে, পর্ব ২৯-এর kernel trick. অনুমান f(x) = Σ(αi − αi*) k(xi, x) + b. এটি একটি quadratic program, আর scikit-learn-এর SVR এটি libsvm-এর SMO-ধাঁচের solver দিয়ে সমাধান করে। KKT-এর complementary slackness থেকে আসে তিন ধরনের বিন্দু, আর তা থেকেই sparsity. নিচের stepper ছয়টি বিন্দুর একটি ছোট SVR-এ (linear kernel) এটি দেখায়।

x = 1…6 km; y = 1.4 1.9 3.1 5.5 4.6 5.8 (১০ মিনিটের এককে)linear kernel

            
  1. ফল। ছয়টি অর্ডারে linear SVR-এর রেখা f(x) = ০.৯x + ০.৬. প্রশ্ন: এই রেখা কোন অর্ডারগুলোর ওপর নির্ভর করে?
  2. Residual. চারটি অর্ডার রেখার সামান্য নিচে, একটি (x = ৪) অনেক ওপরে: সেটি দেরির অর্ডার।
  3. ভেতরের বিন্দু। x = ১, ৩, ৬-এর ∣r∣ < ০.৫. কোনো শর্ত আঁটসাঁট নয়, আর complementary slackness বলে ঢিলে শর্তের multiplier শূন্য। এদের dual coefficient ০: রেখায় এদের কোনো ভূমিকা নেই।
  4. কিনারার বিন্দু। x = ২ আর ৫ ঠিক f − ε রেখায়। শর্ত আঁটসাঁট কিন্তু slack শূন্য, তাই multiplier ০ আর C-এর মাঝে: −০.৬৩৩ আর −০.৩৬৭. চিহ্ন ঋণাত্মক, কারণ এরা নিচের কিনারায়।
  5. বাইরের বিন্দু। x = ৪ tube-এর ০.৮ ওপরে। ξ > ০ হলে KKT বলে multiplier ঠিক C. দেরির অর্ডারটির টান C = ১-এ আটকে যায়, যত দেরিই হোক।
  6. যাচাই। coefficient-এর যোগফল ০, আর Σ coef·x = ০.৯ = w. b আসে একটি কিনারার বিন্দু থেকে: x = ২-এ y = f − ε, তাই b = ১.৯ + ০.৫ − ১.৮ = ০.৬. ছয়টির মধ্যে মাত্র তিনটি support vector.

সংক্ষেপে: tube-এর ভেতরে → coefficient ০; কিনারায় → ০ < ∣coefficient∣ < C; বাইরে → ∣coefficient∣ = C. (কিনারার বিন্দুর coefficient বিরল ক্ষেত্রে ঠিক ০ বা C-ও হতে পারে; KKT কিনারায় পুরো [০, C] অনুমোদন করে।) coefficient শূন্য নয় এমন বিন্দুই support vector. scikit-learn-এ dual_coef_ রাখে αi − αi*, শুধু support vector-দের জন্য; support_ তাদের সূচক। একটি বিকল্প রূপও আছে: NuSVR (Schölkopf ও সহকর্মীরা, ২০০০), যেখানে ε-এর বদলে ν দেন, যা support vector-এর ভাগের একটি নিম্নসীমা আর tube-এর বাইরের বিন্দুর ভাগের একটি ঊর্ধ্বসীমা; ε তখন model নিজে ঠিক করে।

৪ · ব্রাউজারে SVR — ε বদলালে tube আর support vector

এবার আসল আকারে। নিচের module seed দিয়ে বাজারঘরের অর্ডার বানায়: দূরত্ব ০.৫ থেকে ২০ km, সময় একটি বাঁকা ধারা আর ৪ মিনিট SD-র এলোমেলো ভুল, সঙ্গে প্রায় ৫% অর্ডারে ২৫ থেকে ৪৫ মিনিটের বড় দেরি। সব ডেটা কাল্পনিক; আসল ধারা model জানে না। চারটি ব্লকই এখান থেকে ডেটা নেয়।

# বাজারঘর (কাল্পনিক দোকান): hub থেকে দূরত্ব (km) বনাম ডেলিভারির সময় (মিনিট)
import numpy as np

def eta_curve(km):                    # আসল বাঁকা ধারা (model জানে না)
    return 18 + 22 * np.log1p(km) + 5 * np.sin(km / 1.6)

def orders(n=80, seed=30, late=0.05):
    rng = np.random.default_rng(seed)
    km = rng.uniform(0.5, 20, n).round(2)
    mins = eta_curve(km) + rng.normal(0, 4, n)
    slow = rng.random(n) < late       # ~5% অর্ডারে বড় দেরি (জ্যাম, বৃষ্টি)
    mins[slow] += rng.uniform(25, 45, slow.sum())
    return km.reshape(-1, 1), mins.round(1)

প্রথম ব্লক বাঁ দিকে তিনটি loss আঁকে, তারপর ৮০টি অর্ডারে SVR(kernel="rbf") তিনটি ε-এ চালিয়ে support vector গোনে, আর ε = ৫-এর tube ডান দিকে আঁকে। C = ১০০ নেওয়া হয়েছে, কারণ y মিনিটে, শ-খানেকের ঘরে; scikit-learn-এর default C = ১.০ আর epsilon = ০.১ এই এককে খুব ছোট। ছবির লেখা ইংরেজিতে, কারণ পাতার matplotlib বাংলা অক্ষর ঠিকমতো আঁকে না।

import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import SVR
from bazar_eta import orders

r = np.linspace(-3, 3, 301)                   # residual; এখানে ε = δ = 1
fig, ax = plt.subplots(1, 2, figsize=(9, 3.6))
fig.subplots_adjust(bottom=0.16, wspace=0.3)
ax[0].plot(r, r**2 / 2, label="squared r^2/2")
ax[0].plot(r, np.where(abs(r) <= 1, r**2 / 2, abs(r) - 0.5), label="Huber, delta=1")
ax[0].plot(r, np.maximum(0, abs(r) - 1), label="eps-insensitive, eps=1")
ax[0].set_xlabel("residual r"); ax[0].set_ylabel("loss"); ax[0].legend(fontsize=8)

X, y = orders(n=80)                           # 80টি অর্ডার: km → মিনিট
grid = np.linspace(0, 20.5, 300).reshape(-1, 1)
print("eps  n_SV  share  train_MAE")
fits = {}
for eps in [1.0, 5.0, 10.0]:
    m = fits[eps] = SVR(kernel="rbf", C=100, epsilon=eps, gamma=0.05).fit(X, y)
    mae = np.mean(np.abs(y - m.predict(X)))
    print(f"{eps:3.0f} {len(m.support_):5d} {len(m.support_) / len(y):6.0%} {mae:10.2f}")

m = fits[5.0]; sv = m.support_; f = m.predict(grid)
coef = np.abs(m.dual_coef_[0])                # |alpha_i - alpha_i*|
print("eps=5: at C =", np.sum(np.isclose(coef, 100)),
      "| between 0 and C (on the edge) =", np.sum(coef < 100 - 1e-6))
ax[1].fill_between(grid[:, 0], f - 5, f + 5, alpha=0.2, label="tube f +/- 5")
ax[1].plot(grid, f, "g-", label="SVR, eps=5")
ax[1].scatter(X[:, 0], y, s=12, label="orders")
ax[1].scatter(X[sv, 0], y[sv], s=60, facecolors="none", edgecolors="r",
              label=f"support vectors ({len(sv)})")
ax[1].set_xlabel("distance from hub (km)"); ax[1].set_ylabel("delivery time (min)")
ax[1].legend(fontsize=7); plt.show()

আসল আউটপুট (ব্রাউজারের Python; ছবিটি ব্লকের নিচে আঁকা হয়):

eps  n_SV  share  train_MAE
  1    65    81%       5.15
  5    28    35%       5.36
 10    14    18%       6.84
eps=5: at C = 21 | between 0 and C (on the edge) = 7

ε বাড়লে support vector কমে: ε = ১ মিনিটে ৮০টির ৬৫টি (৮১%), ৫ মিনিটে ২৮টি (৩৫%), ১০ মিনিটে ১৪টি (১৮%). ভুলের SD ৪ মিনিট, তাই ১ মিনিটের tube-এ প্রায় কেউ আঁটে না, আর ১০ মিনিটের tube-এ বড় দেরিগুলো ছাড়া প্রায় সবাই আঁটে। দাম: ε বাড়ালে training MAE ৫.১৫ থেকে ৬.৮৪: চওড়া tube-এ ছোট ভুলগুলোকে model আর পাত্তা দেয় না, রেখা একটু ঢিলে হয়। ε = ৫-এ ২৮টি support vector-এর ২১টির ∣coefficient∣ ঠিক C = ১০০ (tube-এর বাইরে), ৭টি কিনারায়। ছবিতে লাল বৃত্ত দেওয়া বিন্দুগুলো tube-এর কিনারায় বা বাইরে, আর ওপরের বড় দেরির অর্ডারগুলো রেখাকে বেশি টানতে পারেনি: বাম দিকের বক্ররেখায় দেখুন, ε-insensitive loss বাইরে ঢাল ১-এ থেমে থাকে।

৫ · Kernel ridge regression — বন্ধ রূপে সমাধান

পর্ব ১৭-এ ridge regression-এর সমাধান দেখেছেন: n×p ডেটা X হলে w = (XᵀX + λIp)−1Xᵀy, যেখানে λ শাস্তির জোর। একটি matrix অভেদ (push-through identity) বলে (XᵀX + λIp)−1Xᵀ = Xᵀ(XXᵀ + λIn)−1; দুই পাশ (XᵀX + λI) দিয়ে গুণ করলেই যাচাই হয়, বা পর্ব ০৯-এর SVD দিয়ে দুই পাশ একই রূপে আসে। তাই:

w = Xᵀα,   α = (XXᵀ + λI)−1y

XXᵀ হলো n×n matrix, যার (i, j) ঘর xi·xj. এখন X-এর জায়গায় feature map φ(X) বসান, আর φ(xi)·φ(xj)-এর জায়গায় k(xi, xj). পাওয়া যায় kernel ridge regression (Saunders, Gammerman আর Vovk ১৯৯৮ সালে “dual variables”-এ ridge নামে এটি ML-এ আনেন; গণিতটি তার অনেক আগের):

α = (K + λI)−1y,   f(x*) = Σi αi k(xi, x*) = k(x*, X)α

এখানে K হলো n×n Gram matrix, Kij = k(xi, xj). RBF-এর φ অসীম মাত্রার, তাই w সরাসরি লেখা যায় না, কিন্তু α আর K দিয়ে অনুমান পুরোপুরি চলে। পর্ব ১০-এ দেখেছেন Gram matrix positive semidefinite; λ > ০ যোগ করলে K + λI-এর প্রতিটি eigenvalue অন্তত λ, অর্থাৎ positive definite. তাই সমাধান সবসময় আছে, অনন্য, আর Cholesky দিয়ে দ্রুত বের করা যায়; SciPy-তে solve(..., assume_a="pos") ঠিক এই পথ নেয়। (K + λI)α = y-কে সাজালে একটি সুন্দর অভেদ পাওয়া যায়:

y − Kα = λα, অর্থাৎ residuali = λ · αi

প্রতিটি αi তার নিজের residual-এর সমানুপাতিক। কোনো বিন্দুর residual ঠিক শূন্য না হলে তার α-ও শূন্য নয়: KRR-এর সমাধান স্বভাবতই dense. SVR-এ ভেতরের বিন্দুর loss-এর ঢাল ০ বলে coefficient ০ হয়; squared loss-এর ঢাল 2r কেবল r = ০-তেই শূন্য। নিচের stepper তিনটি বিন্দুতে পুরো হিসাব হাতে করে।

x = 0, 1, 2; y = 2, 4, 3; k(a, b) = 2^−(a − b)²γ = ln 2 ≈ 0.693

            
  1. Kernel বাছাই। γ = ln ২ নিলে RBF kernel হয় ২-এর ঘাত, তাই হাতে হিসাব সহজ: পাশাপাশি দুটি বিন্দুর মিল ০.৫, দুই ঘর দূরের মিল ০.০৬২৫.
  2. Gram matrix. তিনটি বিন্দুর প্রতিটি জোড়ার মিল দিয়ে ৩×৩ matrix K. কর্ণে ১, কারণ প্রতিটি বিন্দু নিজের সঙ্গে পুরো মেলে।
  3. শাস্তি যোগ। কর্ণে λ = ০.৫ যোগ করে K + λI. Determinant ২.৬৫০৪, ধনাত্মক; positive definite বলে সমাধান অনন্য।
  4. Linear system. (K + λI)α = y সমাধান করে α = [০.৬০১৩, ২.০৩৩৯, ১.২৯৭০]. প্রথম সারি বসিয়ে দেখুন: বাম দিক ঠিক ২, যা y-এর প্রথম মান।
  5. Residual = λα. Training বিন্দুতে অনুমান Kα, আর y − Kα হুবহু ০.৫ × α. তিনটি residual-ই শূন্য নয়, তাই তিনটি α-ও শূন্য নয়: dense.
  6. নতুন অর্ডার। x* = ১.৫-এর সঙ্গে তিনটি বিন্দুর মিল k*, তারপর k*·α = ২.৯২৭৩. scikit-learn-এর KernelRidge একই উত্তর দেয়, আট দশমিক পর্যন্ত।

৬ · KRR নিজে বানানো — scikit-learn-এর সঙ্গে মেলানো, λ আর γ

দ্বিতীয় ব্লক ৮০টি অর্ডারে RBF-এর Gram matrix নিজে বানায়, scipy.linalg.solve দিয়ে α বের করে, আর ৩০০টি আলাদা test অর্ডারে k(x*, X)α দিয়ে অনুমান করে। তারপর একই কাজ KernelRidge(kernel="rbf")-এ। scikit-learn-এ শাস্তির নাম alpha; এই পর্বের λ আর সেটি একই জিনিস, আর নিজের কোডের α (dual coefficient) হলো তার dual_coef_. শেষে কয়েকটি λ আর γ-এ test RMSE মাপে।

import numpy as np
from scipy.linalg import solve
from sklearn.kernel_ridge import KernelRidge
from bazar_eta import orders

X, y = orders(n=80)                       # train
Xt, yt = orders(n=300, seed=31)           # আলাদা test অর্ডার

def rbf(A, B, gamma):                     # k(a, b) = exp(-gamma (a - b)^2)
    return np.exp(-gamma * (A - B.T) ** 2)

gam, lam = 0.05, 1.0
K = rbf(X, X, gam)                        # 80 x 80 Gram matrix
alpha = solve(K + lam * np.eye(len(y)), y, assume_a="pos")
pred = rbf(Xt, X, gam) @ alpha            # f(x*) = k(x*, X) alpha

krr = KernelRidge(alpha=lam, kernel="rbf", gamma=gam).fit(X, y)
print("K:", K.shape, "| max |alpha - sklearn| =",
      f"{np.max(np.abs(alpha - krr.dual_coef_)):.1e}")
print("max |pred - sklearn| =", f"{np.max(np.abs(pred - krr.predict(Xt))):.1e}")
print("first preds:", np.round(pred[:3], 6))
print("non-zero alpha:", np.sum(np.abs(alpha) > 1e-8), "of", len(y))

ym = y.mean()                             # KernelRidge-এ intercept নেই
far = np.array([[60.0]])                  # ডেটার অনেক বাইরে, 60 km
print(f"60 km: raw y -> {krr.predict(far)[0]:.1f} min, centred y -> "
      f"{ym + KernelRidge(alpha=1, kernel='rbf', gamma=0.05).fit(X, y - ym).predict(far)[0]:.1f} min")

print("\ntest RMSE, centred y   gamma=0.005  0.05     1")
for lam in [0.01, 1.0, 100.0]:
    row = []
    for gam in [0.005, 0.05, 1.0]:
        m = KernelRidge(alpha=lam, kernel="rbf", gamma=gam).fit(X, y - ym)
        row.append(np.sqrt(np.mean((yt - ym - m.predict(Xt)) ** 2)))
    print(f"lambda={lam:<6g}", "".join(f"{v:9.2f}" for v in row))

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

K: (80, 80) | max |alpha - sklearn| = 2.4e-13
max |pred - sklearn| = 2.6e-13
first preds: [80.937173 46.931732 76.893436]
non-zero alpha: 80 of 80
60 km: raw y -> 0.0 min, centred y -> 71.2 min

test RMSE, centred y   gamma=0.005  0.05     1
lambda=0.01       10.43     9.09    13.63
lambda=1          10.18    10.63    11.91
lambda=100        15.08    14.85    15.64

মিল: নিজের α আর dual_coef_-এর সবচেয়ে বড় পার্থক্য প্রায় ১০−১৩, অনুমানেও তাই: শুধু floating-point-এর গোলমাল। scikit-learn ভেতরে একই সমীকরণ Cholesky দিয়ে সমাধান করে। Dense: ৮০টি α-র ৮০টিই শূন্য নয়। Intercept-এর ফাঁদ: ৬০ km দূরের (ডেটার বাইরে) অর্ডারে RBF-এর সব মিল প্রায় শূন্য, তাই অনুমান ০.০ মিনিট! KernelRidge কোনো intercept রাখে না, ডেটা থেকে দূরে সে শূন্যের দিকে নামে। y থেকে গড় বাদ দিয়ে fit করলে দূরে অনুমান গড়ে (৭১.২ মিনিট) ফেরে, যা অন্তত যুক্তিসংগত। λ আর γ: γ = ১ (প্রায় ১ km-এর মিল) প্রতিটি সারিতে খারাপ, কারণ রেখা প্রতিটি অর্ডারের দিকে বাঁকে (overfitting); λ = ১০০ সব γ-তে খারাপ, কারণ শাস্তি এত বেশি যে রেখা প্রায় গড়ে সমতল (underfitting). এখানে সবচেয়ে কম RMSE λ = ০.০১, γ = ০.০৫-এ। RMSE-তে বড় দেরিগুলোর বর্গও ঢুকেছে, তাই ছোট ভুলের SD মাত্র ৪ মিনিট হলেও সেরা সেটিং ৯ মিনিটের নিচে নামে না।

λ = ০ নয়: λ খুব ছোট হলে K + λI প্রায় singular, কারণ RBF-এর Gram matrix-এর অনেক eigenvalue শূন্যের খুব কাছে। তখন α বিশাল আর অস্থির হয়, আর assume_a="pos" ব্যর্থও হতে পারে। λ একটি regularization শুধু নয়, সংখ্যাগত স্থিরতার রক্ষাকবচও। আর মনে রাখুন, ব্রাউজারের NumPy-তে np.linalg.cholesky ব্যর্থ হলে error না দিয়ে চুপচাপ NaN ফেরায়; SciPy-র scipy.linalg ব্যর্থতা ধরে error দেয়।

৭ · KRR বনাম SVR — dense না sparse, আর কত দাম

দুটি model-এর অনুমান একই আকারের, তাই ভালো fit দুটিই দিতে পারে। পার্থক্য তিন জায়গায়। Loss: squared loss বড় ভুলে বর্গের জোরে টানে, ε-insensitive সরলরেখায়; বড় দেরির অর্ডার থাকলে SVR কম টলে। Sparsity: KRR সব n টি α রাখে, SVR শুধু support vector. দাম: KRR-এর fit মানে n×n matrix বানানো (মেমরি n²) আর তার Cholesky (প্রায় n³/৩ গুণ-যোগ), অর্থাৎ time complexity O(n³): n দ্বিগুণ হলে কাজ প্রায় আট গুণ। SVR-এর QP-র কোনো বন্ধ রূপ নেই; scikit-learn-এর docs বলে তার fit-এর সময় n-এর দ্বিঘাতের চেয়ে বেশি হারে বাড়ে। অনুমানে KRR প্রতিটি নতুন বিন্দুর জন্য n টি kernel মান গোনে, SVR শুধু support vector-এর সংখ্যার সমান।

তৃতীয় ব্লক n = ১০০ থেকে ৮০০ পর্যন্ত দুটি model চালিয়ে একই ২০০০টি test অর্ডারে MAE আর RMSE, শূন্য নয় এমন coefficient, আর fit ও অনুমানের সময় মাপে। KRR-এ y থেকে গড় বাদ দেওয়া হয়েছে (অংশ ৬-এর কারণে)।

import time
import numpy as np
from sklearn.kernel_ridge import KernelRidge
from sklearn.svm import SVR
from bazar_eta import orders

Xt, yt = orders(n=2000, seed=31)          # একই test অর্ডার সবার জন্য

def run(model, X, y, shift):
    t0 = time.perf_counter(); model.fit(X, y - shift)
    t1 = time.perf_counter(); p = model.predict(Xt) + shift
    t2 = time.perf_counter()
    mae = np.mean(np.abs(yt - p)); rmse = np.sqrt(np.mean((yt - p) ** 2))
    return mae, rmse, (t1 - t0) * 1000, (t2 - t1) * 1000

print("   n model  MAE   RMSE  non-zero  fit_ms  pred_ms")
for n in [100, 200, 400, 800]:
    X, y = orders(n=n, seed=30)
    krr = KernelRidge(alpha=1.0, kernel="rbf", gamma=0.05)
    svr = SVR(kernel="rbf", C=100, epsilon=5, gamma=0.05)
    for name, m, s in [("KRR", krr, y.mean()), ("SVR", svr, 0.0)]:
        mae, rmse, tf, tp = run(m, X, y, s)
        nz = np.sum(np.abs(m.dual_coef_) > 1e-8)
        print(f"{n:4d} {name:>5} {mae:5.2f} {rmse:6.2f} {nz:6d} {tf:9.1f} {tp:8.1f}")

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

   n model  MAE   RMSE  non-zero  fit_ms  pred_ms
 100   KRR  6.82  10.33    100       1.8      5.3
 100   SVR  5.73   9.46     37       2.1      9.2
 200   KRR  5.39   9.38    200       3.9      8.5
 200   SVR  5.20   9.33     52       3.9     12.0
 400   KRR  5.58   9.32    400      10.6     15.8
 400   SVR  5.13   9.28    106      12.0     23.8
 800   KRR  5.24   9.21    800      57.6     31.8
 800   SVR  5.07   9.26    215      39.1     47.3

ভুল: n বাড়লে দুটির MAE কমে (KRR ৬.৮২ থেকে ৫.২৪, SVR ৫.৭৩ থেকে ৫.০৭)। প্রতিটি n-এ SVR-এর MAE একটু কম, কারণ ৫% বড় দেরির টান তার কাছে C-তে আটকে থাকে। RMSE-তে পার্থক্য প্রায় নেই, আর n = ৮০০-এ KRR সামান্য এগিয়ে (৯.২১ বনাম ৯.২৬): squared loss-এ শেখা model squared metric-এ ভালো করে। Sparsity: KRR-এর সব n টি coefficient শূন্য নয়; SVR-এর ৩৭, ৫২, ১০৬ আর ২১৫টি, অর্থাৎ ২৬ থেকে ৩৭%. Support vector-ও n-এর সঙ্গে প্রায় সমানুপাতে বাড়ে। Fit-এর সময়: n ৪০০ থেকে ৮০০-তে KRR ১০.৬ থেকে ৫৭.৬ ms (সাড়ে পাঁচ গুণের মতো; n³-এর হিসাবে আট গুণ, কিন্তু ছোট n-এ স্থির খরচও মিশে থাকে), SVR ১২.০ থেকে ৩৯.১ ms. অনুমানের সময়: এখানে SVR কম kernel মান গুনেও KRR-এর চেয়ে ধীর। একটি সম্ভাব্য কারণ: এক feature-এ kernel গোনা খুব সস্তা, KRR সব কাজ একটি বড় NumPy matrix গুণে সারে, আর libsvm প্রতিটি নতুন বিন্দু আলাদা করে দেখে। Sparsity-র সুবিধা চোখে পড়ে যখন প্রতিটি kernel মান দামি (অনেক feature) আর n বড়। সব সময় ব্রাউজারের একটি run-এর; আপনার যন্ত্রে সংখ্যা আলাদা হবে, প্রবণতা মিলিয়ে দেখুন।

দিকKernel ridge (KRR)SVR
Losssquared, r²ε-insensitive, max(০, ∣r∣ − ε)
সমাধানবন্ধ রূপ: (K + λI)α = yquadratic program (libsvm, SMO-ধাঁচ)
Coefficientdense: সব n টি, residual = λαsparse: শুধু support vector
Hyperparameterλ, kernel-এর γC, ε, kernel-এর γ
Fit-এর দামমেমরি n², সময় প্রায় n³দ্বিঘাতের বেশি; ডেটা আর C-তে নির্ভরশীল
অনুমানের দামপ্রতি বিন্দুতে n টি kernel মানপ্রতি বিন্দুতে #SV টি kernel মান
বড় ভুলেবর্গের টান, বেশি টলেটান C-তে আটকে, কম টলে
বাড়তি পাওনাleave-one-out-এর বন্ধ রূপ; Gaussian process-এর গড়ছোট model, দ্রুত অনুমান

Gaussian process-এর সঙ্গে যোগ: একটি Gaussian process ধরে নেয় f-এর যেকোনো কয়েকটি মান একসঙ্গে multivariate Gaussian (পর্ব ১৯), যার covariance k দেয়, আর পর্যবেক্ষণে noise-এর variance σ². তখন x*-এ অনুমানের গড় k(x*, X)(K + σ²I)−1y, অর্থাৎ λ = σ² নিলে KRR-এর অনুমানের হুবহু সমান। Gaussian process এর সঙ্গে প্রতিটি অনুমানের অনিশ্চয়তাও দেয়, যা KRR দেয় না। পুরো গল্প পর্ব ৪৬ (Gaussian process — kernel দিয়ে অনিশ্চয়তাসহ অনুমান)-এ। আর n লাখে পৌঁছালে n×n matrix আর রাখাই যায় না; Nyström আর random feature দিয়ে কীভাবে এগোতে হয়, তা পর্ব ৩১ (বড় ডেটায় kernel — Nyström, random features আর কখন SVM নয়)-এর বিষয়।

৮ · Hyperparameter বাছাই — Pipeline আর GridSearchCV

SVR-এ তিনটি নব (C, ε, γ), KRR-এ দুটি (λ, γ), আর সবগুলোর মান ডেটার scale-এর ওপর নির্ভর করে। RBF দূরত্ব মাপে, তাই km আর অন্য feature একসঙ্গে থাকলে বড় এককের feature দূরত্ব দখল করে; StandardScaler লাগবেই, আর সেটি Pipeline-এর ভেতরে, যেন প্রতিটি fold-এ শুধু training অংশ থেকে গড় আর SD শেখে (AI-এর ভিত্তি কোর্সের পর্ব ৬৪)। বাছাই হবে cross-validation-এ grid search দিয়ে (AI-এর ভিত্তি কোর্সের পর্ব ৬৬), আর test set থাকবে তালাবদ্ধ, একদম শেষে একবার। কয়েকটি শুরুর নিয়ম:

  • ε: y-এর এককে মাপা। ভুলের SD-র কাছাকাছি বা তার কিছুটা নিচ থেকে খোঁজা শুরু করুন। StandardScaler শুধু X scale করে, y নয়; y-ও scale করলে ε-এর মানে বদলায়।
  • γ: scale করা X-এ γ = ১ মানে প্রায় এক SD দূরত্বে মিল e−১. scikit-learn-এর SVR-এর default gamma="scale", অর্থাৎ ১-কে (feature সংখ্যা × X-এর variance) দিয়ে ভাগ। লগ-স্কেলে (০.১, ১, ১০) খুঁজুন।
  • C আর λ: দুটিই লগ-স্কেলে। C বড় বা λ ছোট মানে কম শাস্তি, বেশি আঁকাবাঁকা রেখা।
  • KRR-এর intercept: TransformedTargetRegressor দিয়ে y-ও scale করুন, তাতে প্রতিটি fold-এ নিজের গড় বাদ যায়।
import numpy as np
from sklearn.compose import TransformedTargetRegressor
from sklearn.kernel_ridge import KernelRidge
from sklearn.model_selection import GridSearchCV, KFold
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVR
from bazar_eta import orders

X, y = orders(n=200, seed=30)             # train + CV
Xt, yt = orders(n=2000, seed=31)          # তালাবদ্ধ test, শেষে একবার
cv = KFold(5, shuffle=True, random_state=42)

svr = make_pipeline(StandardScaler(), SVR(kernel="rbf"))
krr = TransformedTargetRegressor(         # y-কেও scale: intercept-এর অভাব ঢাকে
    regressor=make_pipeline(StandardScaler(), KernelRidge(kernel="rbf")),
    transformer=StandardScaler())
grids = {
    "SVR": (svr, {"svr__C": [10, 100, 1000], "svr__epsilon": [1, 5, 10],
                  "svr__gamma": [0.3, 3, 30]}),
    "KRR": (krr, {"regressor__kernelridge__alpha": [0.01, 0.1, 1],
                  "regressor__kernelridge__gamma": [0.3, 3, 30]}),
}
for name, (model, grid) in grids.items():
    gs = GridSearchCV(model, grid, cv=cv,
                      scoring="neg_mean_absolute_error").fit(X, y)
    test_mae = np.mean(np.abs(yt - gs.predict(Xt)))
    best = {k.split("__")[-1]: v for k, v in gs.best_params_.items()}
    print(f"{name}: {len(gs.cv_results_['params'])} settings x 5 folds")
    print("  best:", best)
    print(f"  CV MAE = {-gs.best_score_:.2f} | test MAE = {test_mae:.2f}")

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

SVR: 27 settings x 5 folds
  best: {'C': 100, 'epsilon': 1, 'gamma': 3}
  CV MAE = 4.32 | test MAE = 5.16
KRR: 9 settings x 5 folds
  best: {'alpha': 0.1, 'gamma': 3}
  CV MAE = 4.41 | test MAE = 5.37

SVR ২৭টি সেটিং × ৫ fold = ১৩৫টি fit থেকে বেছেছে C = ১০০, ε = ১ মিনিট, γ = ৩ (scale করা km-এ; km-এর SD প্রায় ৫.৬ বলে আসল এককে প্রায় ৩/৫.৬² ≈ ০.০৯৫, অংশ ৪-এর ০.০৫-এর কাছাকাছি)। Scoring MAE বলে ছোট ε জিতেছে: tube সরু হলে model ছোট ভুলেও মন দেয়। KRR বেছেছে λ = ০.১, γ = ৩. CV বনাম test: দুটির CV MAE (৪.৩২, ৪.৪১) test MAE-র (৫.১৬, ৫.৩৭) চেয়ে কম। এটি প্রত্যাশিত: ২৭টি সেটিং-এর মধ্যে সেরাটির CV স্কোর একটু আশাবাদী, কারণ বাছাইয়ের সময় fold-এর এলোমেলো সৌভাগ্যও ধরা পড়ে; আর test-এর বড় দেরিগুলো আলাদা এলোমেলো টানে এসেছে। তাই রিপোর্টে best_score_ নয়, তালাবদ্ধ test-এর সংখ্যা দিন, বা nested CV চালান। এই ডেটায় দুটি model প্রায় সমান; ০.২ মিনিটের পার্থক্য একটি seed-এর একটি run, সাধারণ সিদ্ধান্ত নয় (পর্ব ২২-এর paired test দিয়ে যাচাই করুন)।

আরও গভীরে: SVR-এর পূর্ণ তত্ত্ব আর solver-এর খুঁটিনাটি Alex Smola আর Bernhard Schölkopf-এর “A tutorial on support vector regression” (Statistics and Computing, ২০০৪)-এ, আর তাঁদের বই Learning with Kernels (২০০২)-এ। libsvm-এর ভেতরের কৌশল (working set বাছাই, shrinking, kernel cache) Chih-Chung Chang আর Chih-Jen Lin-এর libsvm প্রবন্ধে (ACM TIST, ২০১১)। KRR-এর একটি বড় সুবিধা: leave-one-out residual বন্ধ রূপে পাওয়া যায়, H = K(K + λI)−1 হলে ei/(১ − Hii), তাই n বার fit না করেই LOO-CV চলে। Gaussian process আর kernel পদ্ধতির সম্পর্ক বিস্তারিত Rasmussen আর Williams-এর Gaussian Processes for Machine Learning (২০০৬)-এ।

পরীক্ষা ও ইন্টারভিউতে: (১) ε = ৫, residual −৮ হলে ε-insensitive loss? max(০, ৮ − ৫) = ৩. (২) SVR-এ কোন বিন্দু support vector? যাদের ∣r∣ ≥ ε, অর্থাৎ tube-এর কিনারায় বা বাইরে; বাইরেরগুলোর ∣α − α*∣ = C. (৩) KRR-এর বন্ধ রূপ? α = (K + λI)−1y, f(x*) = k(x*, X)α; residual = λα. (৪) KRR আর SVR-এর মূল পার্থক্য? squared বনাম ε-insensitive loss; dense বনাম sparse; বন্ধ রূপ বনাম QP. (৫) KRR আর Gaussian process-এর সম্পর্ক? λ = σ² হলে KRR-এর অনুমান GP-র posterior গড়; GP বাড়তি variance দেয়।

৯ · AI-এর যুগে — SVR আর KRR কোড যাচাই

“ডেলিভারির সময় অনুমানের জন্য SVR বানাও” বললে AI assistant দ্রুত চলনসই কোড দেয়। কিন্তু এই বিষয়ের ভুলগুলো চুপচাপ থাকে, error দেয় না।

AI প্রায়ই যা করেকেন সমস্যাকীভাবে ধরবেন
SVR() default রাখে, y মিনিটেepsilon=0.1, C=1.0 এই এককে অর্থহীন; প্রায় সব বিন্দু support vector, রেখা চ্যাপ্টাy-এর scale দেখুন; ε আর C grid-এ খুঁজুন; len(model.support_) ছাপুন
Scaler পুরো ডেটায় fit করে, তারপর split বা CVtest-এর গড় আর SD training-এ ঢোকে (leakage)Scaler Pipeline-এর ভেতরে; test তালাবদ্ধ
KernelRidge-এ intercept আছে ধরে নেয়নেই; ডেটা থেকে দূরে অনুমান শূন্যে নামেy কেন্দ্রে আনুন বা TransformedTargetRegressor; দূরের একটি x-এ অনুমান ছাপুন
“KRR sparse” বা “SVR-এর বন্ধ রূপ আছে” বলেউল্টো: KRR dense আর বন্ধ রূপের, SVR sparse আর QPdual_coef_-এর শূন্য নয় এমন মান গুনুন
np.linalg.inv(K) @ y লেখে, λ ছাড়াRBF Gram matrix প্রায় singular; inverse অস্থির আর ধীরλ > ০; scipy.linalg.solve(..., assume_a="pos")
best_score_-কে চূড়ান্ত ফল বলেবাছাইয়ের পক্ষপাতে আশাবাদীতালাবদ্ধ test বা nested CV; কয়েকটি seed

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

আমার কাছে ডেলিভারির ডেটা: km (hub থেকে দূরত্ব) আর minutes (ডেলিভারির সময়), প্রায় ২০০ সারি, কিছু অর্ডারে বড় দেরি। ১. scikit-learn SVR(kernel="rbf") আর KernelRidge(kernel="rbf") দুটির জন্য Pipeline বানাও, StandardScaler-সহ; KernelRidge-এ intercept নেই, তাই y কীভাবে সামলাবে লেখো। ২. C, epsilon, gamma আর alpha-র grid দাও লগ-স্কেলে, আর বলো epsilon কোন এককে মাপা হয় আর কেন default 0.1 এখানে খাটে না। ৩. GridSearchCV-তে MAE দিয়ে বাছাই, তারপর আলাদা test set-এ একবার মূল্যায়ন; best_score_ কেন আশাবাদী, ব্যাখ্যা করো। ৪. বাছাই করা SVR-এর support vector-এর সংখ্যা আর KRR-এর dual_coef_-এর শূন্য নয় এমন মানের সংখ্যা ছাপাও। ৫. তুমি যে parameter নাম আর default মান বলছ, সেগুলো কোন scikit-learn version-এর docs অনুযায়ী, তা লেখো।

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

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

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

প্র ০১Vapnik কেন regression-এ একটি “মরা অঞ্চল”-সহ loss বেছেছিলেন? ১৯৯০-এর দশকে SVR কী নিয়ে এসেছিল, আর robust পরিসংখ্যানের সঙ্গে তার সম্পর্ক কী?

১৯৯০-এর দশকের শুরুতে AT&T Bell Labs-এ Vapnik আর তাঁর সহকর্মীরা support vector classifier দাঁড় করান: সর্বোচ্চ margin, আর সমাধান নির্ভর করবে অল্প কয়েকটি বিন্দুর ওপর। Regression-এ একই কাঠামো আনতে একটি loss দরকার ছিল, যা শ্রেণিবিভাগের hinge loss-এর মতো আচরণ করে: যথেষ্ট ভালো অনুমানে শাস্তি শূন্য। ১৯৯৫ সালের বই The Nature of Statistical Learning Theory-তে Vapnik ε-insensitive loss দেন, আর ১৯৯৬ সালের NIPS সম্মেলনে Drucker, Burges, Kaufman, Smola ও Vapnik “Support Vector Regression Machines” প্রবন্ধে এটিকে পরীক্ষামূলকভাবে ridge regression আর regression tree-এর সঙ্গে তুলনা করেন।

মরা অঞ্চলের যুক্তি দুটি। প্রথম, sparsity: ভেতরের বিন্দুর multiplier শূন্য, তাই model শুধু support vector মনে রাখে, যা সেই সময়ের কম মেমরির কম্পিউটারে একটি বাস্তব সুবিধা ছিল। দ্বিতীয়, Vapnik-এর তত্ত্বে ε একটি “নির্ভুলতার সহনসীমা”: আপনি আগেই বলে দিচ্ছেন কতটা ভুল মেনে নেবেন, আর বাকি ক্ষমতা ব্যয় হচ্ছে রেখা সমতল রাখায়।

Robust পরিসংখ্যানের সঙ্গে মিলটি স্পষ্ট। Peter Huber ১৯৬৪ সালে দেখান, বড় ভুলে loss বর্গ নয়, সরলরৈখিক হলে কয়েকটি দূষিত পর্যবেক্ষণ অনুমানকে যত খুশি টানতে পারে না। ε-insensitive loss-এরও বাইরের দিক সরলরৈখিক, তাই একটি অর্ডারের টান C-তে আটকে থাকে। পার্থক্য হলো, Huber মাঝখানে বর্গ রাখে (ছোট ভুলেও শেখে), ε-loss মাঝখানে কিছুই শেখে না। ফলে ε খুব বড় হলে সত্যিকারের সংকেতও tube-এ হারিয়ে যায়।

পরে Schölkopf ও সহকর্মীরা ২০০০ সালে ν-SVR দেন, কারণ ব্যবহারকারীদের জন্য ε আগে থেকে জানা কঠিন ছিল; ν দিলে ε ডেটা থেকে আসে। এটি একটি পুনরাবৃত্ত শিক্ষা: তত্ত্বের সুন্দর hyperparameter বাস্তবে বাছাই করা কঠিন হলে নতুন parameterization আসে।

মূল উপলব্ধি: ε-insensitive loss একসঙ্গে তিনটি জিনিস দেয়: sparse সমাধান, বড় ভুলে সীমিত টান, আর একটি স্পষ্ট সহনসীমা; দাম হলো আরেকটি hyperparameter, যার একক y-এর একক।

প্র ০২খনির ভূতত্ত্বের kriging, পরিসংখ্যানের spline আর ML-এর kernel ridge: একই গণিত কেন তিনবার আলাদা নামে আবিষ্কৃত হলো, আর এ থেকে কী শেখার আছে?

১৯৫০-এর দশকে দক্ষিণ আফ্রিকার খনি প্রকৌশলী Danie Krige কয়েকটি বোরহোলের নমুনা থেকে আশপাশের সোনার পরিমাণ অনুমানের পদ্ধতি নিয়ে কাজ করেন। ফরাসি গণিতবিদ Georges Matheron ১৯৬০-এর দশকে এটিকে আনুষ্ঠানিক রূপ দেন আর নাম দেন kriging: কাছের নমুনাকে বেশি ওজন, আর ওজন আসে দূরত্বের একটি covariance function থেকে। সূত্রটি লিখলে দেখা যায় অনুমান k(x*, X)(K + σ²I)−1y, এই পর্বের KRR-এর হুবহু রূপ।

প্রায় একই সময়ে পরিসংখ্যানে smoothing spline-এর তত্ত্ব গড়ে ওঠে। George Kimeldorf আর Grace Wahba ১৯৭০–৭১ সালের প্রবন্ধে দেখান, spline-এর সমস্যার সমাধান ডেটা বিন্দুগুলোতে কেন্দ্র করা kernel-এর যোগফল, আর একটি Bayesian ব্যাখ্যাও আছে: Gaussian prior-এর posterior গড়। এটিই representer theorem-এর আদি রূপ। Wahba-র ১৯৯০ সালের বই Spline Models for Observational Data এই ধারাকে একত্র করে।

ML-এ ১৯৯০-এর দশকে SVM-এর জনপ্রিয়তার সঙ্গে kernel ধারণা আবার আসে, আর ১৯৯৮ সালে Saunders, Gammerman ও Vovk ridge regression-কে dual চলকে লিখে kernel বসান। প্রায় একই সময়ে Neal আর Williams-এর কাজে Gaussian process ML-এ জনপ্রিয় হয়। তিন সম্প্রদায় আলাদা ভাষায় কথা বলত: ভূতত্ত্বে variogram, পরিসংখ্যানে reproducing kernel Hilbert space, ML-এ feature map আর kernel trick.

শেখার বিষয় দুটি। প্রথম, একই estimator-এর একাধিক ব্যাখ্যা থাকতে পারে: KRR-কে regularized least squares হিসেবে পড়লে λ শাস্তি; GP হিসেবে পড়লে λ noise variance, আর বাড়তি পাওনা অনিশ্চয়তা। দ্বিতীয়, নতুন নাম দেখলে আগে সূত্রটি লিখে দেখুন; অনেক “নতুন” পদ্ধতি পুরোনো পদ্ধতির নতুন রূপ, আর পুরোনো সাহিত্য প্রায়ই কঠিন প্রশ্নের (যেমন hyperparameter বাছাই) ভালো উত্তর রাখে।

মূল উপলব্ধি: Kriging, smoothing spline, Gaussian process-এর গড় আর kernel ridge একই linear system সমাধান করে; পার্থক্য ব্যাখ্যায়, আর ব্যাখ্যা ঠিক করে আপনি বাড়তি কী পাবেন।

প্র ০৩SVR-এর sparsity কি সত্যিই বড় সুবিধা? ডেটা বাড়লে support vector-এর সংখ্যা কেমন আচরণ করে, আর কখন dense KRR-ই ভালো?

Sparsity-র প্রতিশ্রুতি হলো ছোট model আর দ্রুত অনুমান: n টির বদলে শুধু support vector মনে রাখা। কিন্তু কতগুলো support vector থাকবে, তা ডেটার noise আর ε-এর ওপর নির্ভর করে। Noise-এর SD যদি ε-এর চেয়ে বড় হয়, তাহলে বিন্দুগুলোর একটি স্থির ভাগ tube-এর বাইরে পড়বেই, আর n বাড়লে support vector-ও মোটামুটি সেই অনুপাতে বাড়ে। এই পাতার তৃতীয় ব্লকে n = ১০০ থেকে ৮০০-তে support vector-এর ভাগ ২৬% থেকে ৩৭%-এর মধ্যে থেকেছে, শূন্যের দিকে নামেনি। শ্রেণিবিভাগের SVM-এর জন্য Ingo Steinwart ২০০৩ সালে দেখান, noise থাকলে support vector-এর সংখ্যা n-এর সঙ্গে রৈখিক হারে বাড়ে; regression-এও একই ধরনের আচরণ প্রত্যাশিত, যদিও সঠিক হার loss আর ডেটার ওপর নির্ভর করে।

অর্থাৎ sparsity একটি ধ্রুব ভাগের সাশ্রয়, আকারের সাশ্রয় নয়। ৩০% support vector মানে অনুমানে kernel গোনার কাজ প্রায় তিন ভাগের এক ভাগ, যা অনেক feature-এর দামি kernel-এ কাজে আসে; কিন্তু তৃতীয় ব্লকের এক-feature ডেটায় এই সাশ্রয় সময়ের মাপে চোখেই পড়েনি। কিন্তু fit-এর সময়ে QP-র দাম থেকে যায়।

অন্যদিকে KRR-এর কিছু বাস্তব সুবিধা আছে। এর fit একটি Cholesky, যা অত্যন্ত অপ্টিমাইজড BLAS/LAPACK-এ চলে, তাই মাঝারি n-এ প্রায়ই দ্রুত। এর hyperparameter একটি কম (ε নেই)। Leave-one-out error বন্ধ রূপে পাওয়া যায়, তাই λ বাছাই সস্তা। আর Gaussian process হিসেবে পড়লে অনিশ্চয়তাও পাওয়া যায়। ডেটায় বড় outlier না থাকলে আর n কয়েক হাজারের মধ্যে থাকলে KRR একটি শক্ত, সহজ পছন্দ।

ঠিক উত্তর তাই কাজের ওপর নির্ভর করে: outlier আর দ্রুত অনুমান জরুরি হলে SVR; সরল বাছাই, অনিশ্চয়তা আর মাঝারি ডেটা হলে KRR; আর n অনেক বড় হলে দুটির কোনোটিই সরাসরি নয়, approximation দরকার।

মূল উপলব্ধি: SVR-এর sparsity noise-যুক্ত ডেটায় n-এর একটি ভাগ মাত্র; সিদ্ধান্ত নিন loss, অনুমানের গতি আর বাছাইয়ের সহজতা মিলিয়ে, এক শব্দের স্লোগানে নয়।

প্র ০৪২০০০-এর দশকে kernel পদ্ধতি ML-এর কেন্দ্রে ছিল, পরে বড় ডেটায় পিছিয়ে পড়ে। n³-এর দেয়াল কী, আর kernel পদ্ধতি এখনো কোথায় যুক্তিসংগত?

১৯৯০-এর শেষ থেকে ২০০০-এর দশকের বড় অংশ জুড়ে SVM আর kernel পদ্ধতি অনেক benchmark-এ শক্তিশালী ছিল: convex optimization, ভালো তত্ত্ব আর কম hyperparameter. কিন্তু এদের একটি গঠনগত সীমা আছে। Exact KRR-এ n×n Gram matrix রাখতে হয়: n = ১ লাখ হলে ১০১০টি সংখ্যা, float64-এ প্রায় ৮০ GB. Cholesky-র কাজ প্রায় n³/৩, যা n দশ গুণ হলে হাজার গুণ বাড়ে। SVR-এর solver পুরো matrix না রেখেও চলে, কিন্তু scikit-learn-এর docs বলে তার fit-এর সময় দ্বিঘাতের বেশি হারে বাড়ে, আর কয়েক দশ হাজার নমুনার পরে কঠিন হয়ে ওঠে।

এই দেয়াল ভাঙতে দুটি বড় ধারণা আসে। Christopher Williams আর Matthias Seeger ২০০১ সালে Nyström পদ্ধতি দেন: কয়েকটি landmark বিন্দু নিয়ে K-এর একটি low-rank approximation. Ali Rahimi আর Ben Recht ২০০৭ সালে random Fourier features দেন: RBF kernel-কে কয়েকশ এলোমেলো cosine feature-এর dot product দিয়ে আনুমানিকভাবে প্রকাশ, তারপর সাধারণ linear model. দুটিই পর্ব ৩১-এর বিষয়।

একই সময়ে বড় ডেটায় অন্য পদ্ধতি এগিয়ে যায়। ছবি, ভাষা আর শব্দে deep learning নিজের feature শেখে আর mini-batch SGD-তে বিশাল ডেটায় চলে; tabular ডেটায় gradient boosting প্রায়ই শক্তিশালী। তবে এটি “kernel মৃত” নয়। ছোট ও মাঝারি বৈজ্ঞানিক ডেটায় (কয়েকশ থেকে কয়েক হাজার নমুনা), যেখানে মসৃণ সম্পর্ক আর অনিশ্চয়তা জরুরি, kernel ridge আর Gaussian process এখনো ব্যবহৃত হয়, যেমন রসায়ন ও পদার্থবিজ্ঞানের কিছু গবেষণায় অণুর ধর্ম অনুমানে। Bayesian optimization-এ (যেমন hyperparameter tuning) Gaussian process একটি প্রচলিত হাতিয়ার। আর neural network-এর তত্ত্বে neural tangent kernel-এর মতো ধারণা kernel-এর ভাষাকেই আবার ফিরিয়ে আনে।

মূল উপলব্ধি: Kernel পদ্ধতির সীমা গঠনগত (n² মেমরি, প্রায় n³ সময়), তাই ছোট-মাঝারি ডেটায় এরা শক্তিশালী আর বড় ডেটায় approximation বা অন্য পদ্ধতি লাগে; সিদ্ধান্ত নিন ডেটার আকার আর প্রয়োজন দেখে, ফ্যাশন দেখে নয়।

প্র ০৫SVR train হয় ε-insensitive loss-এ, কিন্তু আমরা বাছাই করি MAE বা RMSE দিয়ে। এই অমিল কি সমস্যা? Model selection-এ overfitting কীভাবে ঢোকে, আর কীভাবে রিপোর্ট করবেন?

Training loss আর মূল্যায়নের metric আলাদা হওয়া স্বাভাবিক, এমনকি প্রায়ই কাম্য। Training loss বাছা হয় optimization সহজ করতে আর কাঙ্ক্ষিত আচরণ (sparsity, robustness) পেতে; metric বাছা হয় ব্যবসার প্রশ্ন থেকে। বাজারঘরের প্রশ্ন যদি “গড়ে কত মিনিট ভুল” হয়, MAE ঠিক; যদি বড় ভুল বিশেষভাবে খারাপ হয়, RMSE; যদি “৯০% অর্ডার প্রতিশ্রুত সময়ের মধ্যে” হয়, তাহলে quantile বা coverage (পর্ব ২৪)। Hyperparameter বাছাইয়ের scoring সেই metric-ই হওয়া উচিত, কারণ GridSearchCV যা মাপে, তাই অপ্টিমাইজ করে। এই পাতার চতুর্থ ব্লকে MAE দিয়ে বাছাই করায় ছোট ε জিতেছে; RMSE দিলে ফল আলাদা হতে পারত।

দ্বিতীয় সমস্যা আরও সূক্ষ্ম। Gavin Cawley আর Nicola Talbot ২০১০ সালে Journal of Machine Learning Research-এ “On over-fitting in model selection and subsequent selection bias in performance evaluation” প্রবন্ধে দেখান, অনেক hyperparameter সেটিং-এর মধ্যে CV দিয়ে সেরাটি বাছলে সেই সেরা CV স্কোর আশাবাদী হয়, আর kernel পদ্ধতির মতো নমনীয় model-এ এই পক্ষপাত দুটি পদ্ধতির তুলনার সিদ্ধান্তও উল্টে দিতে পারে। কারণ সরল: ২৭টি সেটিং-এর প্রত্যেকটির স্কোরে কিছু এলোমেলো ভাগ্য আছে, আর সর্বোচ্চটি বাছলে সেই ভাগ্যও বেছে নেওয়া হয়।

প্রতিকার পরিচিত: বাছাই আর মূল্যায়ন আলাদা ডেটায়। হয় একটি তালাবদ্ধ test set, যা শুধু একবার ছোঁয়া হয়, নয়তো nested CV (AI-এর ভিত্তি কোর্সের পর্ব ৬৬), যেখানে ভেতরের loop বাছাই করে আর বাইরের loop নিরপেক্ষভাবে মাপে। দুটি model তুলনা করতে একই fold-এ paired পার্থক্য দেখুন, কয়েকটি seed-এ, আর একটি run-এর ০.২ মিনিটের ব্যবধানে সিদ্ধান্ত নেবেন না।

মূল উপলব্ধি: Training loss আচরণ ঠিক করে, scoring metric বাছাই ঠিক করে, আর রিপোর্টের সংখ্যা আসে বাছাইয়ে না-ছোঁয়া ডেটা থেকে; তিনটিকে আলাদা রাখুন।

অনুশীলন

হিসাবগুলো খাতায় করুন, তারপর উত্তর মেলান। চাইলে পাতার ব্লকগুলোতে সংখ্যা বদলে যাচাই করুন।

  1. পূর্ণ numerical: দুটি অর্ডার x = ০ আর ১, y = ৩ আর ১. Kernel k(a, b) = ২−(a − b)² (RBF, γ = ln ২), λ = ০.৫. (ক) K আর K + λI লিখুন। (খ) α = (K + λI)−1y বের করুন। (গ) residual = λα যাচাই করুন। (ঘ) x* = ০.৫-এ অনুমান কত? (ঙ) একটি SVR-এ ε = ০.৫, আর চারটি বিন্দুর residual −০.২, ০.৫, ০.৯, −১.৪ হলে ε-insensitive loss-এর যোগফল কত, আর কয়টি বিন্দু support vector হতে পারে?

    (ক) দূরত্ব ১ → ২−১ = ০.৫, তাই K = [[১, ০.৫], [০.৫, ১]], K + λI = [[১.৫, ০.৫], [০.৫, ১.৫]]. (খ) Determinant = ২.২৫ − ০.২৫ = ২; inverse = ½ [[১.৫, −০.৫], [−০.৫, ১.৫]]. α = ½ [১.৫ × ৩ − ০.৫ × ১, −০.৫ × ৩ + ১.৫ × ১] = ½ [৪, ০] = [২, ০]. (গ) Kα = [২, ১]; y − Kα = [১, ০] = ০.৫ × [২, ০] ✓. দ্বিতীয় α শূন্য, কারণ তার residual কাকতালীয়ভাবে ঠিক শূন্য; সাধারণ ডেটায় এমন হয় না। (ঘ) k* = [২−০.২৫, ২−০.২৫] = [০.৮৪০৯, ০.৮৪০৯]; f = ০.৮৪০৯ × ২ + ০ = ১.৬৮১৮. (ঙ) loss: ০, ০, ০.৪, ০.৯; যোগফল ১.৩. Support vector হলো ∣r∣ ≥ ε: ০.৫, ০.৯, −১.৪, অর্থাৎ ৩টি: ০.৯ আর −১.৪ বাইরে, তাই নিশ্চিতভাবে (∣coef∣ = C); ০.৫ কিনারায়, সাধারণত ০ আর C-এর মাঝের coefficient নিয়ে। ভেতরের −০.২ কখনো নয়।

  2. সমালোচনা ও নকশা: একজন বিশ্লেষক লিখেছেন: “পুরো ডেটায় StandardScaler চালিয়ে km আর minutes দুটিই scale করেছি। তারপর SVR() default দিয়ে GridSearchCV-তে শুধু C খুঁজেছি, আর best_score_ রিপোর্ট করেছি। KRR-ও চেষ্টা করেছি, কিন্তু সেটি sparse নয় বলে বাদ দিয়েছি। Support vector ৯৮%, তাই model ডেটা খুব ভালো শিখেছে।” ভুলগুলো ধরুন আর একটি ভালো নকশা দিন।

    সমস্যা: (১) Split-এর আগে পুরো ডেটায় scaler: test-এর গড় আর SD training-এ ঢুকেছে। (২) y scale করার পর default epsilon=0.1 মানে y-এর SD-র এক দশমাংশ; এটি হয়তো ঠিক, হয়তো নয়, কিন্তু খোঁজা হয়নি; γ-ও খোঁজা হয়নি। (৩) ৯৮% support vector ভালো শেখার লক্ষণ নয়: বলে tube noise-এর তুলনায় অনেক সরু, প্রায় সব বিন্দু কিনারায় বা বাইরে, sparsity-র সুবিধা হারিয়ে গেছে। (৪) best_score_ বাছাইয়ের পক্ষপাতে আশাবাদী। (৫) “sparse নয়” KRR বাদ দেওয়ার যুক্তি নয়; মাঝারি n-এ KRR দ্রুত ও সমান ভালো হতে পারে। ভালো নকশা: আগে train/test ভাগ; Pipeline(StandardScaler, SVR), প্রয়োজনে TransformedTargetRegressor; C, ε, γ লগ-স্কেলের grid-এ, scoring ব্যবসার metric (যেমন MAE); KRR-ও একই fold-এ; একটি সরল baseline; শেষে তালাবদ্ধ test-এ একবার MAE, support vector-এর সংখ্যা আর অনুমানের সময় রিপোর্ট।

  3. আউটপুট অনুমান করুন: চালানোর আগে তিনটি লাইন লিখুন।
    import numpy as np
    r = np.array([-7, -5, -2, 0, 3, 5.5, 12])
    L = np.maximum(0, np.abs(r) - 5)
    print(L)
    print(int(np.sum(np.abs(r) >= 5)), L.sum())
    K = np.array([[1, 0.5], [0.5, 1]])
    a = np.linalg.solve(K + 0.5 * np.eye(2), [3, 1])
    print(a, np.array([3, 1]) - K @ a)

    ডেস্কটপে সত্যিকারের run (Python 3.14, NumPy 2.5):

    [2.  0.  0.  0.  0.  0.5 7. ]
    4 9.5
    [2. 0.] [1. 0.]

    ε = ৫-এ −৭-এর loss ২, −৫ ঠিক কিনারায় বলে ০, ৫.৫-এর ০.৫, ১২-এর ৭. ∣r∣ ≥ ৫ এমন মান চারটি (−৭, −৫, ৫.৫, ১২): SVR-এ শুধু এরাই support vector হতে পারে। যোগফল ৯.৫. শেষ লাইন অনুশীলন ১-এর KRR: α = [২, ০], আর residual [১, ০] = ০.৫ × α.

  4. কোডিং: দুটি function লিখুন: krr_fit(X, y, lam, gamma), যা y থেকে গড় বাদ দিয়ে RBF Gram matrix-এ scipy.linalg.cho_factor আর cho_solve দিয়ে α বের করে, আর krr_predict(model, Xnew), যা গড় ফিরিয়ে যোগ করে। বাজারঘরের ৮০টি অর্ডারে (λ = ১, γ = ০.০৫) কেন্দ্রে আনা y-তে চালানো KernelRidge-এর সঙ্গে মেলান, আর ৬০ km-এ অনুমান ছাপুন।
    import numpy as np
    from scipy.linalg import cho_factor, cho_solve
    from sklearn.kernel_ridge import KernelRidge
    from bazar_eta import orders
    
    def krr_fit(X, y, lam, gamma):
        ym = y.mean()
        K = np.exp(-gamma * (X - X.T) ** 2)
        c = cho_factor(K + lam * np.eye(len(y)))
        return X, cho_solve(c, y - ym), ym, gamma
    
    def krr_predict(model, Xnew):
        X, alpha, ym, gamma = model
        return ym + np.exp(-gamma * (Xnew - X.T) ** 2) @ alpha
    
    X, y = orders(n=80)
    Xt, yt = orders(n=300, seed=31)
    mine = krr_predict(krr_fit(X, y, 1.0, 0.05), Xt)
    ref = KernelRidge(alpha=1.0, kernel="rbf", gamma=0.05).fit(X, y - y.mean())
    print(f"{np.max(np.abs(mine - (ref.predict(Xt) + y.mean()))):.1e}")
    print(np.round(krr_predict(krr_fit(X, y, 1.0, 0.05), np.array([[60.0]])), 1))

    ডেস্কটপে সত্যিকারের run (Python 3.14, NumPy 2.5, SciPy 1.18, scikit-learn 1.9) ছাপে:

    1.4e-13
    [71.2]

    পার্থক্য ১০−১৩-এর ঘরে, অর্থাৎ হুবহু একই সমাধান। ৬০ km-এ অনুমান ৭১.২ মিনিট, training-এর গড়: কেন্দ্রে আনা y ছাড়া এটি ০ হতো। (X - X.T) শুধু এক feature-এ কাজ করে; বহু feature-এ sklearn.metrics.pairwise.rbf_kernel বা বর্গ-দূরত্বের সূত্র লাগবে। cho_factor একবার করলে একই λ-তে নতুন y-এর জন্য আবার factor করতে হয় না।

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

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

ক্রমRBF kernel দিয়ে kernel ridge regression নিজে চালানোর ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. Training ডেটা থেকে y-এর গড় বাদ দেওয়া (intercept-এর জন্য)
  2. প্রতিটি জোড়া training বিন্দুর kernel মান দিয়ে Gram matrix K বানানো
  3. কর্ণে λ যোগ করে K + λI বানানো
  4. Cholesky দিয়ে (K + λI)α = y সমাধান করে α পাওয়া
  5. নতুন বিন্দুর সঙ্গে training বিন্দুগুলোর kernel মান k(x*, X) গোনা
  6. k(x*, X)α-এর সঙ্গে গড় ফিরিয়ে যোগ করে অনুমান দেওয়া

একটি SVR-এ ε = ৫ মিনিট। একটি অর্ডারের আসল সময় অনুমানের চেয়ে ৮ মিনিট কম (residual −৮)। ε-insensitive loss কত?

  • ০
  • ৮
  • ৩
  • ৬৪

একটি fit করা SVR-এ (ε-tube সহ) কোন training বিন্দুগুলোর dual coefficient (α − α*) নিশ্চিতভাবে শূন্য?

  • যাদের residual-এর মাপ ε-এর চেয়ে বেশি (tube-এর বাইরে)
  • যাদের residual-এর মাপ ε-এর চেয়ে কম (tube-এর ভেতরে)
  • কোনো বিন্দুরই নয়, সমাধান dense
  • প্রতিটি বিন্দুর কিছু না কিছু ভূমিকা থাকে, তাই কারও নয়

Kernel ridge regression-এ α = (K + λI)−1y. Training বিন্দু i-এর residual yi − (Kα)i কীসের সমান?

  • সবসময় ০
  • αi / λ
  • Kii · yi
  • λ · αi

একই ডেটা আর একই C, γ রেখে SVR-এর ε ১ থেকে ১০-এ বাড়ালে সাধারণত কী ঘটে?

  • Support vector কমে, আর training-এর ভুল সাধারণত একটু বাড়ে
  • Support vector বাড়ে
  • কিছুই বদলায় না, কারণ ε শুধু অনুমানের পরিসর দেখায়
  • X-এর scale বদলে যায়

scikit-learn-এর KernelRidge(kernel="rbf") সব মিনিট-মাপের y (গড় প্রায় ৭০) দিয়ে fit করা হলো। Training ডেটার অনেক বাইরের একটি x-এ অনুমান কোন দিকে যায়?

  • training-এর y-এর গড়ের দিকে (প্রায় ৭০)
  • অসীমের দিকে
  • শূন্যের দিকে
  • সবচেয়ে কাছের training বিন্দুর y-এর সমান

n টি training বিন্দুতে exact kernel ridge regression fit করার মেমরি আর সময়ের মোটামুটি হার কত?

  • মেমরি O(n), সময় O(n)
  • মেমরি O(n²), সময় O(n³)
  • মেমরি O(n³), সময় O(n²)
  • মেমরি O(p²), সময় O(p³), n-এর ওপর নির্ভর করে না

শব্দকোষ

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

মনে রাখুন

  1. এক আকার: SVR আর KRR দুটিরই অনুমান Σ βi k(xi, x) (representer theorem); loss আলাদা বলে β আলাদা।
  2. ε-insensitive loss: max(০, ∣r∣ − ε). ভেতরে coefficient ০, কিনারায় ০ < ∣coef∣ < C, বাইরে ∣coef∣ = C. ε y-এর এককে মাপা; ε বাড়লে support vector কমে।
  3. KRR: α = (K + λI)−1y, f(x*) = k(x*, X)α; K + λI positive definite, তাই Cholesky. residual = λα, তাই dense. KernelRidge-এ intercept নেই।
  4. দাম: KRR-এ মেমরি n², সময় প্রায় n³; SVR-এর QP দ্বিঘাতের বেশি, কিন্তু অনুমানে শুধু support vector. λ = σ² হলে KRR-এর অনুমান Gaussian process-এর গড়।
  5. বাছাই: Pipeline-এ StandardScaler, C/ε/γ/λ লগ-স্কেলের grid-এ, ব্যবসার metric দিয়ে; best_score_ আশাবাদী, তাই তালাবদ্ধ test বা nested CV.

পরের পর্বে: n যখন কয়েক লাখ, n×n matrix আর রাখা যায় না। পর্ব ৩১ (বড় ডেটায় kernel — Nyström, random features আর কখন SVM নয়) দেখাবে কয়েকটি landmark বা এলোমেলো feature দিয়ে kernel-কে কীভাবে আনুমানিক করা যায়, আর কখন kernel ছেড়ে অন্য model নেওয়াই ভালো।

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

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