# Environnement - Packages¶

In [176]:

    # activer l'environnement
    using Pkg
    Pkg.activate("env_julia_dtc")

      Activating project at `c:\Users\ricco\Desktop\demo\env_julia_dtc`

In [177]:

    # liste des packages installés
    Pkg.status()

    Status `C:\Users\ricco\Desktop\demo\env_julia_dtc\Project.toml`
      [324d7699] CategoricalArrays v1.1.0
      [a93c6f00] DataFrames v1.8.2
      [7806a523] DecisionTree v0.12.4
      [f526b714] GraphViz v0.2.0
      [7073ff75] IJulia v1.34.4
      [add582a8] MLJ v0.23.2
      [c6f25543] MLJDecisionTreeInterface v0.4.4
      [23777cdb] MLJTransforms v0.1.5
      [30f210dd] ScientificTypesBase v3.1.0
      [2913bbd2] StatsBase v0.34.10
      [fdbf4ff8] XLSX v0.11.4

# Importation, préparation des données¶

### Chargement - Inspection¶

In [178]:

    # packages
    import DataFrames as DFR
    import XLSX

    # lecture des données
    df = DFR.DataFrame(XLSX.readtable("./data_marketing.xlsx"))

    # premières lignes
    println(DFR.size(df))

    (10000, 16)

In [179]:

    # description
    println(DFR.describe(df))

    16×7 DataFrame
     Row │ variable           mean      min               median   max           nmissing  eltype
         │ Symbol             Union…    Any               Union…   Any           Int64     DataType
    ─────┼──────────────────────────────────────────────────────────────────────────────────────────
       1 │ age                43.5394   18                43.0     69                   0  Int64
       2 │ revenu_annuel      50134.8   20000.0           49957.2  1.02936e5            0  Float64
       3 │ score_credit       679.969   500.0             680.325  850.0                0  Float64
       4 │ anciennete_client  9.4085    0                 9.0      19                   0  Int64
       5 │ panier_montant     1509.94   200.0             1494.4   4482.27              0  Float64
       6 │ sensibilite_promo  0.500272  0.0               0.49955  0.9999               0  Float64
       7 │ frequence_achat    7.504     1                 8.0      14                   0  Int64
       8 │ taux_endettement   35.1021   10.01             35.175   59.99                0  Float64
       9 │ region_risque      0.300578  0.1001            0.30215  0.4999               0  Float64
      10 │ type_produit                 automobile                 electronique         0  String
      11 │ canal_achat                  magasin                    web                  0  String
      12 │ nb_cartes_credit   2.1078    1                 2.0      6                    0  Int64
      13 │ incident_paiement  0.3168    0                 0.0      1                    0  Int64
      14 │ epargne            35066.0   4107.22           32519.9  100000.0             0  Float64
      15 │ stabilite_emploi   0.697161  0.0               0.7042   1.0                  0  Float64
      16 │ financement                  credit_classique           paiement_3x          0  String

In [180]:

    # schema : types au sens de MLJ
    import MLJ
    MLJ.schema(df)

    ┌───────────────────┬────────────┬─────────┐
    │ names             │ scitypes   │ types   │
    ├───────────────────┼────────────┼─────────┤
    │ age               │ Count      │ Int64   │
    │ revenu_annuel     │ Continuous │ Float64 │
    │ score_credit      │ Continuous │ Float64 │
    │ anciennete_client │ Count      │ Int64   │
    │ panier_montant    │ Continuous │ Float64 │
    │ sensibilite_promo │ Continuous │ Float64 │
    │ frequence_achat   │ Count      │ Int64   │
    │ taux_endettement  │ Continuous │ Float64 │
    │ region_risque     │ Continuous │ Float64 │
    │ type_produit      │ Textual    │ String  │
    │ canal_achat       │ Textual    │ String  │
    │ nb_cartes_credit  │ Count      │ Int64   │
    │ incident_paiement │ Count      │ Int64   │
    │ epargne           │ Continuous │ Float64 │
    │ stabilite_emploi  │ Continuous │ Float64 │
    │ financement       │ Textual    │ String  │
    └───────────────────┴────────────┴─────────┘

### Préparation des structures y vs. X¶

