Функции потерь

Flux предоставляет большое количество распространенных функций потерь, используемых для обучения моделей машинного обучения. Они сгруппированы в модуле Flux.Losses.

Функции потерь для контролируемого обучения обычно ожидают в качестве входных данных целевой объект y и предсказание от вашей модели. По соглашению Flux используется следующий порядок аргументов.

loss(ŷ, y)

Большинство функций потерь во Flux имеют необязательный аргумент agg, обозначающий тип агрегирования, выполняемого для пакета:

loss(ŷ, y)                         # значение по умолчанию — `mean`
loss(ŷ, y, agg=sum)                # использовать `sum` для редукции
loss(ŷ, y, agg=x->sum(x, dims=2))  # частичная редукция
loss(ŷ, y, agg=x->mean(w .* x))    # взвешенное среднее
loss(ŷ, y, agg=identity)           # без агрегирования.

Список функций

# Flux.Losses.maeFunction

mae(ŷ, y; agg = mean)

Возвращает потерю, соответствующую средней абсолютной погрешности:

agg(abs.(ŷ .- y))

Пример

julia> y_model = [1.1, 1.9, 3.1];

julia> Flux.mae(y_model, 1:3)
0.10000000000000009

# Flux.Losses.mseFunction

mse(ŷ, y; agg = mean)

Возвращает потерю, соответствующую среднеквадратичной погрешности:

agg((ŷ .- y) .^ 2)

См. также описание mae, msle, crossentropy.

Пример

julia> y_model = [1.1, 1.9, 3.1];

julia> y_true = 1:3;

julia> Flux.mse(y_model, y_true)
0.010000000000000018

# Flux.Losses.msleFunction

msle(ŷ, y; agg = mean, eps = eps(eltype(ŷ)))

Потери, соответствующие среднеквадратичным логарифмическим погрешностям, вычисляются следующим образом.

agg((log.(ŷ .+ ϵ) .- log.(y .+ ϵ)) .^ 2)

Член ϵ == eps обеспечивает численную устойчивость. Штрафует за заниженную оценку больше, чем за завышенную.

Пример

julia> Flux.msle(Float32[1.1, 2.2, 3.3], 1:3)
0.009084041f0

julia> Flux.msle(Float32[0.9, 1.8, 2.7], 1:3)
0.011100831f0

# Flux.Losses.huber_lossFunction

huber_loss(ŷ, y; delta = 1, agg = mean)

Возвращает среднее значение потери Губера при заданном предсказании и истинных значениях y.

             | 0.5 * |ŷ - y|^2,            for |ŷ - y| <= δ
Huber loss = |
             |  δ * (|ŷ - y| - 0.5 * δ), otherwise

Пример

julia> ŷ = [1.1, 2.1, 3.1];

julia> Flux.huber_loss(ŷ, 1:3)  # по умолчанию δ = 1 > |ŷ - y|
0.005000000000000009

julia> Flux.huber_loss(ŷ, 1:3, delta=0.05)  # изменяет поведение при |ŷ - y| > δ
0.003750000000000005

# Flux.Losses.label_smoothingFunction

label_smoothing(y::Union{Number, AbstractArray}, α; dims::Int=1)

Возвращает сглаженные метки, то есть доверие к значениям меток ослаблено.

Если y задан как вектор с одним активным состоянием или пакет таких векторов, он вычисляется следующим образом

y .* (1 - α) .+ α / size(y, dims)

когда y задан как число или пакет чисел для бинарной классификации, он вычисляется следующим образом:

y .* (1 - α) .+ α / 2

в этом случае метки сдвигаются в сторону 0.5.

α — это число в интервале (0, 1), называемое коэффициентом сглаживания. При большем значении α происходит большее сглаживание y.

dims означает измерение с одним активным состоянием, если только dims=0, что означает применение сглаживания меток к бинарным распределениям, закодированным в одном числе.

Пример

julia> y = Flux.onehotbatch([1, 1, 1, 0, 1, 0], 0:1)
2×6 OneHotMatrix(::Vector{UInt32}) with eltype Bool:
 ⋅  ⋅  ⋅  1  ⋅  1
 1  1  1  ⋅  1  ⋅

julia> y_smoothed = Flux.label_smoothing(y, 0.2f0)
2×6 Matrix{Float32}:
 0.1  0.1  0.1  0.9  0.1  0.9
 0.9  0.9  0.9  0.1  0.9  0.1

julia> y_sim = softmax(y .* log(2f0))
2×6 Matrix{Float32}:
 0.333333  0.333333  0.333333  0.666667  0.333333  0.666667
 0.666667  0.666667  0.666667  0.333333  0.666667  0.333333

