Пошаговое руководство по математическим определениям, алгоритмам и реализациям функций потерь в PyTorch.

Вы можете найти часть 2 здесь.

Как и люди, машина учится на своих прошлых ошибках. Эти «ошибки» формально называются потерями и вычисляются с помощью функции (т. Е. Функции потерь). Если предсказание алгоритма машинного обучения дальше от истины, функция потерь будет большой, и наоборот. Таким образом, целью любого процесса обучения было бы минимизировать такие потери, чтобы конечный результат точно соответствовал реальным этикеткам. В этом посте мы рассмотрим математическое определение и алгоритм некоторых из наиболее популярных функций потерь и их реализации в PyTorch.

Вступление

Выбор наилучшей функции потерь - это проектное решение, которое зависит от наших вычислительных ограничений (например, скорости и места), наличия значительных выбросов в наборах данных и типов входов / выходов, которые у нас есть.

Тем не менее, один из первых вопросов, который нам нужно задать при выборе между различными функциями потерь, - это тип данных, которые мы представляем. Как правило, функции потерь можно аккуратно сгруппировать в зависимости от конкретных задач, с которыми мы имеем дело: либо регрессия, либо классификация. Регрессия имеет дело с непрерывным набором данных, например, при прогнозировании ВВП на душу населения в стране с учетом темпов роста населения, урбанизации, исторических тенденций ВВП и т. Д. С другой стороны, проблема классификации связана с конечными дискретными категориями, такими как предсказание того, есть ли на спутниковых снимках какое-либо дождливое событие или нет.

Функции регрессионных потерь

Средняя абсолютная ошибка (потеря L1)

Средняя абсолютная ошибка (MAE) суммирует абсолютную разницу между истиной (y_i) и соответствующим ей предсказанием (y_hat_i), деленную на общее количество таких пар.

Алгоритмы: MAE

import numpy as np
y_pred = np.array([0.000, 0.100, 0.200])
y_true = np.array([0.000, 0.200, 0.250])
# Defining Mean Absolute Error loss function
def mae(pred, true):
    # Get absolute difference
    differences = pred - true
    absolute_differences = np.absolute(differences)
    # Get the mean
    mean_absolute_error = absolute_differences.mean()
    return mean_absolute_error
mae_value = mae(y_pred, y_true)
print ("MAE error is: " + str(mae_value))

Реализация PyTorch: MAE

import torch
mae_loss = torch.nn.L1Loss()
input = torch.randn(2, 3, requires_grad=True)
target = torch.randn(2, 3)
output = mae_loss(input, target)
output.backward()
input
#tensor([[-0.5855,  0.4962, -0.7684],
        [ 0.0587,  0.5546,  0.9823]], requires_grad=True)
target
#tensor([[ 0.7184, -1.3773,  0.9070],
        [-0.1963, -3.2091, -0.8386]])
output
#tensor(1.7821, grad_fn=<L1LossBackward>)

Среднеквадратическая ошибка (потеря L2)

Подобно MAE, среднеквадратичная ошибка (MSE) суммирует возведенную в квадрат (попарную) разницу между истиной (y_i) и предсказанием (y_hat_i), разделенную на количество таких пар. MSE обычно наказывает предсказания, которые далеки от истины, применяя оператор квадрата, но менее надежны для выбросов, поскольку они имеют тенденцию преувеличивать такие наблюдения.

Алгоритмы: MSE

import numpy as np
y_pred = np.array([0.000, 0.100, 0.200])
y_true = np.array([0.000, 0.200, 0.250])
# Defining Mean Squared Error loss function
def mse(pred, true):
    # Get squared difference
    differences = pred - true
    squared_differences = differences ** 2
    # Get the mean
    mean_squared_error = squared_differences.mean()
    return mean_squared_error
mse_value = mse(y_pred, y_true)
print ("MSE error is: " + str(mse_value))

Реализация PyTorch: MSE

import torch
mse_loss = torch.nn.MSELoss()
input = torch.randn(2, 3, requires_grad=True)
target = torch.randn(2, 3)
output = mse_loss(input, target)
output.backward()
input
#tensor([[-0.4867, -0.4977, -0.6090],
        [-1.2539, -0.0048, -0.6077]], requires_grad=True)