In [181]:

    # isoler y et X dans des structures distinctes
    y, X = MLJ.unpack(df,==(:financement))

    # dimensions
    println("Dim. de y = $(DFR.size(y))")
    println("Dim. de X = $(DFR.size(X))")

    Dim. de y = (10000,)
    Dim. de X = (10000, 15)

In [182]:

    # effectifs par classe
    import StatsBase
    StatsBase.countmap(y)

    Dict{String, Int64} with 3 entries:
      "paiement_3x"      => 5920
      "l_o_a"            => 2613
      "credit_classique" => 1467

### Typage des variables pour la modélisation¶

In [183]:

    # typage de la variable cible
    import CategoricalArrays as CA
    y = CA.categorical(y)

    # vérification des modalités
    CA.levels(y)

    3-element CategoricalArrays.CategoricalArray{String,1,UInt32}:
     "credit_classique"
     "l_o_a"
     "paiement_3x"

In [184]:

    # typer correctement les X à modifier
    # en les énumérant individuellement
    # utilisation du package ScientificTypesBase
    import ScientificTypesBase as STB
    MLJ.coerce!(X,
                :age => STB.Continuous,
                :anciennete_client => STB.Continuous,
                :frequence_achat => STB.Continuous,
                :type_produit => STB.Multiclass,
                :canal_achat => STB.Multiclass,
                :nb_cartes_credit => STB.Continuous,
                :incident_paiement => STB.Continuous)

    # schéma
    MLJ.schema(X)

    ┌───────────────────┬───────────────┬──────────────────────────────────┐
    │ names             │ scitypes      │ types                            │
    ├───────────────────┼───────────────┼──────────────────────────────────┤
    │ age               │ Continuous    │ Float64                          │
    │ revenu_annuel     │ Continuous    │ Float64                          │
    │ score_credit      │ Continuous    │ Float64                          │
    │ anciennete_client │ Continuous    │ Float64                          │
    │ panier_montant    │ Continuous    │ Float64                          │
    │ sensibilite_promo │ Continuous    │ Float64                          │
    │ frequence_achat   │ Continuous    │ Float64                          │
    │ taux_endettement  │ Continuous    │ Float64                          │
    │ region_risque     │ Continuous    │ Float64                          │
    │ type_produit      │ Multiclass{3} │ CategoricalValue{String, UInt32} │
    │ canal_achat       │ Multiclass{3} │ CategoricalValue{String, UInt32} │
    │ nb_cartes_credit  │ Continuous    │ Float64                          │
    │ incident_paiement │ Continuous    │ Float64                          │
    │ epargne           │ Continuous    │ Float64                          │
    │ stabilite_emploi  │ Continuous    │ Float64                          │
    └───────────────────┴───────────────┴──────────────────────────────────┘

### Codage des descripteurs catégoriels¶

In [185]:

    # one-hot encoder pour les descripteurscatégoriels
    OneHotEncoder = @MLJ.load OneHotEncoder pkg=MLJTransforms

    import MLJTransforms ✔

    ┌ Info: For silent loading, specify `verbosity=0`.
    └ @ Main C:\Users\ricco\.julia\packages\MLJModels\9LbNu\src\loading.jl:159

    MLJTransforms.OneHotEncoder

In [186]:

    # encodage (par défaut, pas de modalité exclue)
    # instanciation et préparation
    ohe = MLJ.machine(OneHotEncoder(),X)

    # entraînement
    MLJ.fit!(ohe)

    # transformation
    XPrim = MLJ.transform(ohe,X)

    ┌ Info: Training machine(OneHotEncoder(features = Symbol[], …), …).
    └ @ MLJBase C:\Users\ricco\.julia\packages\MLJBase\krfwA\src\machines.jl:499
    ┌ Info: Spawning 3 sub-features to one-hot encode feature :type_produit.
    └ @ MLJTransforms C:\Users\ricco\.julia\packages\MLJTransforms\rATN1\src\transformers\other_transformers\one_hot_encoder.jl:67
    ┌ Info: Spawning 3 sub-features to one-hot encode feature :canal_achat.
    └ @ MLJTransforms C:\Users\ricco\.julia\packages\MLJTransforms\rATN1\src\transformers\other_transformers\one_hot_encoder.jl:67

10000×19 DataFrame
9975 rows omitted