julia> y_dis = vcat(y_sim[2,:]', y_sim[1,:]')
2×6 Matrix{Float32}:
 0.666667  0.666667  0.666667  0.333333  0.666667  0.333333
 0.333333  0.333333  0.333333  0.666667  0.333333  0.666667

julia> Flux.crossentropy(y_sim, y) < Flux.crossentropy(y_sim, y_smoothed)
true

julia> Flux.crossentropy(y_dis, y) > Flux.crossentropy(y_dis, y_smoothed)
true

# Flux.Losses.crossentropyFunction

crossentropy(ŷ, y; dims = 1, eps = eps(eltype(ŷ)), agg = mean)

Возвращает перекрестную энтропию между заданными распределениями вероятностей. Вычисляется следующим образом:

agg(-sum(y .* log.(ŷ .+ ϵ); dims))

Перекрестная энтропия обычно используется в качестве потери при многоклассовой классификации. В этом случае метки y задаются в формате с одним активным состоянием. dims задает измерение (или измерения), содержащее вероятности классов. Предполагается, что предсказание должно равняться единице во всех измерениях (dims), как и в случае с выходными данными операции softmax.

Для обеспечения численной стабильности рекомендуется использовать logitcrossentropy, а не softmax с последующей crossentropy.

Используйте label_smoothing для сглаживания истинных меток в качестве предварительной обработки перед вычислением потерь.

См. также описание logitcrossentropy, binarycrossentropy, logitbinarycrossentropy.

Пример

julia> y_label = Flux.onehotbatch([0, 1, 2, 1, 0], 0:2)
3×5 OneHotMatrix(::Vector{UInt32}) with eltype Bool:
 1  ⋅  ⋅  ⋅  1
 ⋅  1  ⋅  1  ⋅
 ⋅  ⋅  1  ⋅  ⋅

julia> y_model = softmax(reshape(-7:7, 3, 5) .* 1f0)
3×5 Matrix{Float32}:
 0.0900306  0.0900306  0.0900306  0.0900306  0.0900306
 0.244728   0.244728   0.244728   0.244728   0.244728
 0.665241   0.665241   0.665241   0.665241   0.665241

julia> sum(y_model; dims=1)
1×5 Matrix{Float32}:
 1.0  1.0  1.0  1.0  1.0

julia> Flux.crossentropy(y_model, y_label)
1.6076053f0

julia> 5 * ans ≈ Flux.crossentropy(y_model, y_label; agg=sum)
true

julia> y_smooth = Flux.label_smoothing(y_label, 0.15f0)
3×5 Matrix{Float32}:
 0.9   0.05  0.05  0.05  0.9
 0.05  0.9   0.05  0.9   0.05
 0.05  0.05  0.9   0.05  0.05

julia> Flux.crossentropy(y_model, y_smooth)
1.5776052f0

# Flux.Losses.logitcrossentropyFunction

logitcrossentropy(ŷ, y; dims = 1, agg = mean)

Возвращает перекрестную энтропию, вычисляемую следующим образом:

agg(-sum(y .* logsoftmax(ŷ; dims); dims))

Математически эквивалентна crossentropy(softmax(ŷ), y), но численно более устойчива, чем использование функций crossentropy и softmax по отдельности.

См. также описание binarycrossentropy, logitbinarycrossentropy, label_smoothing.

Пример

julia> y_label = Flux.onehotbatch(collect("abcabaa"), 'a':'c')
3×7 OneHotMatrix(::Vector{UInt32}) with eltype Bool:
 1  ⋅  ⋅  1  ⋅  1  1
 ⋅  1  ⋅  ⋅  1  ⋅  ⋅
 ⋅  ⋅  1  ⋅  ⋅  ⋅  ⋅

julia> y_model = reshape(vcat(-9:0, 0:9, 7.5f0), 3, 7)
3×7 Matrix{Float32}:
 -9.0  -6.0  -3.0  0.0  2.0  5.0  8.0
 -8.0  -5.0  -2.0  0.0  3.0  6.0  9.0
 -7.0  -4.0  -1.0  1.0  4.0  7.0  7.5

julia> Flux.logitcrossentropy(y_model, y_label)
1.5791205f0

julia> Flux.crossentropy(softmax(y_model), y_label)
1.5791197f0

# Flux.Losses.binarycrossentropyFunction

binarycrossentropy(ŷ, y; agg = mean, eps = eps(eltype(ŷ)))

Возвращает потери бинарной перекрестной энтропии, вычисляемые следующим образом.

agg(@.(-y * log(ŷ + ϵ) - (1 - y) * log(1 - ŷ + ϵ)))

