Fit et selection de modèle

Motivation

J’utilise Distribution dans la plupart de mes applications mais je ne lui laisse pas exprimer son plein potentiel, et celui du package distribution. j’ai donc souhaité créer une application entièrement dédiée à ces outils.

L’outil

Ici l’utilisateur peut uploader le dataset de son choix. choix Une liste déroulante des différentes colonnes sera disponible pour qu’il puisse en visualiser la distribution.

Julia va ensuite fit la colonne selectionée par l’utilisateur a un grand nombre de lois pré-enregistrées. On va ensuite calculer le critère d’information d’Akaike avec la formule suivante:

\[AIC = 2k - 2l + \frac{2k^2 + 2k}{n - k - 1} \]

Où:

    - k: nombre de parametre du modèle 
    - n: taille du dataset 
    - l: logvraissemblance de l'échantillon par rapport à la loi considérée

Le troisième terme est une pénalité sur la taille de la série considérée, car pour des petites séries, AIC va avoir tendance à sélectionner des modèles à nombreux paramètres.

L’application va lui plotter la densité de la distribution correspondante au modèle le plus adapté, Et on plottera également la distribution liée au modèle non paramétrique de la méthode des noyaux.

Code
using DataFrames
using RDatasets
using StatsPlots
using Distributions
function akaike_estimate(v::Array, d)
        l,k = log_vraisemblance(v,d)
    
        # Pour les petits datasets AIC va selectioner les lois a plusieurs parametres
        # On prévient l'overfitting en ajoutant un correcteur (qui sannule si n grand)
        correcteur = (2k^2 + 2k) / (length(v) - k - 1)

        return 2*k - 2*l + correcteur
end

function log_vraisemblance(v,d)
        # retourne: [log-vraisemblance, nbparams]
    loi =   try 
                fit(d ,v)
            catch e 
                    println("probleme de support")
                    println(e)
                0                               
            end
    if loi == 0 
            return [99^100,1]
    else
        println("loi $(loi)")
        # ll calculée a la main: temp = logpdf.(loi,v) |> sum
        temp = loglikelihood(loi,v)
        if temp == -Inf 
                return [99^100,1]
        end
        return [temp, length(params(loi))]
    end
end

function get_errors(v::Array)
    dist_list = [
            Normal,
            Beta,
            Exponential,
            Cauchy,
            #Poisson,
            Gamma,
            Laplace,
            Rayleigh,
            Uniform]
            
    akaike_list = [akaike_estimate(v,d) for d in dist_list]

    df = DataFrame(
            Distributions = dist_list,
            #erreur = erreur_liste,
            akaike_estimate = akaike_list
        )
    sort!(df,[order(:akaike_estimate, rev =false)])
    return df
            
end

iris = dataset("datasets", "iris")

data = iris.SepalLength

tab_akaike = get_errors(data)


l = fit(tab_akaike[1,1],data)
l2 = fit(Normal,data)

b_inf = minimum(data) 
b_sup = maximum(data) 
Code
tab_akaike
8×2 DataFrame
RowDistributionsakaike_estimate
UnionAllFloat64
1Gamma368.694
2Normal372.161
3Uniform388.362
4Laplace398.379
5Cauchy445.121
6Rayleigh632.571
7Exponential831.617
8Beta6.82478e18
Code
using KernelDensity
x = range(b_inf,b_sup,200)

histogram(data, 
        bins = 25,
        normalize = true, 
        size = (1000,850), 
        label = "Distribution sepal length")

plot!(x,pdf.(l,x), 
    label = "Meilleur fit $(tab_akaike[1,1]) $(round.(params(l)))", 
    lw = 3)

plot!(range(b_inf, b_sup, length =length(kde(data).density)), 
        kde(data).density, 
        label = "Densité des noyaux", 
        lw = 3)