Как идет обучение линейной модели?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Обучение линейной модели
Обучение линейной модели — это процесс нахождения оптимальных коэффициентов (весов), которые минимизируют ошибку предсказаний. Несмотря на кажущуюся простоту, это фундаментальный процесс, понимание которого критично для работы с более сложными моделями.
Формулировка задачи
Для линейной регрессии модель имеет вид:
y_pred = w0 + w1*x1 + w2*x2 + ... + wn*xn
y_pred = w^T * x
где:
- w — вектор весов (coefficients) размера (n+1,)
- x — вектор признаков (features) размера (n+1,), где первый элемент всегда 1 (для смещения/intercept)
- y — целевая переменная
Два основных подхода к обучению
Подход 1: Аналитическое решение (Normal Equation)
Для линейной регрессии существует закрытая форма решения. Минимизируя Mean Squared Error (MSE):
L(w) = ||Xw - y||^2 = (Xw - y)^T(Xw - y)
Производная по w:
∂L/∂w = 2X^T(Xw - y) = 0
Решение (Normal Equation):
w = (X^T*X)^(-1) * X^T * y
Это прямое вычисление без итераций:
import numpy as np
from sklearn.linear_model import LinearRegression
# Способ 1: Scikit-learn (использует numpy.linalg.lstsq)
model = LinearRegression()
model.fit(X_train, y_train)
print(f"Веса: {model.coef_}")
print(f"Intercept: {model.intercept_}")
# Способ 2: Явное вычисление
X_with_bias = np.c_[np.ones(X_train.shape[0]), X_train]
w = np.linalg.inv(X_with_bias.T @ X_with_bias) @ X_with_bias.T @ y_train
y_pred = X_with_bias @ w
Преимущества Normal Equation:
- Точное решение за один вычислительный шаг
- Не требует выбора learning rate
- Не нужны итерации
Недостатки:
- Требует вычисления матрицы (X^T*X)^(-1), что O(n^3) по сложности
- Неустойчива численно, если матрица плохо обусловлена
- Работает только для регрессии, не для классификации
- Для больших n (>10000) становится неэффективной
Подход 2: Итеративная оптимизация (Gradient Descent)
Вместо прямого решения, используем итеративный алгоритм:
1. Инициализировать w случайными значениями
2. Вычислить предсказания: y_pred = X * w
3. Вычислить ошибки: error = y_pred - y
4. Вычислить градиент: ∇L = X^T * error / N
5. Обновить веса: w = w - α * ∇L
6. Повторить шаги 2–5 до сходимости
import numpy as np
class LinearRegressionGD:
def __init__(self, learning_rate=0.01, n_iterations=1000):
self.lr = learning_rate
self.n_iter = n_iterations
self.w = None
self.losses = []
def fit(self, X, y):
n_samples, n_features = X.shape
self.w = np.zeros(n_features)
for _ in range(self.n_iter):
# Predictions
y_pred = X @ self.w
# Compute loss (MSE)
loss = np.mean((y_pred - y)**2)
self.losses.append(loss)
# Compute gradient
gradient = (2 / n_samples) * X.T @ (y_pred - y)
# Update weights
self.w -= self.lr * gradient
return self
def predict(self, X):
return X @ self.w
# Пример использования
model = LinearRegressionGD(learning_rate=0.01, n_iterations=100)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
Сравнение подходов
| Аспект | Normal Equation | Gradient Descent |
|---|---|---|
| Скорость вычисления | O(n^3) | O(n) за итерацию |
| Требует learning rate | Нет | Да |
| Работает для больших n | Плохо | Хорошо |
| Количество итераций | 1 | Много |
| Применимость | Только регрессия | Регрессия, классификация, DL |
Практический пример: Полный pipeline
from sklearn.linear_model import LinearRegression, SGDRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
import matplotlib.pyplot as plt
# Генерируем данные
X = np.random.randn(100, 1)
y = 3 * X.squeeze() + 2 + np.random.randn(100) * 0.5
# Разбиваем
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Подход 1: Normal Equation
model_ne = LinearRegression()
model_ne.fit(X_train, y_train)
y_pred_ne = model_ne.predict(X_test)
mse_ne = mean_squared_error(y_test, y_pred_ne)
print(f"Normal Equation - MSE: {mse_ne:.3f}, Coef: {model_ne.coef_[0]:.3f}, Intercept: {model_ne.intercept_:.3f}")
# Подход 2: SGD (mini-batch gradient descent)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
model_sgd = SGDRegressor(loss='squared_error', max_iter=1000, learning_rate='optimal', eta0=0.01)
model_sgd.fit(X_train_scaled, y_train)
y_pred_sgd = model_sgd.predict(X_test_scaled)
mse_sgd = mean_squared_error(y_test, y_pred_sgd)
print(f"SGD - MSE: {mse_sgd:.3f}, Coef: {model_sgd.coef_[0]:.3f}")
# Визуализация
plt.scatter(X_test, y_test, label='Actual')
plt.plot(X_test, y_pred_ne, 'r-', label='Normal Equation')
plt.plot(X_test, y_pred_sgd, 'g--', label='SGD')
plt.legend()
plt.show()
Регуляризация при обучении
Для предотвращения переобучения добавляются штрафы за большие веса:
Ridge Regression (L2 регуляризация)
L(w) = ||Xw - y||^2 + λ*||w||^2
from sklearn.linear_model import Ridge
model = Ridge(alpha=1.0) # alpha — параметр регуляризации
model.fit(X_train, y_train)
Lasso Regression (L1 регуляризация)
L(w) = ||Xw - y||^2 + λ*||w||_1
from sklearn.linear_model import Lasso
model = Lasso(alpha=0.1) # Меньший alpha → меньше регуляризации
model.fit(X_train, y_train)
Elastic Net (L1 + L2)
from sklearn.linear_model import ElasticNet
model = ElasticNet(alpha=0.1, l1_ratio=0.5)
model.fit(X_train, y_train)
Диагностика обучения
Learning Curve
Показывает, как меняется ошибка с количеством данных:
from sklearn.model_selection import learning_curve
train_sizes, train_scores, val_scores = learning_curve(
LinearRegression(), X, y, cv=5,
train_sizes=np.linspace(0.1, 1.0, 10),
scoring='neg_mean_squared_error'
)
plt.plot(train_sizes, -train_scores.mean(axis=1), label='Train')
plt.plot(train_sizes, -val_scores.mean(axis=1), label='Validation')
plt.legend()
plt.show()
Convergence Curve
Показывает сходимость gradient descent:
import matplotlib.pyplot as plt
plt.plot(model.losses)
plt.xlabel('Iteration')
plt.ylabel('Loss')
plt.title('Convergence of Gradient Descent')
plt.show()
Важные моменты
- Нормализация: Признаки должны быть нормализованы перед обучением, особенно для GD
- Сходимость: GD может не сойтись если learning rate слишком большой
- Масштабируемость: Normal Equation O(n^3), GD O(n) за итерацию
- Регуляризация: Обязательна для плохо обусловленных задач
Обучение линейной модели — это простой, но мощный процесс, который лежит в основе современного машинного обучения.