Row | age | revenu_annuel | score_credit | anciennete_client | panier_montant | sensibilite_promo | frequence_achat | taux_endettement | region_risque | type_produit__automobile | type_produit__electromenager | type_produit__electronique | canal_achat__magasin | canal_achat__mobile | canal_achat__web | nb_cartes_credit | incident_paiement | epargne | stabilite_emploi
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
| Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64 | Float64
1 | 56.0 | 37214.2 | 733.34 | 18.0 | 674.91 | 0.6048 | 3.0 | 17.25 | 0.4908 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 2.0 | 0.0 | 22395.3 | 0.9081
2 | 69.0 | 57130.5 | 701.2 | 13.0 | 2413.49 | 0.3271 | 6.0 | 29.22 | 0.1043 | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 0.0 | 3.0 | 0.0 | 11986.1 | 0.7551
3 | 46.0 | 59486.8 | 715.98 | 16.0 | 2048.7 | 0.8174 | 12.0 | 49.62 | 0.3656 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 2.0 | 0.0 | 24541.2 | 0.6869
4 | 32.0 | 42887.3 | 756.3 | 14.0 | 1494.53 | 0.1354 | 1.0 | 31.08 | 0.4172 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 2.0 | 1.0 | 32215.9 | 0.7385
5 | 60.0 | 38423.4 | 671.0 | 5.0 | 909.72 | 0.8817 | 12.0 | 14.99 | 0.3556 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 | 1.0 | 21098.7 | 0.8862
6 | 25.0 | 74142.8 | 613.07 | 18.0 | 1034.89 | 0.9747 | 12.0 | 14.8 | 0.2092 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 3.0 | 1.0 | 76838.1 | 0.7647
7 | 38.0 | 53412.4 | 758.07 | 19.0 | 2958.34 | 0.9677 | 4.0 | 21.85 | 0.4291 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 3.0 | 1.0 | 46627.2 | 0.6407
8 | 56.0 | 59539.5 | 648.21 | 5.0 | 1642.75 | 0.1477 | 9.0 | 38.24 | 0.4653 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 3.0 | 0.0 | 21234.0 | 0.6609
9 | 36.0 | 37668.9 | 638.58 | 5.0 | 2563.89 | 0.5496 | 2.0 | 51.51 | 0.3734 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 42762.7 | 0.8463
10 | 40.0 | 31710.7 | 572.23 | 3.0 | 1693.25 | 0.5849 | 2.0 | 36.69 | 0.3044 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 13997.1 | 0.4952
11 | 28.0 | 41458.2 | 714.28 | 0.0 | 1137.84 | 0.1949 | 2.0 | 47.3 | 0.2465 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 2.0 | 0.0 | 10809.5 | 0.8906
12 | 28.0 | 48139.7 | 582.71 | 18.0 | 1967.27 | 0.5468 | 10.0 | 42.28 | 0.232 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 2.0 | 1.0 | 33027.9 | 0.3127
13 | 41.0 | 34036.7 | 634.98 | 10.0 | 3226.27 | 0.6465 | 10.0 | 36.2 | 0.3893 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 2.0 | 1.0 | 21709.4 | 0.7146
⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮ | ⋮
9989 | 41.0 | 54902.5 | 609.66 | 19.0 | 1361.18 | 0.5281 | 3.0 | 41.17 | 0.3285 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 3.0 | 0.0 | 36557.0 | 0.6157
9990 | 23.0 | 62980.4 | 676.76 | 17.0 | 1133.09 | 0.4147 | 10.0 | 49.29 | 0.4074 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 2.0 | 1.0 | 45079.1 | 1.0
9991 | 44.0 | 51340.4 | 580.87 | 12.0 | 943.65 | 0.9199 | 14.0 | 29.19 | 0.424 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 2.0 | 0.0 | 19148.5 | 0.8463
9992 | 35.0 | 64768.6 | 666.04 | 7.0 | 1626.23 | 0.4052 | 8.0 | 54.18 | 0.2328 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 3.0 | 0.0 | 26832.0 | 0.8973
9993 | 41.0 | 59211.6 | 653.52 | 13.0 | 528.71 | 0.596 | 10.0 | 46.78 | 0.3493 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 2.0 | 0.0 | 59188.2 | 0.7929
9994 | 54.0 | 44602.4 | 671.94 | 2.0 | 2243.38 | 0.6919 | 8.0 | 40.3 | 0.2743 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 2.0 | 0.0 | 39378.8 | 0.7103
9995 | 41.0 | 63437.8 | 646.44 | 3.0 | 634.77 | 0.019 | 11.0 | 19.92 | 0.1392 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 3.0 | 0.0 | 33575.5 | 0.891
9996 | 55.0 | 51372.2 | 589.54 | 10.0 | 486.33 | 0.5909 | 14.0 | 43.51 | 0.3594 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 2.0 | 1.0 | 51140.1 | 0.6452
9997 | 51.0 | 48408.0 | 658.02 | 6.0 | 1298.16 | 0.518 | 8.0 | 51.69 | 0.335 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 3.0 | 0.0 | 12281.5 | 0.3953
9998 | 57.0 | 42857.0 | 735.85 | 4.0 | 1202.0 | 0.594 | 4.0 | 46.5 | 0.141 | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 0.0 | 1.0 | 1.0 | 11600.2 | 0.6747
9999 | 64.0 | 52490.3 | 755.69 | 1.0 | 1784.45 | 0.0757 | 7.0 | 38.74 | 0.1283 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 2.0 | 0.0 | 15144.0 | 0.6815
10000 | 32.0 | 64946.9 | 826.36 | 5.0 | 1567.87 | 0.0556 | 10.0 | 45.73 | 0.1999 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 4.0 | 1.0 | 58678.1 | 1.0

