Функции потерь
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.mae
— Function
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.mse
— Function
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.msle
— Function
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_loss
— Function
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_smoothing
— Function
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.crossentropy
— Function
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.logitcrossentropy
— Function
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.binarycrossentropy
— Function
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.logitbinarycrossentropy
— Function
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.kldivergence
— Function
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_loss
— Function
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_loss
— Function
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_loss
— Function
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_loss
— Function
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_loss
— Function
tversky_loss(ŷ, y; beta = 0.7)
Возвращает потерю Тверски. Используется с несбалансированными данными, чтобы придать больший вес ложноотрицательным результатам. Большее значение β == beta
имеет больший вес, чем точность (за счет большего внимания к ложноотрицательным результатам). Вычисляется следующим образом:
1 - sum(|y .* ŷ| + 1) / (sum(y .* ŷ + (1 - β)*(1 .- y) .* ŷ + β*y .* (1 .- ŷ)) + 1)
#
Flux.Losses.binary_focal_loss
— Function
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_loss
— Function
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_loss
— Function
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