Линейная регрессия
Линейная регрессия — один из самых фундаментальных и широко используемых алгоритмов в машинном обучении.
Линейная регрессия — самый базовый алгоритм машинного обучения для предсказания непрерывных значений; он предполагает, что целевая переменнаяyи переменные-признакиxимеют линейную зависимость, и пытается найти наиболее подходящую линию, описывающую эту зависимость.
y = w * x + b
Где:
y— предсказанное значениеx— переменная-признакw— вес (наклон)b— смещение (свободный член)
Цель линейной регрессии — найти оптимальныеwиb, чтобы предсказанное значениеyимело минимальную ошибку относительно истинного значения. Обычно используемая функция ошибки — среднеквадратичная ошибка (MSE):
MSE = 1/n * Σ(y_i - y_pred_i)^2
Где:
- y_i — фактическое значение.
- y_pred_i — предсказанное значение.
- n — это количество точек данных.
Наша цель — минимизировать MSE, подбирая w и b.
Как решить задачу линейной регрессии?
1. Метод наименьших квадратов
Метод наименьших квадратов — распространённый подход к решению линейной регрессии; он находит оптимальные значения (w) и (b) путём решения следующих уравнений.
Цель метода наименьших квадратов — минимизировать остаточную сумму квадратов (RSS) по формуле:
\[ \text{RSS} = \sum_{i=1}^n (y_i - \hat{y}_i)^2 \]
Где:
\( y_i \)— фактическое значение.\( \hat{y}_i \)— предсказанное значение, которое\( \hat{y}_i = w x_i + b \)вычисляется моделью линейной регрессии.
Минимизируя RSS, можно получить следующие нормальные уравнения:
\[ \begin{cases} w \sum_{i=1}^n x_i^2 + b \sum_{i=1}^n x_i = \sum_{i=1}^n x_i y_i \\ w \sum_{i=1}^n x_i + b n = \sum_{i=1}^n y_i \end{cases} \]
Матричная форма
Запишите нормальные уравнения в матричной форме:
\[ \begin{bmatrix} \sum_{i=1}^n x_i^2 & \sum_{i=1}^n x_i \\ \sum_{i=1}^n x_i & n \end{bmatrix} \begin{bmatrix} w \\ b \end{bmatrix} = \begin{bmatrix} \sum_{i=1}^n x_i y_i \\ \sum_{i=1}^n y_i \end{bmatrix} \]
Метод решения
Решив приведенное выше матричное уравнение, можно получить оптимальное решение.\( w \)и\( b \):
\[ \begin{bmatrix} w \\ b \end{bmatrix} = \begin{bmatrix} \sum_{i=1}^n x_i^2 & \sum_{i=1}^n x_i \\ \sum_{i=1}^n x_i & n \end{bmatrix}^{-1} \begin{bmatrix} \sum_{i=1}^n x_i y_i \\ \sum_{i=1}^n y_i \end{bmatrix} \]
2. Градиентный спуск
Цель градиентного спуска — минимизировать функцию потерь\( J(w, b) \) . В задачах линейной регрессии в качестве функции потерь обычно используется среднеквадратичная ошибка (MSE):
\[ J(w, b) = \frac{1}{2m} \sum_{i=1}^m (y_i - \hat{y}_i)^2 \]
Где:
\( m \)— это количество выборок.\( y_i \)— фактическое значение.\( \hat{y}_i \)— предсказанное значение, которое\( \hat{y}_i = w x_i + b \)вычисляется моделью линейной регрессии.
Градиент — это частная производная функции потерь по параметрам, указывающая направление изменения функции потерь в пространстве параметров. Для линейной регрессии градиент вычисляется следующим образом:
\[ \frac{\partial J}{\partial w} = -\frac{1}{m} \sum_{i=1}^m x_i (y_i - \hat{y}_i) \]
\[ \frac{\partial J}{\partial b} = -\frac{1}{m} \sum_{i=1}^m (y_i - \hat{y}_i) \]
Правила обновления параметров
Градиентный спуск обновляет параметры, используя следующие правила:\( w \)и\( b \):
\[ w := w - \alpha \frac{\partial J}{\partial w} \]
\[ b := b - \alpha \frac{\partial J}{\partial b} \]
Где:
\( \alpha \)— это скорость обучения, которая управляет размером шага каждого обновления.
Шаги градиентного спуска
- Инициализировать параметры: инициализировать
\( w \)и\( b \)значения (обычно устанавливаются в 0 или случайные значения). - Вычислить функцию потерь: вычислить значение функции потерь при текущих параметрах
\( J(w, b) \)。 - Вычислить градиент: вычислить частную производную функции потерь по
\( w \)и\( b \)параметры. - Обновление параметров: обновление в соответствии с градиентом
\( w \)и\( b \)。 - Повторение итерации: повторяйте шаги со 2 по 4, пока функция потерь не сойдётся или не будет достигнуто максимальное число итераций.
Реализация линейной регрессии на Python
Ниже мы используем простой пример, чтобы продемонстрировать, как реализовать линейную регрессию с помощью Python.
1. Импорт необходимых библиотек
Пример
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
2. Генерация данных
Пример
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# Сгенерировать случайные данные
np.random.seed(0)
x = 2 * np.random.rand(100, 1)
y = 4 + 3 * x + np.random.randn(100, 1)
# Визуализировать данные
plt.scatter(x, y)
plt.xlabel('x')
plt.ylabel('y')
plt.title('Сгенерированные данные из примера')
plt.show()
Отображение выглядит следующим образом:

