В случае MSE (среднеквадратичная ошибка)

  1. Ошибка (прогнозируемое значение — истинное значение) соответствует стандартному нормальному распределению [Среднее значение 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 (средняя абсолютная ошибка)

  1. Ошибка (прогнозируемое значение — истинное значение) может больше не соответствовать стандартному нормальному распределению.
  2. Количество точек данных с положительной ошибкой равно количеству точек данных с отрицательной ошибкой.

Давайте возьмем очень простой пример, чтобы понять 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 дает предиктор медианы.