In [187]:

    # description
    DFR.describe(XPrim)

19×7 DataFrame

Row | variable | mean | min | median | max | nmissing | eltype
--- | --- | --- | --- | --- | --- | --- | ---
| Symbol | Float64 | Float64 | Float64 | Float64 | Int64 | DataType
1 | age | 43.5394 | 18.0 | 43.0 | 69.0 | 0 | Float64
2 | revenu_annuel | 50134.8 | 20000.0 | 49957.2 | 1.02936e5 | 0 | Float64
3 | score_credit | 679.969 | 500.0 | 680.325 | 850.0 | 0 | Float64
4 | anciennete_client | 9.4085 | 0.0 | 9.0 | 19.0 | 0 | Float64
5 | panier_montant | 1509.94 | 200.0 | 1494.4 | 4482.27 | 0 | Float64
6 | sensibilite_promo | 0.500272 | 0.0 | 0.49955 | 0.9999 | 0 | Float64
7 | frequence_achat | 7.504 | 1.0 | 8.0 | 14.0 | 0 | Float64
8 | taux_endettement | 35.1021 | 10.01 | 35.175 | 59.99 | 0 | Float64
9 | region_risque | 0.300578 | 0.1001 | 0.30215 | 0.4999 | 0 | Float64
10 | type_produit__automobile | 0.3307 | 0.0 | 0.0 | 1.0 | 0 | Float64
11 | type_produit__electromenager | 0.3329 | 0.0 | 0.0 | 1.0 | 0 | Float64
12 | type_produit__electronique | 0.3364 | 0.0 | 0.0 | 1.0 | 0 | Float64
13 | canal_achat__magasin | 0.3296 | 0.0 | 0.0 | 1.0 | 0 | Float64
14 | canal_achat__mobile | 0.3359 | 0.0 | 0.0 | 1.0 | 0 | Float64
15 | canal_achat__web | 0.3345 | 0.0 | 0.0 | 1.0 | 0 | Float64
16 | nb_cartes_credit | 2.1078 | 1.0 | 2.0 | 6.0 | 0 | Float64
17 | incident_paiement | 0.3168 | 0.0 | 0.0 | 1.0 | 0 | Float64
18 | epargne | 35066.0 | 4107.22 | 32519.9 | 100000.0 | 0 | Float64
19 | stabilite_emploi | 0.697161 | 0.0 | 0.7042 | 1.0 | 0 | Float64

### Partition TRAIN/TEST - Création des indices¶

In [188]:

    # effectif total
    n = DFR.nrow(df)
    print("Taille de la base = $n")

    Taille de la base = 10000

