rho_loss(y::AbstractVector{Y}, x::AbstractVector{X}, rho::AbstractFloat = Float16(0.5f0)) where {Y<:Real, X<:Real} =
    rho_loss.(y, x, rho);
function rho_loss(y::Real, x::Real, rho::AbstractFloat = Float16(0.5f0))
    diff = y - x;
    over = rho * diff;
    under = (1 - rho) * -diff;
    return 2 * max(over, under);
end



function deepAR_ql(y::AbstractVector{V}, x::AbstractVector{V}, rho::AbstractFloat = Float16(0.5f0)) where {V<:AbstractVector}
    sum_y = 0.0;
    sum_rho = 0.0;

    for (vy, vx) in zip(y, x)
        rl, sl = deepAR_ql(vy, vx, rho);
        sum_rho += rl;
        sum_y += sl;
    end

    return sum_rho, sum_y    
end
function deepAR_ql(y::AbstractMatrix{Y}, x::AbstractMatrix{X}, rho::AbstractFloat = Float16(0.5f0)) where {Y<:Real, X<:Real}
    sum_y = 0.0;
    sum_rho = 0.0;

    for (rowy, rowx) in zip(eachrow(y), eachrow(x))
        rl, sl = deepAR_ql(rowy, rowx, rho);
        sum_rho += rl;
        sum_y += sl;
    end

    return sum_rho, sum_y    
end
function deepAR_ql(y::AbstractVector{Y}, x::AbstractVector{X}, rho::AbstractFloat = Float16(0.5f0)) where {Y<:Real, X<:Real}
    sum_y = sum(y);
    sum_x = sum(x);

    rLoss = rho_loss(sum_x, sum_y, rho);

    return rLoss, sum_y
end



function deepSSM_ql(y::AbstractVector{V}, x::AbstractVector{V}, rho::AbstractFloat = Float16(0.5f0)) where {V<:AbstractVector}
    sum_y = 0.0;
    sum_rho = 0.0;

    for (vy, vx) in zip(y, x)
        sr, sl = deepSSM_ql(vy, vx, rho);
        sum_rho += sr;
        sum_y += sl;
    end

    return sum_rho, sum_y    
end
function deepSSM_ql(y::AbstractMatrix{Y}, x::AbstractMatrix{X}, rho::AbstractFloat = Float16(0.5f0)) where {Y<:Real, X<:Real}
    sum_y = 0.0;
    sum_rho = 0.0;

    for (rowy, rowx) in zip(eachrow(y), eachrow(x))
        sr, sl = deepSSM_ql(rowy, rowx, rho);
        sum_rho += sr;
        sum_y += sl;
    end

    return sum_rho, sum_y    
end
function deepSSM_ql(y::AbstractVector{Y}, x::AbstractVector{X}, rho::AbstractFloat = Float16(0.5f0)) where {Y<:Real, X<:Real}
    sum_y = sum(y);
    sum_rho = 0.0;

    for (yi, xi) in zip(y, x)
        sum_rho += rho_loss(yi, xi, rho);
    end

    return sum_rho, sum_y
end

function nb_loss(yhats::Union{H, AbstractVecOrMat{H}},
                 labels::Union{L, AbstractVecOrMat{L}};
                 theta::Union{H, AbstractVecOrMat{H}}) where {H, L}
    tmpr = yhats .* inv.(theta);
    r = softplus.(tmpr);
    tmpp = theta ./ (1.0f0 .+ theta);
    p = sigmoid.(tmpp);
    ls = negative_binomial_loglikelihood.(r, p, labels);
    return ls;
end