В случае MSE (среднеквадратичная ошибка)
- Ошибка (прогнозируемое значение — истинное значение) соответствует стандартному нормальному распределению [Среднее значение 0 и отклонение 1].
Когда мы обучаем линейную регрессию с использованием MSE, общая ошибка приближается к нулю. В связи с этим,
- Линия регрессии моделирует среднее предсказание.
- Алгоритм становится чувствительным к выбросам.
Давайте посмотрим на реализацию линейной регрессии с MSE.
import matplotlib.pyplot as plt import numpy as np import torch import torch.nn as nn from torch.autograd import Variable from sklearn.datasets import make_regression x_dim = 1 y_dim = 1 seed = 42 np.random.seed(seed) torch.manual_seed(seed) device = 'cuda' if torch.cuda.is_available() else 'cpu' # Dataset x_values, y_values = make_regression(n_samples=50, n_features=x_dim, noise=50, random_state=seed) # Manually adding the outlier point x_values[0] = 2 y_values[0] = 500 x_train = np.array(x_values, dtype=np.float32) x_train = x_train.reshape(-1, x_dim) y_train = np.array(y_values, dtype=np.float32) y_train = y_train.reshape(-1, y_dim) plt.plot(x_train, y_train, 'go', alpha=0.5) plt.show()
Модель линейной регрессии
class LR(nn.Module): def __init__(self, x_dim, y_dim=1): super(LR, self).__init__() self.linear = nn.Linear(x_dim, y_dim) def forward(self, x): return self.linear(x)
Обучение моделей
learning_rate = 0.0002 num_epochs = 20000 mse_model = LR(x_dim, y_dim) mse_model = mse_model.to(device) criterion = torch.nn.MSELoss() optimizer = torch.optim.SGD(mse_model.parameters(), lr=learning_rate) total_loss = [] for _ in range(num_epochs): inputs = torch.from_numpy(x_train).to(device) labels = torch.from_numpy(y_train).to(device) optimizer.zero_grad() outputs = mse_model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() total_loss.append(loss.item()) plt.plot(total_loss) plt.show()
Оценка модели + термин ошибки
with torch.no_grad(): inputs = torch.from_numpy(x_train).to(device) predicted = mse_model(inputs).cpu().data.numpy() error = (predicted - y_train).reshape(-1) pos_count = np.sum(error >= 0) neg_count = np.sum(error < 0) print(f"Number of positive error {pos_count}") print(f"Number of negative error {neg_count}") print(f"Total Error {np.sum(error)}")
Вывод
Вывод: теоретически у нас должно быть значение общей ошибки, равное 0. Однако мы получаем его как -1,86 [ближе к 0], что показывает, что изученные веса еще не оптимальны.
В случае MAE (средняя абсолютная ошибка)
- Ошибка (прогнозируемое значение — истинное значение) может больше не соответствовать стандартному нормальному распределению.
- Количество точек данных с положительной ошибкой равно количеству точек данных с отрицательной ошибкой.
Давайте возьмем очень простой пример, чтобы понять 2-й пункт.
Формулировка потерь:
где
Когда мы берем вывод L относительно w, мы получаем
Чтобы найти наилучшее значение w, которое минимизирует эту функцию потерь, мы должны
где
Для этого
выражение равно 0, мы имеем равное количество положительных и отрицательных ошибок.
Математическое доказательство здесь: https://gennadylaptev.medium.com/median-and-mae-3e85f92df2d7
Когда мы обучаем линейную регрессию с помощью MAE, она приводит к равному количеству положительных и отрицательных ошибок. В связи с этим,
- Линия регрессии моделирует медиану прогноза.
- Алгоритм становится устойчивым к выбросам.
Обучение моделей
learning_rate = 0.015 num_epochs = 20000 mae_model = LR(x_dim, y_dim) criterion = torch.nn.L1Loss() optimizer = torch.optim.SGD(mae_model.parameters(), lr=learning_rate) total_loss = [] for _ in range(num_epochs): inputs = torch.from_numpy(x_train).to(device) labels = torch.from_numpy(y_train).to(device) optimizer.zero_grad() outputs = mae_model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() total_loss.append(loss.item()) plt.plot(total_loss) plt.show()
Оценка модели + термин ошибки
with torch.no_grad(): inputs = torch.from_numpy(x_train).to(device) predicted = mae_model(inputs).cpu().data.numpy() error = (predicted - y_train).reshape(-1) pos_count = np.sum(error >= 0) neg_count = np.sum(error < 0) print(f"Number of positive error {pos_count}") print(f"Number of negative error {neg_count}") print(f"Total Error {np.sum(error)}")
Вывод
Вывод: мы получаем одинаковое количество положительных и отрицательных ошибок. Суммарная ошибка слишком далека от 0.
Заключение:
Линейная регрессия с MSE дает предиктор среднего, тогда как линейная регрессия с MAE дает предиктор медианы.