In [189]:

    # indices pour partition en train (60%) et test (40%)
    # stratify est possible parce y est catégorielle
    idTrain, idTest = MLJ.partition(1:n,0.6,shuffle=true,rng=42,stratify=y)

    # vérif. dim des identifiants
    println("Effectifs TRAIN = $(length(idTrain)) et TEST = $(length(idTest))")

    Effectifs TRAIN = 6000 et TEST = 4000

# Arbres de décision avec DECISIONTREE (via MLJ)¶

### Chargement de la classe de calcul¶

In [190]:

    # chargement de la classe de calcul à partir du package
    # https://juliaai.github.io/MLJ.jl/stable/models/DecisionTreeClassifier_DecisionTree/#DecisionTreeClassifier_DecisionTree
    DecisionTreeClassifier = @MLJ.load DecisionTreeClassifier pkg=DecisionTree

    import MLJDecisionTreeInterface ✔

    ┌ Info: For silent loading, specify `verbosity=0`.
    └ @ Main C:\Users\ricco\.julia\packages\MLJModels\9LbNu\src\loading.jl:159

    MLJDecisionTreeInterface.DecisionTreeClassifier

### Instanciation, préparation, entraînement¶

In [191]:

    # instanciation avec paramétrage
    # limiter la profondeur pour la lisibilité
    # attention, mode de calcul de l'importance des variables
    # rng pour calcul déterministe (ex. gestion des ex-aequos)
    tree = DecisionTreeClassifier(max_depth=3,
                                feature_importance=:impurity,
                                rng=42)

    # préparation de l'objet pour l'entraînement
    # avec la méthode machine() de MLJ
    # juste préparatoire => les structures de données sont passées en totalité
    mach = MLJ.machine(tree,XPrim,y)

    # lancer l'entraînement -> l'objet mach est màj directement avec "!"
    # cf. le rôle de "rows" pour indiquer les individus réeelement en TRAIN
    # les structures XPrim et y ont été passés préalablement avec machine()
    MLJ.fit!(mach,rows=idTrain)

    ┌ Info: Training machine(DecisionTreeClassifier(max_depth = 3, …), …).
    └ @ MLJBase C:\Users\ricco\.julia\packages\MLJBase\krfwA\src\machines.jl:499

    trained Machine; caches model-specific representations of data
      model: DecisionTreeClassifier(max_depth = 3, …)
      args:
        1:	Source @878 ⏎ ScientificTypesBase.Table{AbstractVector{ScientificTypesBase.Continuous}}
        2:	Source @363 ⏎ AbstractVector{ScientificTypesBase.Multiclass{3}}

### Inspection - Fitted params¶

In [192]:

    # récupération des résultats
    fp = MLJ.fitted_params(mach)

    # type de l'objet
    typeof(fp)

    @NamedTuple{tree::DecisionTree.InfoNode{Float64, UInt32}, raw_tree::DecisionTree.Root{Float64, UInt32}, encoding::Dict{UInt32, CategoricalArrays.CategoricalValue{String, UInt32}}, features::Vector{Symbol}}

In [193]:

    # liste des infos
    # keys() puisque named tuple
    println(keys(fp))

    (:tree, :raw_tree, :encoding, :features)

In [194]:

    # les noms des variables
    fp.features

    19-element Vector{Symbol}:
     :age
     :revenu_annuel
     :score_credit
     :anciennete_client
     :panier_montant
     :sensibilite_promo
     :frequence_achat
     :taux_endettement
     :region_risque
     :type_produit__automobile
     :type_produit__electromenager
     :type_produit__electronique
     :canal_achat__magasin
     :canal_achat__mobile
     :canal_achat__web
     :nb_cartes_credit
     :incident_paiement
     :epargne
     :stabilite_emploi

In [195]:

    # et les modalités de la variable cible
    CA.levels(y)

    3-element CategoricalArrays.CategoricalArray{String,1,UInt32}:
     "credit_classique"
     "l_o_a"
     "paiement_3x"

In [196]:

    # caractéristiques de l'arbre
    # avec println()
    println(fp.tree)

    DecisionTree.InfoNode{Float64, UInt32}(Decision Tree
    Leaves: 8
    Depth:  3, nchildren=2)

