Неделя 2: Линейная регрессия и градиентный спуск
1. Теоретическая часть
1.1. Линейная регрессия
Линейная регрессия — модель для предсказания числовых значений на основе линейной зависимости между признаками и целевой переменной.
Математическая формулировка
Гипотеза:
ℎ𝜃(𝑥)=𝜃0+𝜃1𝑥1+𝜃2𝑥2+⋯+𝜃𝑛𝑥𝑛hθ(x)=θ0+θ1x1+θ2x2+⋯+θnxn
где:
ℎ𝜃(𝑥)hθ(x) — предсказание
𝜃θ — параметры модели (веса)
𝑥x — признаки
Функция потерь (MSE - Mean Squared Error)
𝐽(𝜃)=12𝑚∑𝑖=1𝑚(ℎ𝜃(𝑥(𝑖))−𝑦(𝑖))2J(θ)=2m1i=1∑m(hθ(x(i))−y(i))2
где 𝑚m — количество примеров в выборке.
1.2. Градиентный спуск
Алгоритм оптимизации для нахождения оптимальных параметров 𝜃θ.
Шаги градиентного спуска:
1. Инициализировать 𝜃θ случайными значениями
2. Вычислить градиент функции потерь:
∂𝐽(𝜃)∂𝜃𝑗=1𝑚∑𝑖=1𝑚(ℎ𝜃(𝑥(𝑖))−𝑦(𝑖))𝑥𝑗(𝑖)∂θj∂J(θ)=m1i=1∑m(hθ(x(i))−y(i))xj(i)
3. Обновить параметры:
𝜃𝑗:=𝜃𝑗−𝛼∂𝐽(𝜃)∂𝜃𝑗θj:=θj−α∂θj∂J(θ)
где 𝛼α — скорость обучения (learning rate).
4. Повторять до сходимости
1.3. Разделение данных
Обучающая выборка (Train set) — используется для обучения модели
Тестовая выборка (Test set) — для оценки качества модели
Валидационная выборка (Validation set) — для подбора гиперпараметров
Метрики качества для регрессии:
MSE (Mean Squared Error)
RMSE (Root Mean Squared Error)
R² (Коэффициент детерминации)
2.1. Реализация линейной регрессии с нуля
python
Copy
import numpy as np
class LinearRegression:
def __init__(self, learning_rate=0.01, n_iterations=1000):
self.learning_rate = learning_rate
self.n_iterations = n_iterations
self.weights = None
self.bias = None
def fit(self, X, y):
n_samples, n_features = X.shape
self.weights = np.zeros(n_features)
self.bias = 0
for _ in range(self.n_iterations):
y_pred = np.dot(X, self.weights) + self.bias
# Вычисление градиентов
dw = (1 / n_samples) * np.dot(X.T, (y_pred - y))
db = (1 / n_samples) * np.sum(y_pred - y)
# Обновление параметров
self.weights -= self.learning_rate * dw
self.bias -= self.learning_rate * db
def predict(self, X):
return np.dot(X, self.weights) + self.bias
2.2. Использование Scikit-learn
python
Copy
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
# Загрузка данных (пример)
X, y = ... # Ваши данные
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Обучение модели
model = LinearRegression()
model.fit(X_train, y_train)
# Предсказание и оценка
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"MSE: {mse:.2f}, R²: {r2:.2f}")
2.3. Визуализация регрессии
python
Copy
import matplotlib.pyplot as plt
# Пример для одномерной регрессии
plt.scatter(X_test, y_test, color='blue', label='Реальные значения')
plt.plot(X_test, y_pred, color='red', linewidth=2, label='Предсказание')
plt.xlabel('Признак')
plt.ylabel('Целевая переменная')
plt.legend()
plt.show()
3. Домашнее задание
Задача 1: Реализация стохастического градиентного спуска
Модифицируйте класс LinearRegression, чтобы он использовал стохастический градиентный спуск (обновление весов на каждом примере отдельно).
Решение:
python
Copy
def fit(self, X, y):
n_samples, n_features = X.shape
self.weights = np.zeros(n_features)
self.bias = 0
for _ in range(self.n_iterations):
for i in range(n_samples):
# Берем один случайный пример
idx = np.random.randint(n_samples)
x_i = X[idx]
y_i = y[idx]
# Предсказание и градиенты
y_pred_i = np.dot(x_i, self.weights) + self.bias
dw = (y_pred_i - y_i) * x_i
db = (y_pred_i - y_i)
# Обновление параметров
self.weights -= self.learning_rate * dw
self.bias -= self.learning_rate * db
Задача 2: Применение к реальным данным
1. Загрузите датасет Boston Housing (from sklearn.datasets import load_boston).
2. Разделите данные на train/test.
3. Обучите линейную регрессию и оцените качество через MSE и R².
Решение:
python
Copy
from sklearn.datasets import load_boston
data = load_boston()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
print(f"MSE: {mean_squared_error(y_test, y_pred):.2f}")
print(f"R²: {r2_score(y_test, y_pred):.2f}")
Задача 3: Влияние learning rate
Исследуйте, как скорость обучения (α) влияет на сходимость градиентного спуска.
Попробуйте α = 0.001, 0.01, 0.1, 1.0.
Постройте график функции потерь от итераций для каждого случая.
Решение:
python
Copy
learning_rates = [0.001, 0.01, 0.1, 1.0]
loss_history = {lr: [] for lr in learning_rates}
for lr in learning_rates:
model = LinearRegression(learning_rate=lr)
for _ in range(100):
model.fit(X_train, y_train) # (нужно модифицировать fit для сохранения loss)
loss = ... # Вычислите MSE на каждой итерации
loss_history[lr].append(loss)
# Визуализация
for lr, losses in loss_history.items():
plt.plot(losses, label=f"LR={lr}")
plt.xlabel("Итерации")
plt.ylabel("MSE")
plt.legend()
plt.show()
Итоги недели
✅ Разобрали линейную регрессию и градиентный спуск.
✅ Реализовали модель с нуля и через Scikit-learn.
✅ Научились оценивать качество через MSE и R².
✅ Исследовали влияние learning rate на обучение.
Следующая тема: Логистическая регрессия и классификация. 🚀