Где обычно предсказание задается выходными данными сигмоидной функции активации. Член ϵ == eps включен, чтобы избежать бесконечности. Для обеспечения численной устойчивости рекомендуется использовать logitbinarycrossentropy, а не binarycrossentropy.

Используйте label_smoothing для сглаживания значения y в качестве предварительной обработки перед вычислением потерь.

См. также описание crossentropy, logitcrossentropy.

Примеры

julia> y_bin = Bool[1,0,1]
3-element Vector{Bool}:
 1
 0
 1

julia> y_prob = softmax(reshape(vcat(1:3, 3:5), 2, 3) .* 1f0)
2×3 Matrix{Float32}:
 0.268941  0.5  0.268941
 0.731059  0.5  0.731059

julia> Flux.binarycrossentropy(y_prob[2,:], y_bin)
0.43989f0

julia> all(p -> 0 < p < 1, y_prob[2,:])  # иначе DomainError
true

julia> y_hot = Flux.onehotbatch(y_bin, 0:1)
2×3 OneHotMatrix(::Vector{UInt32}) with eltype Bool:
 ⋅  1  ⋅
 1  ⋅  1

julia> Flux.crossentropy(y_prob, y_hot)
0.43989f0

# Flux.Losses.logitbinarycrossentropyFunction

logitbinarycrossentropy(ŷ, y; agg = mean)

Математически эквивалентна binarycrossentropy(σ(ŷ), y), но численно более устойчива.

См. также описание crossentropy, logitcrossentropy.

Примеры

julia> y_bin = Bool[1,0,1];

julia> y_model = Float32[2, -1, pi]
3-element Vector{Float32}:
  2.0
 -1.0
  3.1415927

julia> Flux.logitbinarycrossentropy(y_model, y_bin)
0.160832f0

julia> Flux.binarycrossentropy(sigmoid.(y_model), y_bin)
0.16083185f0

# Flux.Losses.kldivergenceFunction

kldivergence(ŷ, y; agg = mean, eps = eps(eltype(ŷ)))

Возвращает дивергенцию Кульбака-Лейблера между заданными распределениями вероятностей.

Дивергенция Кульбака-Лейблера — это мера удаленности двух распределений вероятности друг от друга. Она всегда неотрицательна и равна нулю только тогда, когда оба распределения равны.

Пример

julia> p1 = [1 0; 0 1]
2×2 Matrix{Int64}:
 1  0
 0  1

julia> p2 = fill(0.5, 2, 2)
2×2 Matrix{Float64}:
 0.5  0.5
 0.5  0.5

julia> Flux.kldivergence(p2, p1) ≈ log(2)
true

julia> Flux.kldivergence(p2, p1; agg = sum) ≈ 2log(2)
true

julia> Flux.kldivergence(p2, p2; eps = 0)  # около -2e-16 с регулятором
0.0

julia> Flux.kldivergence(p1, p2; eps = 0)  # около 17.3 с регулятором
Inf

# Flux.Losses.poisson_lossFunction

poisson_loss(ŷ, y; agg = mean)

Возвращает, насколько сильно предсказанное распределение расходится с ожидаемым распределением Пуассона y. Вычисляется следующим образом:

sum(ŷ .- y .* log.(ŷ)) / size(y, 2)

Пример

julia> y_model = [1, 3, 3];  # данные должны принимать только целые значения

julia> Flux.poisson_loss(y_model, 1:3)
0.5023128522198171

# Flux.Losses.hinge_lossFunction

hinge_loss(ŷ, y; agg = mean)

Возвращает hinge_loss при заданном предсказании и истинных метках y (содержащих 1 или -1). Вычисляется следующим образом:

sum(max.(0, 1 .- ŷ .* y)) / size(y, 2)

Обычно используется с классификаторами типа машин опорных векторов. См. также описание squared_hinge_loss.

Пример

julia> y_true = [1, -1, 1, 1];

julia> y_pred = [0.1, 0.3, 1, 1.5];

julia> Flux.hinge_loss(y_pred, y_true)
0.55

julia> Flux.hinge_loss(y_pred[1], y_true[1]) != 0  # тот же знак, но |ŷ| < 1
true

julia> Flux.hinge_loss(y_pred[end], y_true[end]) == 0  # тот же знак, но |ŷ| >= 1
true

julia> Flux.hinge_loss(y_pred[2], y_true[2]) != 0 # противоположные знаки
true

# Flux.Losses.squared_hinge_lossFunction

squared_hinge_loss(ŷ, y)

Возвращает квадрат потерь hinge_loss при заданном предсказании и истинных метках y (содержащих 1 или -1). Вычисляется следующим образом:

sum((max.(0, 1 .- ŷ .* y)).^2) / size(y, 2)

Обычно используется с классификаторами типа машин опорных векторов. См. также описание hinge_loss.

