رگرسیون خطی دروازهی ورود به دنیای یادگیری ماشین است؛ الگوریتمی بنیادین که پایههای اصلی آموزش مدلها یعنی تعریف تابع هزینه، گرادیان کاهشی و بهینهسازی پارامترها را به شفافترین شکل ممکن نشان میدهد. تسلط بر این مفهوم به شما امکان میدهد الگوهای اساسی یادگیری نظارتشده را درک کرده و در مسائل واقعی مانند پیشبینی قیمت، تحلیل تقاضا و ارزیابی دادهها به کار بگیرید.
در این درس علاوه بر درک شهودی و ریاضیاتی مفاهیمی مانند میانگین مربعات خطا (MSE) و معادلهی نرمال، رگرسیون خطی ساده و چندگانه را ابتدا از صفر با پایتون پیادهسازی میکنید و سپس پیادهسازی صنعتی آن را با کتابخانهی scikit-learn فرا میگیرید. تمام مراحل این درس نیازی به تجهیزات پردازشی پیچیده ندارد و کدهای آن بهآسانی روی پردازندههای معمولی (CPU) بدون هیچ وابستگی ابری قابل اجرا هستند.
رگرسیون خطی بهترین خط مستقیم ممکن را از میان دادههای شما عبور میدهد. این مدل در واقع «Hello World» دنیای یادگیری ماشین است.
اهداف یادگیری
- بهدستآوردن رابطههای بهروزرسانی گرادیان کاهشی برای میانگین مربعات خطا و پیادهسازی رگرسیون خطی از صفر
- مقایسهی گرادیان کاهشی و معادلهی نرمال از نظر پیچیدگی محاسباتی و تعیین زمان مناسب برای استفاده از هرکدام
- ساخت مدل رگرسیون خطی چندگانه با استانداردسازی ویژگیها و تفسیر وزنهای یادگرفتهشده
- توضیح نحوهی جلوگیری رگرسیون ریج (تنظیم L2) از بیشبرازش از طریق جریمهکردن وزنهای بزرگ
صورت مسئله
دادههایی شامل متراژ چند خانه و قیمت فروش آنها دارید و میخواهید قیمت یک خانهی جدید را بر اساس متراژ آن پیشبینی کنید. شاید بتوان روی نمودار پراکندگی چشمی حدسهایی زد، اما شما به یک فرمول نیاز دارید؛ خطی که به بهترین شکل روی دادهها بنشیند تا بتوانید هر متراژی را به آن بدهید و قیمت پیشبینیشده را تحویل بگیرید.
رگرسیون خطی (linear regression) همین خط را در اختیارتان میگذارد. مهمتر از آن، کل چرخهی آموزش در یادگیری ماشین را به شما معرفی میکند: تعریف مدل، تعریف تابع هزینه و بهینهسازی پارامترها. همهی الگوریتمهای یادگیری ماشین دقیقاً از همین الگو پیروی میکنند. اگر این فرایند را در این حالتِ پایهای بهخوبی یاد بگیرید، ساختارش را در تمام مباحث بعدی تشخیص خواهید داد.
کاربرد این روش محدود به مسائل ساده نیست؛ رگرسیون خطی در سیستمهای عملیاتی واقعی برای پیشبینی تقاضا، تحلیل آزمونهای A/B، مدلسازی مالی و همچنین بهعنوان مدل پایه (baseline) در تمام مسائل رگرسیون استفاده میشود.
مفاهیم پایه
مدل
رگرسیون خطی فرض میکند رابطهای خطی میان ورودی () و خروجی () برقرار است:
w(وزن/شیب): میزان تغییر بهازای 1 واحد افزایش درb(بایاس/عرض از مبدا): مقدار وقتی که
این فرمول برای چند ورودی (ویژگی) بهشکل زیر تعمیم مییابد:
یا بهصورت برداری:
هدف: پیدا کردن مقادیری برای و که در تمام نمونههای آموزشی، مقدار پیشبینیشدهی را تا جای ممکن به مقدار واقعی نزدیک کند.
تابع هزینه (میانگین مربعات خطا)
میزان «نزدیک بودن» را چطور اندازه میگیرید؟ به عددی واحد نیاز دارید که میزان خطای پیشبینیها را نشان دهد. رایجترین معیار، میانگین مربعات خطا یا MSE (مخفف Mean Squared Error) است:
چرا خطا را به توان 2 میرسانیم؟ به دو دلیل: اول اینکه خطاهای بزرگ را بسیار شدیدتر از خطاهای کوچک جریمه میکند (خطای 10 بهاندازهی 100 برابر بدتر از خطای 1 است، نه 10 برابر). دوم اینکه تابع درجهدو، هموار و در همهجا مشتقپذیر است و کار بهینهسازی را بسیار ساده میکند.
تابع هزینه سطحی هندسی میسازد. برای یک وزن () و یک بایاس ()، سطح MSE شبیه به یک کاسه (یک سهمیگون کوژ) است. کف این کاسه نقطهای است که MSE در آن کمینه میشود؛ بنابراین، آموزش مدل یعنی پیدا کردن همین کف کاسه.
گرادیان کاهشی
گرادیان کاهشی (gradient descent) با برداشتن گامهایی رو به پایین، کف کاسه را پیدا میکند.
گرادیانها دو نکته را مشخص میکنند: پارامترها را در چه جهتی حرکت دهیم و چقدر جابهجا کنیم.
برای تابع MSE بههمراه :
قاعدهی بهروزرسانی پارامترها:
نرخ یادگیری (learning rate) طول هر گام را کنترل میکند. اگر بیش از حد بزرگ باشد، از نقطهی کمینه رد میشوید و مدل واگرا میشود؛ اگر خیلی کوچک باشد، آموزش بیاندازه طول میکشد. مقادیر اولیهی معمول عبارتاند از: 0.01، 0.001 یا 0.0001.
معادلهی نرمال (راهحل تحلیلی)
بهطور خاص برای رگرسیون خطی، فرمولی مستقیم وجود دارد که وزنهای بهینه را بدون نیاز به تکرار به دست میآورد:
این فرمول با معکوس کردن یک ماتریس، مقدار را در یک گام محاسبه میکند. این شیوه برای مجموعهدادههای کوچک فوقالعاده است؛ اما برای دادههای حجیم (میلیونها سطر یا هزاران ویژگی)، استفاده از گرادیان کاهشی اولویت دارد، زیرا هزینهی محاسباتی معکوس کردن ماتریس متناسب با برحسب تعداد ویژگیها رشد میکند.
رگرسیون خطی چندگانه
با وجود چند ویژگی، مدل بهشکل زیر درمیآید:
همهچیز مشابه قبل پیش میرود: MSE تابع هزینه باقی میماند و گرادیان کاهشی تمام وزنها را همزمان بهروزرسانی میکند. تنها تفاوت این است که اینبار بهجای یک خط، یک ابرصفحه (hyperplane) را برازش میدهید.
در این حالت مقیاسبندی ویژگیها اهمیت زیادی پیدا میکند. اگر بازهی تغییرات یک ویژگی بین 0 تا 1 و ویژگی دیگر بین 0 تا 1,000,000 باشد، سطح تابع هزینه کشیده میشود و گرادیان کاهشی بهسختی همگرا خواهد شد. بنابراین پیش از شروع آموزش، ویژگیها را استاندارد کنید (میانگین را کم و بر انحراف معیار تقسیم کنید).
رگرسیون چندجملهای
اگر رابطهی بین دادهها خطی نباشد چه؟ باز هم میتوانید با ساختن ویژگیهای چندجملهای از رگرسیون خطی استفاده کنید:
این مدل همچنان رگرسیون «خطی» نامیده میشود، چون رابطه نسبت به وزنها () خطی است؛ شما فقط از ویژگیهای غیرخطیِ استفاده کردهاید.
چندجملهایهای درجهبالاتر میتوانند منحنیهای پیچیدهتری را برازش دهند، اما خطر بیشبرازش (overfitting) را بالا میبرند. یک چندجملهای درجهی 10 شاید دقیقاً از تمام 10 نقطهی دادهی شما عبور کند، ولی روی دادههای جدید پیشبینیهای بسیار ضعیفی ارائه خواهد داد.
ضریب تعیین (امتیاز R-Squared)
معیار MSE نشان میدهد چقدر خطا دارید، اما این عدد به مقیاس بستگی دارد. ضریب تعیین یا معیاری مستقل از مقیاس به دست میدهد:
- : پیشبینی بینقص
- : عملکرد مدل تفاوتی با پیشبینی مداومِ میانگین ندارد
- : عملکرد مدل حتی از پیشبینی میانگین هم بدتر است
پیشدرآمدی بر تنظیم مدل (رگرسیون ریج)
وقتی تعداد ویژگیها زیاد باشد، مدل ممکن است با نسبت دادن وزنهای بزرگ دچار بیشبرازش شود. رگرسیون ریج (Ridge regression یا تنظیم L2) یک جریمه به تابع هزینه اضافه میکند:
این جملهی جریمه مانع از بزرگ شدن وزنها میشود. هایپرپارامتر این تعادل را مدیریت میکند: هرچه بزرگتر باشد، وزنها کوچکتر میشوند و قدرت تنظیم مدل افزایش مییابد. این موضوع را در درسهای آینده مفصل بررسی خواهیم کرد؛ فعلاً در همین حد بدانید که چنین روشی وجود دارد و به چه دلیلی به کار میآید.
پیادهسازی از صفر
گام 1: تولید دادههای نمونه
import random
import math
random.seed(42)
TRUE_W = 3.0
TRUE_B = 7.0
N_SAMPLES = 100
X = [random.uniform(0, 10) for _ in range(N_SAMPLES)]
y = [TRUE_W * x + TRUE_B + random.gauss(0, 2.0) for x in X]
print(f"Generated {N_SAMPLES} samples")
print(f"True relationship: y = {TRUE_W}x + {TRUE_B} (+ noise)")
print(f"First 5 points: {[(round(X[i], 2), round(y[i], 2)) for i in range(5)]}")
گام 2: رگرسیون خطی از صفر با گرادیان کاهشی
class LinearRegression:
def __init__(self, learning_rate=0.01):
self.w = 0.0
self.b = 0.0
self.lr = learning_rate
self.cost_history = []
def predict(self, X):
return [self.w * x + self.b for x in X]
def compute_cost(self, X, y):
predictions = self.predict(X)
n = len(y)
cost = sum((pred - actual) ** 2 for pred, actual in zip(predictions, y)) / n
return cost
def compute_gradients(self, X, y):
predictions = self.predict(X)
n = len(y)
dw = (2 / n) * sum((pred - actual) * x for pred, actual, x in zip(predictions, y, X))
db = (2 / n) * sum(pred - actual for pred, actual in zip(predictions, y))
return dw, db
def fit(self, X, y, epochs=1000, print_every=200):
for epoch in range(epochs):
dw, db = self.compute_gradients(X, y)
self.w -= self.lr * dw
self.b -= self.lr * db
cost = self.compute_cost(X, y)
self.cost_history.append(cost)
if epoch % print_every == 0:
print(f" Epoch {epoch:4d} | Cost: {cost:.4f} | w: {self.w:.4f} | b: {self.b:.4f}")
return self
def r_squared(self, X, y):
predictions = self.predict(X)
y_mean = sum(y) / len(y)
ss_res = sum((actual - pred) ** 2 for actual, pred in zip(y, predictions))
ss_tot = sum((actual - y_mean) ** 2 for actual in y)
return 1 - (ss_res / ss_tot)
print("=== Training Linear Regression (Gradient Descent) ===")
model = LinearRegression(learning_rate=0.005)
model.fit(X, y, epochs=1000, print_every=200)
print(f"\nLearned: y = {model.w:.4f}x + {model.b:.4f}")
print(f"True: y = {TRUE_W}x + {TRUE_B}")
print(f"R-squared: {model.r_squared(X, y):.4f}")
گام 3: معادلهی نرمال (راهحل تحلیلی)
class LinearRegressionNormal:
def __init__(self):
self.w = 0.0
self.b = 0.0
def fit(self, X, y):
n = len(X)
x_mean = sum(X) / n
y_mean = sum(y) / n
numerator = sum((X[i] - x_mean) * (y[i] - y_mean) for i in range(n))
denominator = sum((X[i] - x_mean) ** 2 for i in range(n))
self.w = numerator / denominator
self.b = y_mean - self.w * x_mean
return self
def predict(self, X):
return [self.w * x + self.b for x in X]
def r_squared(self, X, y):
predictions = self.predict(X)
y_mean = sum(y) / len(y)
ss_res = sum((actual - pred) ** 2 for actual, pred in zip(y, predictions))
ss_tot = sum((actual - y_mean) ** 2 for actual in y)
return 1 - (ss_res / ss_tot)
print("\n=== Normal Equation (Closed-Form) ===")
model_normal = LinearRegressionNormal()
model_normal.fit(X, y)
print(f"Learned: y = {model_normal.w:.4f}x + {model_normal.b:.4f}")
print(f"R-squared: {model_normal.r_squared(X, y):.4f}")
گام 4: رگرسیون خطی چندگانه
class MultipleLinearRegression:
def __init__(self, n_features, learning_rate=0.01):
self.weights = [0.0] * n_features
self.bias = 0.0
self.lr = learning_rate
self.cost_history = []
def predict_single(self, x):
return sum(w * xi for w, xi in zip(self.weights, x)) + self.bias
def predict(self, X):
return [self.predict_single(x) for x in X]
def compute_cost(self, X, y):
predictions = self.predict(X)
n = len(y)
return sum((pred - actual) ** 2 for pred, actual in zip(predictions, y)) / n
def fit(self, X, y, epochs=1000, print_every=200):
n = len(y)
n_features = len(X[0])
for epoch in range(epochs):
predictions = self.predict(X)
errors = [pred - actual for pred, actual in zip(predictions, y)]
for j in range(n_features):
grad = (2 / n) * sum(errors[i] * X[i][j] for i in range(n))
self.weights[j] -= self.lr * grad
grad_b = (2 / n) * sum(errors)
self.bias -= self.lr * grad_b
cost = self.compute_cost(X, y)
self.cost_history.append(cost)
if epoch % print_every == 0:
print(f" Epoch {epoch:4d} | Cost: {cost:.4f}")
return self
def r_squared(self, X, y):
predictions = self.predict(X)
y_mean = sum(y) / len(y)
ss_res = sum((actual - pred) ** 2 for actual, pred in zip(y, predictions))
ss_tot = sum((actual - y_mean) ** 2 for actual in y)
return 1 - (ss_res / ss_tot)
random.seed(42)
N = 100
X_multi = []
y_multi = []
for _ in range(N):
size = random.uniform(500, 3000)
bedrooms = random.randint(1, 5)
age = random.uniform(0, 50)
price = 50 * size + 10000 * bedrooms - 1000 * age + 50000 + random.gauss(0, 20000)
X_multi.append([size, bedrooms, age])
y_multi.append(price)
def standardize(X):
n_features = len(X[0])
means = [sum(X[i][j] for i in range(len(X))) / len(X) for j in range(n_features)]
stds = []
for j in range(n_features):
variance = sum((X[i][j] - means[j]) ** 2 for i in range(len(X))) / len(X)
stds.append(variance ** 0.5)
X_scaled = []
for i in range(len(X)):
row = [(X[i][j] - means[j]) / stds[j] if stds[j] > 0 else 0 for j in range(n_features)]
X_scaled.append(row)
return X_scaled, means, stds
y_mean_val = sum(y_multi) / len(y_multi)
y_std_val = (sum((yi - y_mean_val) ** 2 for yi in y_multi) / len(y_multi)) ** 0.5
y_scaled = [(yi - y_mean_val) / y_std_val for yi in y_multi]
X_scaled, x_means, x_stds = standardize(X_multi)
print("\n=== Multiple Linear Regression (3 features) ===")
print("Features: house size, bedrooms, age")
multi_model = MultipleLinearRegression(n_features=3, learning_rate=0.01)
multi_model.fit(X_scaled, y_scaled, epochs=1000, print_every=200)
print(f"\nWeights (standardized): {[round(w, 4) for w in multi_model.weights]}")
print(f"Bias (standardized): {multi_model.bias:.4f}")
print(f"R-squared: {multi_model.r_squared(X_scaled, y_scaled):.4f}")
گام 5: رگرسیون چندجملهای
class PolynomialRegression:
def __init__(self, degree, learning_rate=0.01):
self.degree = degree
self.weights = [0.0] * degree
self.bias = 0.0
self.lr = learning_rate
def make_features(self, X):
return [[x ** (d + 1) for d in range(self.degree)] for x in X]
def predict(self, X):
features = self.make_features(X)
return [sum(w * f for w, f in zip(self.weights, row)) + self.bias for row in features]
def fit(self, X, y, epochs=1000, print_every=200):
features = self.make_features(X)
n = len(y)
for epoch in range(epochs):
predictions = [sum(w * f for w, f in zip(self.weights, row)) + self.bias for row in features]
errors = [pred - actual for pred, actual in zip(predictions, y)]
for j in range(self.degree):
grad = (2 / n) * sum(errors[i] * features[i][j] for i in range(n))
self.weights[j] -= self.lr * grad
grad_b = (2 / n) * sum(errors)
self.bias -= self.lr * grad_b
if epoch % print_every == 0:
cost = sum(e ** 2 for e in errors) / n
print(f" Epoch {epoch:4d} | Cost: {cost:.6f}")
return self
def r_squared(self, X, y):
predictions = self.predict(X)
y_mean = sum(y) / len(y)
ss_res = sum((actual - pred) ** 2 for actual, pred in zip(y, predictions))
ss_tot = sum((actual - y_mean) ** 2 for actual in y)
return 1 - (ss_res / ss_tot)
random.seed(42)
X_poly = [x / 10.0 for x in range(0, 50)]
y_poly = [0.5 * x ** 2 - 2 * x + 3 + random.gauss(0, 1.0) for x in X_poly]
x_max = max(abs(x) for x in X_poly)
X_poly_norm = [x / x_max for x in X_poly]
y_poly_mean = sum(y_poly) / len(y_poly)
y_poly_std = (sum((yi - y_poly_mean) ** 2 for yi in y_poly) / len(y_poly)) ** 0.5
y_poly_norm = [(yi - y_poly_mean) / y_poly_std for yi in y_poly]
print("\n=== Polynomial Regression (degree 2 vs degree 5) ===")
print("True relationship: y = 0.5x^2 - 2x + 3")
print("\nDegree 2:")
poly2 = PolynomialRegression(degree=2, learning_rate=0.1)
poly2.fit(X_poly_norm, y_poly_norm, epochs=2000, print_every=500)
print(f" R-squared: {poly2.r_squared(X_poly_norm, y_poly_norm):.4f}")
print("\nDegree 5:")
poly5 = PolynomialRegression(degree=5, learning_rate=0.1)
poly5.fit(X_poly_norm, y_poly_norm, epochs=2000, print_every=500)
print(f" R-squared: {poly5.r_squared(X_poly_norm, y_poly_norm):.4f}")
print("\nDegree 2 fits the true curve well. Degree 5 fits training data slightly better")
print("but risks overfitting on new data.")
گام 6: رگرسیون ریج (تنظیم L2)
class RidgeRegression:
def __init__(self, n_features, learning_rate=0.01, alpha=1.0):
self.weights = [0.0] * n_features
self.bias = 0.0
self.lr = learning_rate
self.alpha = alpha
def predict_single(self, x):
return sum(w * xi for w, xi in zip(self.weights, x)) + self.bias
def predict(self, X):
return [self.predict_single(x) for x in X]
def fit(self, X, y, epochs=1000, print_every=200):
n = len(y)
n_features = len(X[0])
for epoch in range(epochs):
predictions = self.predict(X)
errors = [pred - actual for pred, actual in zip(predictions, y)]
mse = sum(e ** 2 for e in errors) / n
reg_term = self.alpha * sum(w ** 2 for w in self.weights)
cost = mse + reg_term
for j in range(n_features):
grad = (2 / n) * sum(errors[i] * X[i][j] for i in range(n))
grad += 2 * self.alpha * self.weights[j]
self.weights[j] -= self.lr * grad
grad_b = (2 / n) * sum(errors)
self.bias -= self.lr * grad_b
if epoch % print_every == 0:
print(f" Epoch {epoch:4d} | Cost: {cost:.4f} | L2 penalty: {reg_term:.4f}")
return self
print("\n=== Ridge Regression (L2 Regularization) ===")
print("Same data as multiple regression, with alpha=0.1")
ridge = RidgeRegression(n_features=3, learning_rate=0.01, alpha=0.1)
ridge.fit(X_scaled, y_scaled, epochs=1000, print_every=200)
print(f"\nRidge weights: {[round(w, 4) for w in ridge.weights]}")
print(f"Plain weights: {[round(w, 4) for w in multi_model.weights]}")
print("Ridge weights are smaller (shrunk toward zero) due to the L2 penalty.")
استفاده از ابزارهای واقعی
حالا همین کارها را با scikit-learn پیاده میکنیم؛ یعنی همان ابزاری که در محیط کار واقعی استفاده خواهید کرد.
from sklearn.linear_model import LinearRegression as SklearnLR
from sklearn.linear_model import Ridge
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
np.random.seed(42)
X_sk = np.random.uniform(0, 10, (100, 1))
y_sk = 3.0 * X_sk.squeeze() + 7.0 + np.random.normal(0, 2.0, 100)
X_train, X_test, y_train, y_test = train_test_split(X_sk, y_sk, test_size=0.2, random_state=42)
lr = SklearnLR()
lr.fit(X_train, y_train)
y_pred = lr.predict(X_test)
print("=== Scikit-learn Linear Regression ===")
print(f"Coefficient (w): {lr.coef_[0]:.4f}")
print(f"Intercept (b): {lr.intercept_:.4f}")
print(f"R-squared (test): {r2_score(y_test, y_pred):.4f}")
print(f"MSE (test): {mean_squared_error(y_test, y_pred):.4f}")
poly = PolynomialFeatures(degree=2, include_bias=False)
X_poly_sk = poly.fit_transform(X_train)
X_poly_test = poly.transform(X_test)
lr_poly = SklearnLR()
lr_poly.fit(X_poly_sk, y_train)
print(f"\nPolynomial degree 2 R-squared: {r2_score(y_test, lr_poly.predict(X_poly_test)):.4f}")
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
ridge = Ridge(alpha=1.0)
ridge.fit(X_train_scaled, y_train)
print(f"Ridge R-squared: {r2_score(y_test, ridge.predict(X_test_scaled)):.4f}")
print(f"Ridge coefficient: {ridge.coef_[0]:.4f}")
کدی که خودتان از صفر نوشتید و scikit-learn خروجی یکسانی تولید میکنند. تفاوت اصلی اینجاست: scikit-learn حالتهای خاص (edge cases)، پایداری عددی (numerical stability) و بهینهسازیهای عملکردی را مدیریت میکند. در محیط عملیاتی از این کتابخانه استفاده کنید و از نسخهی دستنویس برای درک عمیق پشتصحنه بهره ببرید.
خروجی این درس
این درس خروجی زیر را تولید میکند:
outputs/skill-regression.md- مهارتی برای انتخاب رویکرد رگرسیون مناسب بر اساس نوع مسئله
تمرینها
- الگوریتمهای گرادیان کاهشی دستهای (batch)، گرادیان کاهشی تصادفی (SGD) و گرادیان کاهشی با دستهی کوچک (mini-batch) را پیادهسازی کنید. سرعت همگرایی آنها را روی یک مجموعهدادهی یکسان مقایسه کنید. کدامیک زودتر همگرا میشود؟ نمودار تابع هزینهی کدامیک هموارتر است؟
- دادههایی بر اساس یک تابع درجهسه تولید کنید (). چندجملهایهایی با درجات 1، 3 و 10 را روی آنها برازش دهید. مقدار دادههای آموزش و دادههای آزمون را مقایسه کنید. بیشبرازش از چه درجهای خودش را نشان میدهد؟
- رگرسیون لاسو (Lasso regression یا تنظیم L1: ) را پیادهسازی کنید. آن را روی دادههای چندویژگیِ مسکن آموزش دهید. ببینید کدام وزنها برخلاف ریج صفر میشوند. چرا L1 جوابهای تنک (sparse) تولید میکند اما L2 اینطور نیست؟
اصطلاحات کلیدی
| اصطلاح | در گفتگوهای عامیانه | معنای دقیق فنی |
|---|---|---|
| رگرسیون خطی | «کشیدن یک خط از میان دادهها» | یافتن وزن و بایاس بهنحوی که مجموع توان دوم اختلاف بین مقادیر و مقادیر واقعی کمینه شود |
| تابع هزینه | «مدل چقدر بد کار میکند» | تابعی که پارامترهای مدل را به یک عدد واحد نگاشت میکند تا خطای پیشبینی را بسنجد؛ الگوریتم بهینهسازی این عدد را کمینه میکند |
| میانگین مربعات خطا | «میانگین خطاهای به توان دو رسیده» | ، که خطاهای بزرگ را بسیار سنگینتر جریمه میکند |
| گرادیان کاهشی | «حرکت به سمت پایین تپه» | تنظیم گامبهگام پارامترها در جهتی که تابع هزینه را کم کند، با استفاده از مشتق جزئی (partial derivative) |
| نرخ یادگیری | «اندازهی گام» | عددی اسکالر که میزان تغییر پارامترها را در هر گام از گرادیان کاهشی کنترل میکند |
| معادلهی نرمال | «حل مسئله بهصورت مستقیم» | راهحل تحلیلی که وزنهای بهینه را بدون نیاز به تکرار به دست میآورد |
| ضریب تعیین (R-squared) | «کیفیت برازش چقدر خوب است» | کسری از واریانس که مدل آن را توضیح میدهد؛ بازهی تغییرات آن از منفی بینهایت تا 1.0 است |
| مقیاسبندی ویژگیها | «یکدست کردن ابعاد ویژگیها» | تغییر بازهی ویژگیها به مقادیری مشابه (مثلاً میانگین صفر و واریانس یک) تا گرادیان کاهشی سریعتر همگرا شود |
| تنظیم مدل (Regularization) | «جریمه کردن پیچیدگی مدل» | افزودن یک جمله به تابع هزینه برای کوچک نگهداشتن وزنها تا از بیشبرازش جلوگیری شود |
| رگرسیون ریج | «تنظیم L2» | رگرسیون خطی با اضافهشدن جریمهی به تابع MSE |
| رگرسیون چندجملهای | «برازش منحنی با ریاضیات خطی» | رگرسیون خطی روی ویژگیهای چندجملهای ()، که همچنان نسبت به وزنها خطی باقی میماند |
| بیشبرازش (Overfitting) | «حفظ کردن دادههای آموزش» | استفاده از مدلی چنان پیچیده که نوفه (نویز) دادههای آموزش را هم یاد میگیرد و روی دادههای جدید شکست میخورد |
برای مطالعهی بیشتر
- کتاب An Introduction to Statistical Learning (ISLR) -- نسخهی رایگان PDF؛ فصلهای 3 و 6 رگرسیون خطی و تنظیم مدل را با مثالهای کاربردی در زبان R پوشش میدهند
- کتاب The Elements of Statistical Learning (ESL) -- نسخهی رایگان PDF؛ مکملی ریاضیمحورتر برای کتاب ISLR با توضیحات عمیقتر دربارهی ریج و لاسو
- یادداشتهای درس CS229 استنفورد دربارهی رگرسیون خطی -- یادداشتهای اندرو انجی که معادلهی نرمال و گرادیان کاهشی را از اصول پایه اثبات میکند
- مستندات رگرسیون خطی در scikit-learn -- مرجعی کاربردی برای مدلهای LinearRegression، Ridge، Lasso و ElasticNet بههمراه نمونهکدها