target
#tensor([[ 2.0417, -1.5456, -1.1467],
        [ 0.7593, -0.5154, -1.3713]])
output
#tensor(2.1129, grad_fn=<MseLossBackward>)

Функции потери классификации

Двоичная кросс-энтропия

Если у вас есть только две метки (например, True или False, Cat или Dog, и т. Д.), то двоичная кросс-энтропия (BCE) является наиболее подходящей функцией потерь. Обратите внимание, что в приведенном выше математическом определении, когда фактическая метка равна 1 (y (i) = 1), вторая половина функции исчезает. В случае, когда фактическая метка равна 0 (y (i) = 0), первая половина уравнения опускается. Короче говоря, мы просто умножаем логарифм фактической предсказанной вероятности для наземного класса истинности. Эта идея полезна, когда мы обобщаем BCE для обработки более двух классов в категориальной перекрестной энтропии (обсуждается в последнем разделе).

Алгоритмы: BCE

import numpy as np
y_pred = np.array([0.1880, 0.4137, 0.2285])
y_true = np.array([0.0, 1.0, 0.0]) #2 labels: (0,1)
def BCE(y_pred, y_true):
    total_bce_loss = np.sum(-y_true * np.log(y_pred) - (1 - y_true) * np.log(1 - y_pred))
    # Get the mean BCE loss
    num_of_samples = y_pred.shape[0]
    mean_bce_loss = total_bce_loss / num_of_samples
    
    return mean_bce_loss

bce_value = BCE(y_pred, y_true)
print ("BCE error is: " + str(bce_value))

Реализация PyTorch: BCE

import torch
bce_loss = torch.nn.BCELoss()
sigmoid = torch.nn.Sigmoid() # Ensuring inputs are between 0 and 1
input = torch.randn(3, requires_grad=True)
target = torch.empty(3).random_(2)
output = bce_loss(sigmoid(input), target)
output.backward()
sigmoid(input)
#tensor([0.1880, 0.4137, 0.2285], grad_fn=<SigmoidBackward>)
target
#tensor([0., 1., 0.])
output
#tensor(0.4501, grad_fn=<BinaryCrossEntropyBackward>)

Категориальная перекрестная энтропия (т.е. отрицательное логарифмическое правдоподобие + логарифм Softmax)

Функция потерь категориальной перекрестной энтропии (CCE) может использоваться для задач с более чем двумя классами, такими как классификация между собакой, кошкой, тигром и т. Д.. Вышеприведенная формула выглядит пугающей, но CCE по сути является обобщением BCE с дополнительным членом суммирования по всем классам, J.

Алгоритмы: CCE

import numpy as np
y_pred = np.array([0.1880, 0.4137, 0.2285])
y_true = np.array([0.0, 1.0, 0.0])
def CCE(y_pred, y_true):
    total_cce_loss = np.sum(-y_true * np.log(y_pred) - (1 - y_true) * np.log(1 - y_pred))
    # Get the mean CCE loss
    num_of_samples = y_pred.shape[0]
    mean_cce_loss = total_cce_loss / num_of_samples
    
    return mean_cce_loss
cce_value = CCE(y_pred, y_true)
print ("CCE error is: " + str(cce_value))

Реализация PyTorch: CCE

import torch
cce_loss = torch.nn.CrossEntropyLoss()
input = torch.randn(2,3, requires_grad=True)
target = torch.empty(2).random_(3) #3 different classes
output = cce_loss(input, target)
output.backward()
input
#tensor([[-0.1069, -1.0915,  0.6950],
        [-0.4095,  1.0890, -1.4179]], requires_grad=True)
target
#tensor([1, 1])
output
#tensor(1.2663, grad_fn=<NllLossBackward>)

Заключение

На этом мы познакомимся с наиболее популярными функциями потерь PyTorch, их математическими определениями, реализациями алгоритмов и практическим опытом PyTorch API. В следующей части этой серии мы рассмотрим другие, менее популярные, но полезные функции потерь.

Подпишитесь на мою информационную рассылку по электронной почте: https://tinyurl.com/2npw2fnz , где я регулярно резюмирую исследовательские работы по ИИ на простом английском языке и в красивой визуализации.