Пример

julia> y_true = [1, -1, 1, 1];

julia> y_pred = [0.1, 0.3, 1, 1.5];

julia> Flux.squared_hinge_loss(y_pred, y_true)
0.625

julia> Flux.squared_hinge_loss(y_pred[1], y_true[1]) != 0
true

julia> Flux.squared_hinge_loss(y_pred[end], y_true[end]) == 0
true

julia> Flux.squared_hinge_loss(y_pred[2], y_true[2]) != 0
true

# Flux.Losses.dice_coeff_lossFunction

dice_coeff_loss(ŷ, y; smooth = 1)

Возвращает потерю на основе коэффициента Дайса. Используется в архитектуре сегментации изображений V-Net . Коэффициент Дайса аналогичен F1_score. Потеря вычисляется следующим образом:

1 - 2*sum(|ŷ .* y| + smooth) / (sum(ŷ.^2) + sum(y.^2) + smooth)

Пример

julia> y_pred = [1.1, 2.1, 3.1];

julia> Flux.dice_coeff_loss(y_pred, 1:3)
0.000992391663909964

julia> 1 - Flux.dice_coeff_loss(y_pred, 1:3)  # ~ показатель F1 для сегментации изображений
0.99900760833609

# Flux.Losses.tversky_lossFunction

tversky_loss(ŷ, y; beta = 0.7)

Возвращает потерю Тверски. Используется с несбалансированными данными, чтобы придать больший вес ложноотрицательным результатам. Большее значение β == beta имеет больший вес, чем точность (за счет большего внимания к ложноотрицательным результатам). Вычисляется следующим образом:

1 - sum(|y .* ŷ| + 1) / (sum(y .* ŷ + (1 - β)*(1 .- y) .* ŷ + β*y .* (1 .- ŷ)) + 1)

# Flux.Losses.binary_focal_lossFunction

binary_focal_loss(ŷ, y; agg=mean, gamma=2, eps=eps(eltype(ŷ)))

Возвращает binaryfocalloss Входное значение, ŷ, должно быть нормализовано (см. вывод softmax).

Для gamma = 0 потеря математически эквивалентна Losses.binarycrossentropy.

См. также описание Losses.focal_loss для использования в нескольких классах.

Пример

julia> y = [0  1  0
            1  0  1]
2×3 Matrix{Int64}:
 0  1  0
 1  0  1

julia> ŷ = [0.268941  0.5  0.268941
            0.731059  0.5  0.731059]
2×3 Matrix{Float64}:
 0.268941  0.5  0.268941
 0.731059  0.5  0.731059

julia> Flux.binary_focal_loss(ŷ, y) ≈ 0.0728675615927385
true

# Flux.Losses.focal_lossFunction

focal_loss(ŷ, y; dims=1, agg=mean, gamma=2, eps=eps(eltype(ŷ)))

Возвращает значение focal_loss, которое можно использовать в задачах классификации с крайне несбалансированными классами. Снижает вес хорошо классифицированных примеров и фокусируется на сложных примерах. Входное значение, ŷ, должно быть нормализовано (см. вывод softmax).

Модулирующий фактор γ == gamma управляет силой понижения веса. Для γ == 0 потеря математически эквивалентна Losses.crossentropy.

Пример

julia> y = [1  0  0  0  1
            0  1  0  1  0
            0  0  1  0  0]
3×5 Matrix{Int64}:
 1  0  0  0  1
 0  1  0  1  0
 0  0  1  0  0

julia> ŷ = softmax(reshape(-7:7, 3, 5) .* 1f0)
3×5 Matrix{Float32}:
 0.0900306  0.0900306  0.0900306  0.0900306  0.0900306
 0.244728   0.244728   0.244728   0.244728   0.244728
 0.665241   0.665241   0.665241   0.665241   0.665241

julia> Flux.focal_loss(ŷ, y) ≈ 1.1277571935622628
true

См. также описание Losses.binary_focal_loss для бинарных (без одного активного состояния) меток.

# Flux.Losses.siamese_contrastive_lossFunction

siamese_contrastive_loss(ŷ, y; margin = 1, agg = mean)

Возвращает контрастные потери, которые могут быть полезны для обучения сиамских сетей. Задается следующим образом:

agg(@. (1 - y) * ŷ^2 + y * max(0, margin - ŷ)^2)

Укажите margin, чтобы установить базовое значение для расстояния, на котором пары становятся разными.

Пример

julia> ŷ = [0.5, 1.5, 2.5];

julia> Flux.siamese_contrastive_loss(ŷ, 1:3)
-4.833333333333333

julia> Flux.siamese_contrastive_loss(ŷ, 1:3, margin = 2)
-4.0