In [197]:

    # affichage de l'abre avec le même champ
    # on retire simplement le println()
    fp.tree

    # un affichage graphique avec GraphViz est possible
    # mais demande pas mal de contorsions
    # un peu comme lors des débuts de SKLEARN sous Python

    incident_paiement < 0.5
    ├─ score_credit < 720.0
    │  ├─ panier_montant < 1502.0
    │  │  ├─ paiement_3x (1250/1543)
    │  │  └─ l_o_a (598/1507)
    │  └─ taux_endettement < 34.99
    │     ├─ credit_classique (536/636)
    │     └─ paiement_3x (230/441)
    └─ sensibilite_promo < 0.6952
       ├─ epargne < 88670.0
       │  ├─ paiement_3x (1056/1305)
       │  └─ l_o_a (3/3)
       └─ revenu_annuel < 30300.0
          ├─ paiement_3x (50/56)
          └─ paiement_3x (369/509)

In [198]:

    # ou autre approche
    import DecisionTree as TD
    DT.print_tree(fp.raw_tree,feature_names=fp.features)

    Feature 17: "incident_paiement" < 0.5 ?
    ├─ Feature 3: "score_credit" < 720.0 ?
        ├─ Feature 5: "panier_montant" < 1502.0 ?
            ├─ 3 : 1250/1543
            └─ 2 : 598/1507
        └─ Feature 8: "taux_endettement" < 34.99 ?
            ├─ 1 : 536/636
            └─ 3 : 230/441
    └─ Feature 6: "sensibilite_promo" < 0.6952 ?
        ├─ Feature 18: "epargne" < 88670.0 ?
            ├─ 3 : 1056/1305
            └─ 2 : 3/3
        └─ Feature 2: "revenu_annuel" < 30300.0 ?
            ├─ 3 : 50/56
            └─ 3 : 369/509

### Importance des variables¶

In [199]:

    # importance des variables
    MLJ.feature_importances(mach)

    19-element Vector{Pair{Symbol, Float64}}:
                     :score_credit => 0.25640648078933176
                :incident_paiement => 0.2531296205468259
                 :taux_endettement => 0.2517768495042364
                   :panier_montant => 0.23019784848167227
                :sensibilite_promo => 0.0029514050112553997
                          :epargne => 0.0029451420461343953
                    :revenu_annuel => 0.0025926536205439
                              :age => 0.0
                :anciennete_client => 0.0
                  :frequence_achat => 0.0
                    :region_risque => 0.0
         :type_produit__automobile => 0.0
     :type_produit__electromenager => 0.0
       :type_produit__electronique => 0.0
             :canal_achat__magasin => 0.0
              :canal_achat__mobile => 0.0
                 :canal_achat__web => 0.0
                 :nb_cartes_credit => 0.0
                 :stabilite_emploi => 0.0

### Inspection - Report¶

In [200]:

    # autre manière d'accéder aux résultats avec report()
    rm = MLJ.report(mach)

    # type de l'object
    typeof(rm)

    @NamedTuple{classes_seen::CategoricalArrays.CategoricalVector{String, UInt32, String, CategoricalArrays.CategoricalValue{String, UInt32}, Union{}}, print_tree::MLJDecisionTreeInterface.TreePrinter{DecisionTree.Root{Float64, UInt32}}, features::Vector{Symbol}}

In [201]:

    # liste des infos
    keys(rm)

    (:classes_seen, :print_tree, :features)

In [202]:

    # autre solution pour affichage de l'arbre
    # sans limitation de profondeur (-1)
    rm.print_tree(-1)

    Feature 17: "incident_paiement" < 0.5 ?
    ├─ Feature 3: "score_credit" < 720.0 ?
        ├─ Feature 5: "panier_montant" < 1502.0 ?
            ├─ 3 : 1250/1543
            └─ 2 : 598/1507
        └─ Feature 8: "taux_endettement" < 34.99 ?
            ├─ 1 : 536/636
            └─ 3 : 230/441
    └─ Feature 6: "sensibilite_promo" < 0.6952 ?
        ├─ Feature 18: "epargne" < 88670.0 ?
            ├─ 3 : 1056/1305
            └─ 2 : 3/3
        └─ Feature 2: "revenu_annuel" < 30300.0 ?
            ├─ 3 : 50/56
            └─ 3 : 369/509

# Evaluation en test¶

### Prédiction en test¶

In [203]:

    # prédiction en test => directement classes prédites
    # XPrim a déjà été passé plus haut
    # reste à indiquer les indices des individus en test => idTest
    pred = MLJ.predict_mode(mach,rows=idTest)

    # premières valeurs
    pred[1:10]

    10-element CategoricalArrays.CategoricalArray{String,1,UInt32}:
     "credit_classique"
     "l_o_a"
     "paiement_3x"
     "paiement_3x"
     "l_o_a"
     "paiement_3x"
     "paiement_3x"
     "paiement_3x"
     "l_o_a"
     "credit_classique"

### Matrice de confusion¶

In [204]:

    # matrice de confusion
    mc = MLJ.confusion_matrix(pred,y[idTest])
    mc

                     ┌──────────────────────────────────────────────────┐
                     │                   Ground Truth                   │
    ┌────────────────┼────────────────┬────────────────┬────────────────┤
    │   Predicted    │   credit_c…    │     l_o_a      │   paiement…    │
    ├────────────────┼────────────────┼────────────────┼────────────────┤
    │   credit_c…    │      324       │       65       │       0        │
    ├────────────────┼────────────────┼────────────────┼────────────────┤
    │     l_o_a      │      247       │      430       │      340       │
    ├────────────────┼────────────────┼────────────────┼────────────────┤
    │   paiement…    │       16       │      550       │      2028      │
    └────────────────┴────────────────┴────────────────┴────────────────┘

### Indicateurs¶

In [205]:

    # indicateurs de performance
    acc = MLJ.accuracy(pred,y[idTest])
    err = MLJ.misclassification_rate(pred,y[idTest])

    # affichage
    println("Accuracy = $acc ; Error Rate = $err")

    Accuracy = 0.6955 ; Error Rate = 0.3045

# Encapsuler les tâches dans un Pipeline¶

In [206]:

    # de nouveau, on peut passer par un pipeline
    pipe = OneHotEncoder() |> DecisionTreeClassifier(max_depth=3,rng=42)

    # machine -> on passe X natif et non plus XPrim transformé
    mach_pipe = MLJ.machine(pipe,X,y)

    # entraînement
    MLJ.fit!(mach_pipe,rows=idTrain)

    # prédiction
    pred_pipe = MLJ.predict_mode(mach_pipe,rows=idTest)

    # et comparons les approches (pas-à-pas vs. pipeline)
    MLJ.confusion_matrix(pred_pipe,pred)

    ┌ Info: Training machine(ProbabilisticPipeline(one_hot_encoder = OneHotEncoder(features = Symbol[], …), …), …).
    └ @ MLJBase C:\Users\ricco\.julia\packages\MLJBase\krfwA\src\machines.jl:499
    ┌ Info: Training machine(:one_hot_encoder, …).
    └ @ MLJBase C:\Users\ricco\.julia\packages\MLJBase\krfwA\src\machines.jl:499
    ┌ Info: Spawning 3 sub-features to one-hot encode feature :type_produit.
    └ @ MLJTransforms C:\Users\ricco\.julia\packages\MLJTransforms\rATN1\src\transformers\other_transformers\one_hot_encoder.jl:67
    ┌ Info: Spawning 3 sub-features to one-hot encode feature :canal_achat.
    └ @ MLJTransforms C:\Users\ricco\.julia\packages\MLJTransforms\rATN1\src\transformers\other_transformers\one_hot_encoder.jl:67
    ┌ Info: Training machine(:decision_tree_classifier, …).
    └ @ MLJBase C:\Users\ricco\.julia\packages\MLJBase\krfwA\src\machines.jl:499

                     ┌──────────────────────────────────────────────────┐
                     │                   Ground Truth                   │
    ┌────────────────┼────────────────┬────────────────┬────────────────┤
    │   Predicted    │   credit_c…    │     l_o_a      │   paiement…    │
    ├────────────────┼────────────────┼────────────────┼────────────────┤
    │   credit_c…    │      389       │       0        │       0        │
    ├────────────────┼────────────────┼────────────────┼────────────────┤
    │     l_o_a      │       0        │      1017      │       0        │
    ├────────────────┼────────────────┼────────────────┼────────────────┤
    │   paiement…    │       0        │       0        │      2594      │
    └────────────────┴────────────────┴────────────────┴────────────────┘