This commit is contained in:
cossio 2020-05-05 18:29:51 +02:00
parent c444226db5
commit 480473a81b
2 changed files with 41 additions and 19 deletions

View File

@ -54,15 +54,15 @@ function huber_loss(ŷ, y; δ=eltype(ŷ)(1))
end end
function _crossentropy(::AbstractVecOrMat, y::AbstractVecOrMat, weight::Nothing) function _crossentropy(::AbstractVecOrMat, y::AbstractVecOrMat, weight::Nothing)
return -sum(y .* log.()) * 1 // size(y, 2) return -sum(xlogy.(y, )) * 1 // size(y, 2)
end end
function _crossentropy(::AbstractVecOrMat, y::AbstractVecOrMat, weight::Number) function _crossentropy(::AbstractVecOrMat, y::AbstractVecOrMat, weight::Number)
return -sum(y .* log.()) .* weight * 1 // size(y, 2) return -sum(xlogy.(y, )) .* weight * 1 // size(y, 2)
end end
function _crossentropy(::AbstractVecOrMat, y::AbstractVecOrMat, weight::AbstractVector) function _crossentropy(::AbstractVecOrMat, y::AbstractVecOrMat, weight::AbstractVector)
return -sum(y .* log.() .* weight) * 1 // size(y, 2) return -sum(xlogy.(y, ) .* weight) * 1 // size(y, 2)
end end
""" """
@ -123,7 +123,7 @@ julia> Flux.binarycrossentropy.(σ.([-1.1491, 0.8619, 0.3127]), [1, 1, 0])
0.8616703662235441 0.8616703662235441
``` ```
""" """
binarycrossentropy(, y; ϵ=eps()) = -y*log( + ϵ) - (1 - y)*log(1 - + ϵ) binarycrossentropy(, y; ϵ=eps()) = -xlogy(y, + ϵ) - xlogy(1 - y, 1 - + ϵ)
# Re-definition to fix interaction with CuArrays. # Re-definition to fix interaction with CuArrays.
CuArrays.@cufunc binarycrossentropy(, y; ϵ=eps()) = -y*log( + ϵ) - (1 - y)*log(1 - + ϵ) CuArrays.@cufunc binarycrossentropy(, y; ϵ=eps()) = -y*log( + ϵ) - (1 - y)*log(1 - + ϵ)
@ -195,7 +195,7 @@ It is always non-negative and zero only when both the distributions are equal
everywhere. everywhere.
""" """
function kldivergence(, y) function kldivergence(, y)
entropy = sum(y .* log.(y)) * 1 //size(y,2) entropy = sum(xlogx.(y)) * 1 //size(y,2)
cross_entropy = crossentropy(, y) cross_entropy = crossentropy(, y)
return entropy + cross_entropy return entropy + cross_entropy
end end
@ -208,7 +208,7 @@ distribution `y`; calculated as `sum(ŷ .- y .* log.(ŷ)) / size(y, 2)`.
[More information.](https://peltarion.com/knowledge-center/documentation/modeling-view/build-an-ai-model/loss-functions/poisson). [More information.](https://peltarion.com/knowledge-center/documentation/modeling-view/build-an-ai-model/loss-functions/poisson).
""" """
poisson(, y) = sum( .- y .* log.()) * 1 // size(y,2) poisson(, y) = sum( .- xlogy.(y, )) * 1 // size(y,2)
""" """
hinge(, y) hinge(, y)
@ -262,3 +262,16 @@ by linearizing all values for each element in the batch.
function flatten(x::AbstractArray) function flatten(x::AbstractArray)
return reshape(x, :, size(x)[end]) return reshape(x, :, size(x)[end])
end end
"""
xlogx(x::Real)
Return `x * log(x)` for `x ≥ 0`, handling `x = 0` by taking the downward limit.
"""
xlogx(x::Real) = x > zero(x) ? x * log(x) : zero(log(x))
"""
xlogy(x::Real, y::Real)
Return `x * log(y)` for `y > 0` with correct limit at `x = 0`.
"""
xlogy(x::T, y::T) where {T<:Real} = x > zero(T) ? x * log(y) : zero(log(x))
xlogy(x::Real, y::Real) = xlogy(promote(x, y)...)

View File

@ -1,9 +1,18 @@
using Test using Test
using Flux: onehotbatch, mse, crossentropy, logitcrossentropy, using Flux: onehotbatch, mse, crossentropy, logitcrossentropy,
σ, binarycrossentropy, logitbinarycrossentropy, flatten σ, binarycrossentropy, logitbinarycrossentropy, flatten,
xlogx, xlogy
const ϵ = 1e-7 const ϵ = 1e-7
@testset "xlogx & xlogy" begin
@test iszero(xlogx(0))
@test xlogx(2) 2.0 * log(2.0)
@test iszero(xlogy(0, 1))
@test xlogy(2, 3) 2.0 * log(3.0)
end
@testset "losses" begin @testset "losses" begin
# First, regression-style y's # First, regression-style y's
y = [1, 1, 0, 0] y = [1, 1, 0, 0]