3. Использование Scikit-learn для линейной регрессии
Пример
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# Сгенерировать случайные данные
np.random.seed(0)
x = 2 * np.random.rand(100, 1)
y = 4 + 3 * x + np.random.randn(100, 1)
# Создайте модель линейной регрессии
model = LinearRegression()
# Обучение модели
model.fit(x, y)
# Вывод параметров модели
print(f"Наклон (w): {model.coef_)
print(f"Свободный член (b): {model.intercept_)
# Прогнозирование
y_pred = model.predict(x)
# Визуализация результата подгонки
plt.scatter(x, y)
plt.plot(x, y_pred, color='red')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Подгонка линейной регрессии')
plt.show()
Результат вывода:
斜率 (w): 2.968467510701019 截距 (b): 4.222151077447231
Отображение выглядит следующим образом:

Мы можем использоватьscore()метод оценки качества модели, возвращающий значение R^2.
Пример
from sklearn.linear_model import LinearRegression
# Сгенерировать случайные данные
np.random.seed(0)
x = 2 * np.random.rand(100, 1)
y = 4 + 3 * x + np.random.randn(100, 1)
# Создайте модель линейной регрессии
model = LinearRegression()
# Обучение модели
model.fit(x, y)
# Расчет оценки модели
score = model.score(x, y)
print("Оценка модели:", score)
Результат вывода:
模型得分: 0.7469629925504755
4. Реализация градиентного спуска вручную
Пример
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# Сгенерировать случайные данные
np.random.seed(0)
x = 2 * np.random.rand(100, 1)
y = 4 + 3 * x + np.random.randn(100, 1)
# Инициализация параметров
w = 0
b = 0
learning_rate = 0.1
n_iterations = 1000
# Градиентный спуск
for i in range(n_iterations):
y_pred = w * x + b
dw = -(2/len(x)) * np.sum(x * (y - y_pred))
db = -(2/len(x)) * np.sum(y - y_pred)
w = w - learning_rate * dw
b = b - learning_rate * db
# Вывод итоговых параметров
print(f"Наклон (w), реализованный вручную: {w}")
print(f"Вручную реализованный свободный член (b): {b}")
# Визуализация результата ручной подгонки
y_pred_manual = w * x + b
plt.scatter(x, y)
plt.plot(x, y_pred_manual, color='green')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Ручная подгонка градиентным спуском')
plt.show()
Результат вывода:
手动实现的斜率 (w): 2.968467510701028 手动实现的截距 (b): 4.222151077447219
Отображение выглядит следующим образом:
