Vous êtes sur la page 1sur 25

SDM

Olivares Pablo

2023-04-27

Objectif et instructions
L’objectif principal de ce TP est d’aborder les SDMs d’un point de vue pratique à travers R, et
en utilisant comme exemple la modélisation de la distribution de l’espèce Vulpes vulpes
(renard roux) à l’échelle mondiale en fonction de variables bioclimatiques.
# Installation des packages s'ils ne sont pas déjà installés.
if (!require("biomod2")) install.packages("biomod2")

## Le chargement a nécessité le package : biomod2

## Warning: le package 'biomod2' a été compilé avec la version R 4.2.2

## biomod2 4.1-2 loaded.


## /!\ Package fresh start... meaning some changes in function names and par
ameters. We apologize for the trouble >{o.o}<

if (!require("raster")) install.packages("raster")

## Le chargement a nécessité le package : raster

## Warning: le package 'raster' a été compilé avec la version R 4.2.2

## Le chargement a nécessité le package : sp

## Warning: le package 'sp' a été compilé avec la version R 4.2.2

if (!require("usdm")) install.packages("usdm")

## Le chargement a nécessité le package : usdm

## Warning: le package 'usdm' a été compilé avec la version R 4.2.2

if (!require("randomForest")) install.packages("randomForest")

## Le chargement a nécessité le package : randomForest

## Warning: le package 'randomForest' a été compilé avec la version R 4.2.2

## randomForest 4.7-1.1

## Type rfNews() to see new features/changes/bug fixes.

SampleMat2 <-function(ref, ratio, as.logi=FALSE)


{
# set a new random seed to ensure that sampling is random (issue when CTA
is involved and seed needs to be set to a fix number)
set.seed(as.double(Sys.time()) + as.numeric(format(Sys.time(), "%OS6"))*1
000000)

ntot <- length(ref)


npres<- sum(ref)
ncal <- ceiling(ntot*ratio)

pres <- sample(which(ref==1), ceiling(npres*ratio))


absc <- sample(which(ref==0), ncal-length(pres))

if(as.logi){
calib <- rep(FALSE, ntot)
calib[c(pres,absc)] <- TRUE
eval <- !calib
} else{
calib <- c(pres,absc)
eval <- (1:ntot)[-c(pres,absc)]
}

return(list("calibration"=calib, "evaluation"=eval))
}

# Activation des packages pour ce TP


library(biomod2) # Obtention des données, fonctions liées aux SDM
library(raster) # Traitement de données spatiales
library(usdm) # Traiter la multicolinéarité (fonction vifcor)
library(randomForest) # Fonction randomForest

Partie I: Préparation des données


L’objectif d’un SDM est de mettre en relation une variable réponse (présence-absence d’une
espèce codée en binaire 1/0) et des variables explicatives aussi appelés prédicteurs
(variables environnementales). On a donc une variable Y (espèce) reliée à un jeu de données
environnementales X. Cette relation est définie par un modèle M. Une fois le modèle calibré
(défini, construit, etc.), on peut l’utiliser pour prédire Y’ en fonction de X’ (nouveau jeu de
données environnementales). Dans cette partie nous allons voir comment préparer X et Y de
telle manière à pouvoir calibrer M. Nous allons utiliser des données qui sont incluses dans le
package ‘biomod2’, package spécialement dédié aux SDMs.

1. Importation des données d’observations de Vulpes vulpes (variable réponse)


## Importation d'un tableau csv, inclus dans le package biomod2
dataSpecies <- read.csv(system.file("external/species/mammals_table.csv",pack
age="biomod2"), row.names = 1)
head(dataSpecies)

## X_WGS84 Y_WGS84 ConnochaetesGnou GuloGulo PantheraOnca PteropusGiganteu


s
## 1 -94.5 82.00001 0 0 0
0
## 2 -91.5 82.00001 0 1 0
0
## 3 -88.5 82.00001 0 1 0
0
## 4 -85.5 82.00001 0 1 0
0
## 5 -82.5 82.00001 0 1 0
0
## 6 -79.5 82.00001 0 1 0
0
## TenrecEcaudatus VulpesVulpes
## 1 0 0
## 2 0 0
## 3 0 0
## 4 0 0
## 5 0 0
## 6 0 0

#Ce tableau importé contient les coordonnées géographiques selon le système géodésique
WGS84 (World Geodetic System 1984) de chaque observation, ainsi que plusieurs colonnes
qui correspondent à différentes espèces. Nous allons extraire la colonne VulpesVulpes (la
dernière) dont les valeurs sont binaires, 1 correspondant à une présence, 0 à une absence.
Cette colonne sera ensuite utilisée pour créer notre tableau final qui servira à calibrer nos
modèles. Note that the echo = FALSE parameter was added to the code chunk to prevent
printing of the R code that generated the plot.
# Extraction de la colonne VulpesVulpes
spp <- dataSpecies[,"VulpesVulpes"]

2. Données environnementales (variables explicatives)


Nous allons utiliser des données environnementales présentées sous forme de rasters qui
correspondent à des variables bioclimatiques dérivées de variables de température et
précipitation. Vous trouverez plus de détails concernant ces variables sur le site suivant:
https://worldclim.org/data/bioclim.html Notez que les valeurs de températures ont été
multipliées par 10 pour des questions de mémoire liées au stockage des données
(https://worldclim.org/data/v1.4/formats.html). Nous allons créer un ‘stack’ (une pile) de
rasters. Ils seront ‘superposés’ et nous pourrons donc facilement obtenir la valeur des
différentes variables à un point donné (à la manière d’une aiguille transperçant une pile de
papier).
# La fonction stack permet d'empiler plusieurs rasters aux dimensions et réso
lutions identiques. Ces rasters proviennent du package biomod2.
dataEnv <- stack(system.file("external/bioclim/current/bio3.grd",
package="biomod2"),
system.file("external/bioclim/current/bio4.grd",
package="biomod2"),
system.file("external/bioclim/current/bio7.grd",
package="biomod2"),
system.file("external/bioclim/current/bio11.grd",
package="biomod2"),
system.file("external/bioclim/current/bio12.grd",
package="biomod2"))
# Affichage des rasters
plot(dataEnv)

3. Obtenir les données environnementales pour chacune des observations


faunistiques
Comme mentionné plus haut, nous allons extraire avec la fonction ‘extract’ les valeurs des
rasters ‘empilés’ au niveau des points d’observations faunistiques.
# Les deux premières colonnes du tableau dataSpecies correspondent aux coordo
nnées. Tappez ?extract pour plus d'informations concernant cette fonction.
envValues <- extract(x=dataEnv,y=dataSpecies[,c(1,2)])
# Si x avait été un seul raster, nous aurions un vecteur en sortie (une série
de valeurs). Comme x est une pile de raster, nous avons un tableau en sortie
(plusieurs séries disposées en colonnes). La fonction 'head' permet d'fficher
les six premières lignes du tableau issu de la fonction extract.
head(envValues)

## bio3 bio4 bio7 bio11 bio12


## [1,] 12.77777 15086.67 471.5556 -381.7777 93.22216
## [2,] 12.23077 15473.69 478.6154 -385.3077 87.53849
## [3,] 11.64706 15987.76 487.2941 -391.3529 95.64696
## [4,] 11.25000 16186.33 489.5417 -396.6250 103.74995
## [5,] 11.11111 15788.04 478.8519 -396.1111 131.66658
## [6,] 11.43333 15299.07 466.1334 -389.9000 148.39989

# Plot permettant d'avoir un apperçu graphique des relations existantes entre


ces variables.
plot(as.data.frame(envValues))

## 4. Eliminer les variables colinéaires


Certaines techniques de modélisation (ex. régression) ne sont pas robustes si les variables
explicatives sont très corrélées entre elles. Quoi qu’il en soit, utiliser des variables
explicatives très corrélées (et donc redondantes) n’a pas vraiment de sens. C’est pourquoi il
est préférable d’éliminer les variables qui pourraient causer un problème lié à leur
colinéarité. Lorsque l’on a deux variables corrélées, le choix d’en garder une plutôt qu’une
autre dépend en premier lieu de sa pertinence d’un point de vue écologique. En effet, on
préfère souvent une variable dont l’impact sur l’espèce est plus direct. Par exemple, la
température et l’altitude sont souvent très corrélées, mais pour des questions
d’interprétations écologiques, il est plus judicieux de conserver la température plutôt que
l’altitude. Une autre manière de choisir (celle que nous allons employer ici), c’est de se baser
sur le VIF (Variation Inflation Factor) de chacune des variables. Le VIF donne une idée de la
colinéarité d’une variable vis-à-vis des autres. En résumé, plus une variable peut être
expliquée par les autres variables (à travers une régresssion linéaire multiple), plus son VIF
est important. Lorsque l’on a une paire de variables dont la corrélation est élevée, il est donc
recommandé de garder la variable qui a le VIF le plus bas (colinéarité plus faible vis-à-vis de
toutes les autres variables). La fonction que nous allons utiliser (‘vifcor’) permettra, pour
chaque paire de variables ayant un coefficient de corrélation supérieur à une seuil donné, de
déterminer la variable à éliminer (VIF plus élevé). Le seuil est arbitraire, il est souvent de
l’ordre de 0.7-0.8 lorsque l’on utilise des techniques de régression, mais dans notre cas, nous
allons le définir à 0.9 (paramètre ‘th’ dans notre fonction). Nous allons donc ici, définir les
variables explicatives (prédicteurs) qui seront utilisées pour nos modèles.
# Fonction vifcor pour évaluer la colinéarité des nos variables. Pour chaque
paire de variables dont le coefficient de corrélation est égal ou supérieur à
0.9, la variable ayant le VIF le plus élevé sera mise de côté.
vifCorResults <- vifcor(envValues,th=0.9)
# Variable à éliminer: Le nom de ces variables se trouve sur le 'slot' (@) no
mmé 'excluded' (@excluded) de l'objet issu de la fonction vifcor.
varToRemove <- vifCorResults@excluded
# Variable à conserver: L'expression 'colnames(envValues)' donne le nom des c
olonnes de notre tableau de variables environnementales (c'est-à-dire le nom
des variables explicatives). L'expression entre crochets '[!colnames(envValue
s) %in% varToRemove]' représente un vecteur logique (TRUE/FALSE) ('%in%' veut
dire 'fait partie' et le point d'interrogation placé au début inverse le résu
ltat). Cela donne TRUE quand le nom de la colonne ne fait pas partie de l'obj
et varToRemove, FALSE lorsqu'il en fait partie. L'objet 'preds' contiendra do
nc le nom des variables explicatives qui seront utilisées pour nos modèles.
preds <- colnames(envValues)[!colnames(envValues) %in% varToRemove]
print(preds)

## [1] "bio3" "bio7" "bio11" "bio12"

5. Tableau final
Nous allons créer un tableau final qui contiendra les observations faunistiques et les valeurs
environnementales correspondantes retenues. Ce tableau nous servira comme base pour la
calibration de nos modèles.
# Nous joignons le vecteur de presence-absence de Vulpes vulpes (en lui donna
nt un nom; VulpesVulpes=...) et le tableau des valeurs environnementales issu
de la fonction 'extract', tout en spécifiant les colonnes qui nous souhaitons
conserver.
dataSpEnv <- data.frame(VulpesVulpes=spp,envValues[,preds])
head(dataSpEnv)

## VulpesVulpes bio3 bio7 bio11 bio12


## 1 0 12.77777 471.5556 -381.7777 93.22216
## 2 0 12.23077 478.6154 -385.3077 87.53849
## 3 0 11.64706 487.2941 -391.3529 95.64696
## 4 0 11.25000 489.5417 -396.6250 103.74995
## 5 0 11.11111 478.8519 -396.1111 131.66658
## 6 0 11.43333 466.1334 -389.9000 148.39989

Partie II: Techniques de modélisation et calibration


Il existe une multitude de techniques de modélisation (GLM, GAM, MaxENT, Random Forest,
Gradient Boosted Trees, SVC, etc.), mais il serait impossible de toutes les aborder dans le
cadre de cours. Nous allons néanmoins en voir deux, l’une étant une technique de régression
(GLM) et l’autre une technique de ‘machine learning’ (Random Forest).

1. Régression: Generalized linear model (GLM)


Comme son nom l’indique, un GLM est une généralisation de la régression linéaire,
permettant de modéliser des données qui ne sont pas normalement distribuées (loi
normale). Dans notre cas, la variable réponse est binaire et suit une loi binomiale. Nous allons
utiliser la fonction ‘logit’ comme fonction lien (voir théorie sur GLM).
La fonction ‘glm’ permet de calibrer un GLM de la manière suivante:
# Calibration du GLM. Le nom de la variable réponse en fonction de toutes les
variables (~.) contenues dans le tableau (data=). Nous spécifions aussi la fa
mille de distribution (binomial) dont la fonction lien est la fonction 'logit
'.
modGLM <- glm(VulpesVulpes~.,data=dataSpEnv,family = binomial("logit"))
# Summary
print(summary(modGLM))

##
## Call:
## glm(formula = VulpesVulpes ~ ., family = binomial("logit"), data = dataSpE
nv)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.77454 -0.43563 -0.03528 0.49395 3.02632
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) -1.0382810 0.4957519 -2.094 0.0362 *
## bio3 -0.1787175 0.0112674 -15.861 < 2e-16 ***
## bio7 0.0216655 0.0010981 19.731 < 2e-16 ***
## bio11 0.0172736 0.0010228 16.889 < 2e-16 ***
## bio12 0.0009981 0.0001358 7.351 1.96e-13 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 3442.9 on 2487 degrees of freedom
## Residual deviance: 1701.9 on 2483 degrees of freedom
## AIC: 1711.9
##
## Number of Fisher Scoring iterations: 6

Le ‘summary’ de notre modèle nous indique que tous nos coefficients ainsi que l’intercept
(ordonnée à l’origine) sont significativement différents de zéro (Pr(>|z|) < 0.05). On peut dès
lors inférer que toutes les variables retenues ont un effet significatif sur la probabilité de
présence de Vulpe vulpes. L’AIC indiqué en-bas du ‘summary’ nous permet de comparer deux
modèles construits sur les mêmes observations (la valeur en soit de l’AIC n’indique rien). Plus
la valeur est faible, plus la qualité du modèle est élevée, comparée à celle de l’autre modèle.
Rappelons ici l’importance du compromis entre biais et variance. Le biais est l’erreur du
modèle provenant de l’incapacité de l’algorithme à traduire le concept reliant la variable
réponse aux prédicteurs (sous-apprentissage ou underfit en anglais). La variance est l’erreur
due à la sensibilité aux petites fluctuations de l’échantillon utilisé pour la calibration
(surapprentissage ou overfit en anglais). Dans ce cas, l’algorithme tend à modéliser le bruit
et les modèles qui varient significativement selon l’échantillon utilisé pour la calibration ne
peuvent être généralisés. Un des objectifs principaux en modélisation est de diminuer l’une
des erreurs (biais ou variance) sans augmenter l’autre. L’AIC permet de choisir entre
plusieurs GLMs, celui qui en même temps explique le mieux les valeurs observées tout en
restant ‘parcimonieux’ et pouvant être généralisé. L’AIC ne peut être calculé sur des modèles
non-paramétriques (tels que les Random Forest) et c’est pourquoi nous allons voir plus loin
une méthode plus générale permettant de comparer la performance de modèles issus de
technique différentes.

2. Machine Learning: Random Forest (RF)


Le Random Forest est une technique basée sur la combinaison d’arbres décisionnels. Un
arbre décisionnel est un outil à la décision représentant un ensemble de choix sous la forme
d’un arbre. La figure ci-dessous illustre comment l’interaction entre la température et les
précipitations peuvent agir sur la présence (points verts) ou l’absence (points oranges) d’une
espèce.
Dans le cas du Random Forest, plusieurs arbres (des dizaines, centaines ou miliers) sont
construits/calibrés sur des sous-ensembles aléatoires du tableau de départ. C’est-à-dire que
pour chaque arbre, une partie des lignes et une partie des colonnes seulement sont prises en
compte. Un arbre décisionnel est donc calibré sur chacun des ces sous-ensembles, et le
modèle final (la forêt) tient compte du résultat de tous les arbres. Sur la base d’une même
série de valeurs environnementales, tous les arbres ne prédisent pas forcément le même
résultat. Il y a donc un choix final basé sur le nombre de ‘votes’. Imaginons un Random Forest
(‘alimenté’ par une série de valeurs environnementales pour un point donné) dont 30% des
arbres prédisent une présence et le reste une absence. On pourra dès lors considérer que
l’espèce a une probabilité de 30% d’être présente. La technique de Random Forest permet de
réduire l’erreur liée à la variance (le surapprentissage) par rapport à l’utlisation d’un seul
arbre construit sur la base de toutes les observations (ex. technique appelée Recursive
partitionning, dont la fonction dans R s’appelle rpart) (voir note plus haut sur le compromis
entre le biais et la variance).
# Calibration du Random Forest. Nous aimerions utiliser le mode 'classificati
on', pour cela nous devons spécifier que la colonne VulpesVulpes est en facto
r (catégorie 1 et catégorie 0). L'autre mode possible est le mode 'regression
', utilisé pour modéliser des valeurs continues.
modRF <- randomForest(as.factor(VulpesVulpes)~.,data=dataSpEnv)
# Summary
print(modRF)
##
## Call:
## randomForest(formula = as.factor(VulpesVulpes) ~ ., data = dataSpEnv)
## Type of random forest: classification
## Number of trees: 500
## No. of variables tried at each split: 2
##
## OOB estimate of error rate: 6.99%
## Confusion matrix:
## 0 1 class.error
## 0 1218 88 0.06738132
## 1 86 1096 0.07275804

La matrice de confusion affichée lorsque l’on exécute l’objet modRF nous indique le nombre
de présences (1) et absences (0) correctement prédites (sur nos points d’observations
utilisés pour calibrer notre modèle). L’idée est de comparer ce que l’on a observé et ce que
l’on a prédit à l’aide du modèle. Ce type de matrice sera utile par la suite pour évaluer et
comparer les performances de nos différents modèles.

Partie III: Evaluation de l’importance relative de chaque variable explicative


Une méthode relativement simple qui permet d’évaluer l’importance d’une variable
explicative (prédicteur) pour un modèle donné est d’observer la variation dans les
prédictions lorsque l’on mélange de manière aléatoire les valeurs de la variable concernée. Si
les prédictions ne varient pas ou peu, on considère que la variable en question n’est pas
importante, en revanche si les prédictions varient beaucoup, alors on considère que la
variable est importante. Pour quantifier cette importance, on calcule un coefficient de
corrélation (cor) entre les prédictions initiales et les prédictions ‘avec mélange’, et on
applique la formule suivante: 1-cor (à noter que n’importe quelle valeur de ‘cor’ négative sera
considérée comme étant nulle; en effet, on considère que si la corrélation est négative,
l’importance relative est maximale). La valeur de l’importance relative d’une variable est
donc comprise en 0 et 1. Comme exemple, nous allons quantifier l’importance relative de la
variable bio7 pour notre modèle GLM:
# PredI (I pour initial) correspond aux prédictions de notre modèle (sur nos
points d'observations). Il est important de spécifier type="response" afin d'
obtenir les valeurs après transformation grâce à la fonction lien (voir théor
ie GLM). Les valeurs prédites seront comprises entre 0 et 1.
predI <- predict(modGLM,type="response")
# Mélange de bio7: Afin de ne pas modifier notre tableau de base, nous allons
en faire une copie appelée dataSpEnvM (M pour modifié).
dataSpEnvM <- dataSpEnv
# La fonction sample nous permet d'extraire un échantillon aléatoire. Dans no
tre cas, nous spécifions que la taille de l'échantillon doit correspondre au
nombre de ligne de notre tableau et que chaque élément ne peut être séléction
né plus d'une fois (replace=FALSE). Ceci revient à 'mélanger' les valeurs de
la colonne concernée.
dataSpEnvM$bio7 <- sample(dataSpEnvM$bio7,size=nrow(dataSpEnvM),replace=FALSE
)
# Prédiction avec variable mélangée.
predM <- predict(modGLM,newdata=dataSpEnvM,type="response")
# Calcul de l'importance relative (la fonction max, permet de considérer n'im
porte quel coefficient négatif comme étant nulle).
varImp <- 1-max(cor(predM,predI),0)
print(varImp)

## [1] 0.9304068

Le mélange, étant aléatoire, peut varier d’une fois à l’autre, c’est pourquoi il est important
d’effectuer cette opération plusieurs fois et de calculer ensuite une moyenne des valeurs
obtenues. Pour cela nous allons créer une boucle itérative. Pour une introduction sur le
fonctionnement des boucles dans R (‘loop’ en anglais), visitez la page suivante:
https://datascienceplus.com/how-to-write-the-loop-in-r/
# PredI (I pour initial) correspond aux prédictions de notre modèle (sur nos
points d'observations). Il est important de spécifier type="response" afin d'
obtenir les valeurs après transformation grâce à la fonction lien (voir théor
ie GLM). Les valeurs prédites seront comprises entre 0 et 1.
predI <- predict(modGLM,type="response")
# Nombre d'itérations.
nIter <- 10
# Vecteur vide dans lesquels nous allons sauvegarder les valeurs obtenues à c
haque itération, dont la longeur correspond au nombre d'itérations.
varImpVect <- vector(mode="numeric",length=nIter)
# Boucle (la valeur de i changera à chaque itération et ira de 1 au nombre dé
fini dans nIter)
for(i in 1:nIter){
# Mélange de bio7: Afin de ne pas modifier notre tableau de base, nous allo
ns en faire une copie appelée dataSpEnvM (M pour modifié).
dataSpEnvM <- dataSpEnv
# La fonction sample nous permet d'extraire un échantillon aléatoire. Dans
notre cas, nous spécifions que la taille de l'échantillon doit correspondre
au nombre de ligne de notre tableau et que chaque élément ne peut être séléct
ionner plus d'une fois. Ceci revient à 'mélanger' les valeurs de la colonne c
oncernée.
dataSpEnvM$bio7 <- sample(dataSpEnvM$bio7,size=nrow(dataSpEnvM),replace=FAL
SE)
# Prédiction avec variable mélangée
predM <- predict(modGLM,newdata=dataSpEnvM,type="response")
# Calcul de l'importance relative (la fonction max, permet de considérer n'
importe quel coefficient négatif comme étant nulle).
varImp <- 1-max(cor(predM,predI),0)
# Sauvegarde de la valeur dans l'objet varImpVect à la position i
varImpVect[i] <- varImp
}
# Calcul de la moyenne de toutes les valeurs obtenues
varImpMoy <- mean(varImpVect)
print(varImpMoy)

## [1] 0.9326423
Maintenant, nous allons appliquer le même principe pour tous les prédicteurs. Nous allons
donc créer un tableau dont les lignes correspondront aux différentes itérations et les
colonnes aux différents prédicteurs. Ce tableau sera rempli comme précédemment, de
manière itérative, mais cette fois, nous allons avoir une double boucle (imbrication), une sur
les prédicteurs, puis une autre sur les itérations.
# PredI (I pour initial) correspond aux prédictions de notre modèle (sur nos
points d'observations). Il est important de spécifier type="response" afin d'
obtenir les valeurs après transformation grâce à la fonction lien (voir théor
ie GLM). Les valeurs prédites seront comprises entre 0 et 1.
predI <- predict(modGLM,type="response")
# Nombre d'itérations.
nIter <- 10
# Tableau vide dans lequel nous allons sauvegarder les valeurs obtenues à cha
que itération, dont les lignes correspondent aux itérations et les colonnes a
ux variables. Nous créons d'abord une matrice remplie de NA, pour laquelle il
est facile de spécifier le nombre de lignes (nrow=) et le nombre de colonnes
(ncol=). Nous transformons ensuite cette matrice en data.frame.
varImpVectTable <- data.frame(matrix(NA,nrow=nIter,ncol=length(preds)))
colnames(varImpVectTable) <- preds
# Boucle (la valeur de p changera à chaque itération et correspondra aux noms
de variables contenues dans l'objet preds)
for(p in preds){
for(i in 1:nIter){
# Mélange de la variable p. Afin de ne pas modifier notre tableau de base,
nous allons en faire une copie appelée dataSpEnvM (M pour modifié).
dataSpEnvM <- dataSpEnv
# La fonction sample nous permet d'extraire un échantillon aléatoire. Dans
notre cas, nous spécifions que la taille de l'échantillon doit correspondre
au nombre de ligne de notre tableau et que chaque élément ne peut être séléct
ionner plus d'une fois. Ceci revient à 'mélanger' les valeurs de la colonne c
oncernée. L'opération sera effectuée sur la colonne p.
dataSpEnvM[,p] <- sample(dataSpEnvM[,p],size=nrow(dataSpEnvM),replace = FAL
SE)
# Prédiction avec variable mélangée
predM <- predict(modGLM,newdata=dataSpEnvM,type="response")
# Calcul de l'importance relative (la fonction max, permet de considérer n'
importe quel coefficient négatif comme étant nulle)
varImp <- 1-max(cor(predM,predI),0)
# Sauvegarde de la valeur dans le tableau, à la ligne i (numéro de l'itérat
ion) et à la colonne p (correspondante à une des variables)
varImpVectTable[i,p] <- varImp
}
}
# Calcul des moyennes avec la fonction apply (fonction qui s'opère sur un dat
a frame). La valeur 2 signifie que l'on souhaite exécuter une opération par c
olonne, et 'mean' correspond à l'opération que l'on souhaite réaliser.
varImpMoy <- apply(varImpVectTable,2,mean)
# Barplot, ylim permet de fixer l'axe des y, ce que permet de pouvoir compare
r les graphiques entre eux (GLM vs Random Forest).
barplot(varImpMoy, ylab="Relative variable importance", main="Vulpes vulpes (
GLM)",ylim=c(0,1))

Nous voyons que les variables bio3 et bio7 sont largement plus importantes que les variables
bio11 et bio12, cette dernière étant presque négligeable. En d’autres termes, les variables
bio3 et bio7 ont permis de bien mieux discriminer les présences des absences que les
variables bio11 et bio12. Nous allons effectuer exactement la même opération pour le modèle
Random Forest.
# PredI (I pour initial) correspond aux prédictions de notre modèle (sur nos
points d'observations). Nous sélectionnons la deuxième colonne qui correspond
aux probabilités de présence.
predI <- predict(modRF,type="prob")[,2]
# Nombre d'itérations
nIter <- 10
# Tableau vide dans lequel nous allons sauvegarder les valeurs obtenues à cha
que itération, dont les lignes correspondent aux itérations et les colonnes a
ux variables. Nous créons d'abord une matrice remplie de NA, pour laquelle il
est facile de spécifier le nombre de lignes (nrow=) et le nombre de colonnes
(ncol=). Nous transformons ensuite cette matrice en data.frame.
varImpVectTable <- data.frame(matrix(NA,nrow=nIter,ncol=length(preds)))
colnames(varImpVectTable) <- preds
# Boucle (la valeur de p changera à chaque itération et correspondra aux chaî
nes de charactères contenues dans l'objet preds)
for(p in preds){
for(i in 1:nIter){
# Mélange de la variable p. Afin de ne pas modifier notre tableau de base,
nous allons en faire une copie appelée dataSpEnvM (M pour modifié).
dataSpEnvM <- dataSpEnv
# La fonction sample nous permet d'extraire un échantillon aléatoire. Dans
notre cas, nous spécifions que la taille de l'échantillon doit correspondre
au nombre de ligne de notre tableau et que chaque élément ne peut être séléct
ionner plus d'une fois. Ceci revient à 'mélanger' les valeurs de la colonne c
oncernée. L'opération sera effectuée sur la colonne p.
dataSpEnvM[,p] <- sample(dataSpEnvM[,p],size=nrow(dataSpEnvM),replace = FAL
SE)
# Prédiction avec variable mélangée
predM <- predict(modRF,newdata=dataSpEnvM,type="prob")[,2]
# Calcul de l'importance relative (la fonction max, permet de considérer n'
importe quel coefficient négatif comme étant nulle)
varImp <- 1-max(cor(predM,predI),0)
# Sauvegarde de la valeur dans le tableau, à la ligne i (numéro de l'itérat
ion) et à la colonne p (correspondante à une des variables)
varImpVectTable[i,p] <- varImp
}
}
# Calcul des moyennes avec la fonction apply (fonction qui s'opère sur un dat
a frame). La valeur 2 signifie que l'on souhaite exécuter une opération par c
olonne, et 'mean' correspond à l'opération que l'on souhaite réaliser.
varImpMoy <- apply(varImpVectTable,2,mean)
# Barplot, ylim permet de fixer l'axe des y, ce que permet de pouvoir compare
r les graphiques entre eux
barplot(varImpMoy, ylab="Relative variable importance", main="Vulpes vulpes (
RF)",ylim=c(0,1))
Nous pouvons évaluer les différences selon la technique de modélisation utilisée. Avec le
Random Forest, l’importance des variables est plus homogène qu’avec le GLM. Ceci peut
s’expliquer par le fait que dans le Random Forest, des interactions complexes entre les
variables peuvent être prises en compte, ce qui peut potentiellement équilibrer l’importance
relative de chacune des variables.

Partie IV: Evaluation des ‘courbes réponses’ associées à chaque variable


explicative
L’idée ici sera de comprendre comment l’espèce répond (comment la probabilité de présence
varie) le long des gradients des différents prédicteurs. Il existe là aussi une méthode
relativement simple, quel que soit la technique de modélisation employée. Comme pour le
calcul de l’importance des variables, l’idée est de modifier le tableau initial, prédire puis
analyser les prédictions. Imaginons que nous souhaitions savoir comment Vulpes vulpes se
comporte en fonction de la variable bio3. Nous allons d’un côté modifier les valeurs de bio3,
en créant un gradient allant de la valeur minimum à la valeur maximum. Et d’un autre côté,
nous allons ‘fixer’ toutes les valeurs des autres colonnes, de telle manière à ce que les autres
variables n’affectent pas les prédictions. C’est-à-dire, la colonne de la variable bio7, par
exemple, aura la même valeur à toutes les lignes. Cette valeur pourra correspondre à la
moyenne, la médiane, la valeur minimum, etc. Nous pourrons dès lors inférer que la variation
dans les nouvelles prédictions sera seulement causée par la variation dans la variable
d’intérêt (dans notre exemple, la variable bio3). A noter que cette technique ne tient pas
compte des possibles interactions entre les variables (ex. interactions modélisées par les
arbres décisionnels). Comme exemple, nous allons donc évaluer la courbe réponse de la
variable bio3 pour notre modèle GLM:
# Afin de ne pas modifier notre tableau de base, nous allons en faire une cop
ie appelée dataSpEnvM (M pour modifié).
dataSpEnvM <- dataSpEnv
# Boucle permettant de fixer les valeurs de chaque colonne (d'attribuer la mê
me valeur à chaque ligne). A chaque itération, nous prenons un colonne p corr
espondant à un des prédicteur (preds) et nous attribuons la valeur médiane à
toutes les lignes
for(p in preds){
dataSpEnvM[,p] <- median(dataSpEnvM[,p])
}
# La fonction imbriquée suivante (en commentaire) est une méthode alternative
à la boucle précédente (elle peut sembler plus compliquée mais elle est plus
rapide et donne exactement le même résultat). La partie apply calcule la médi
ane par colonne, et la fonction sapply applique la fonction 'rep' au résultat
de la fonction apply, à savoir, elle va répéter chacune de ces valeurs un nom
bre de fois qui correspond au nombre de lignes de notre tableau.
# dataSpEnvM[,preds] <- sapply(apply(dataSpEnvM[,preds],2,median),rep,times=n
row(dataSpEnvM))

# Nous allons maintenant remplacer les valeurs de la colonne bio3 par des val
eurs correspondant à un gradient allant de la valeur minimum à la valeur maxi
mum, dont la longueur correspond aux nombre de lignes de notre tableau. Nous
calculons ce gradient sur la base des valeurs initiales (dataSpEnv).
gradient <- seq(min(dataSpEnv$bio3),max(dataSpEnv$bio3),length.out = nrow(dat
aSpEnv))
dataSpEnvM$bio3 <- gradient
# Prédiction sur le tableau modifié.
predM <- predict(modGLM,newdata=dataSpEnvM,type="response")
# Plot de la courbe réponse. En 'x' le gradient, en 'y' les prédictions.
plot(x=dataSpEnvM$bio3,y=predM,type="l",ylab="Presence probability",xlab="bio
3",main="Response curve (GLM)",col="blue",ylim=c(0,1))

Nous voyons ici l’effet de la variable bio3 le long de son gradient sur la probabilité de
présence de notre espèce. Nous allons appliquer le même principe pour toutes les variables
et pour les deux techniques de modélisation. Nous allons programmer une boucle itérative
nous permettant d’afficher toutes les courbes réponses pour chacun des techniques.
# Afin de ne pas modifier notre tableau de base, nous allons en faire une cop
ie appelée dataSpEnvM (M pour modifié).
dataSpEnvM <- dataSpEnv
# Boucle permettant de fixer les valeurs de chaque colonne (d'attribuer la mê
me valeur à chaque ligne). A chaque itération, nous prenons un colonne et nou
s attribuons la valeur médiane à toutes les lignes.
for(p in preds){
dataSpEnvM[,p] <- median(dataSpEnvM[,p])
}
# La fonction imbriquée suivante (en commentaire) est une méthode alternative
à la boucle précédente (elle est plus rapide et donne exactement le même résu
ltat). La partie apply calcule la médiane par colonne, et la fonction sapply
applique la fonction 'rep' au résultat de la fonction apply, à savoir, elle v
a répéter chacune de ces valeurs un nombre de fois qui correspond au nombre d
e lignes de notre tableau.
# dataSpEnvM[,preds] <- sapply(apply(dataSpEnvM[,preds],2,median),rep,times=n
row(dataSpEnvM))

# Comme nous avons 4 variables, nous allons changer les paramètre graphiques
de telle manière à pouvoir afficher sur la même fenêtre les 4 courbes réponse
s (2 lignes et 2 colonnes)
par(mfrow=c(2,2))
# Modèle GLM: boucle itérative sur les prédicteurs.
for(p in preds){
# Afin de ne pas modifier notre tableau de médiane, nous allons en faire un
e copie appelée dataSpEnvMG (G pour gradient)
dataSpEnvMG <- dataSpEnvM
# Nous allons maintenant remplacer les valeurs de la colonne i par des vale
urs correspondant à un gradient allant de la valeur minimum à la valeur maxim
um, dont la longueur correspond aux nombre de lignes de notre tableau. Nous c
alculons ce gradient sur la base des valeurs initiales (dataSpEnv).
gradient <- seq(min(dataSpEnv[,p]),max(dataSpEnv[,p]),length.out = nrow(dat
aSpEnv))
dataSpEnvMG[,p] <- gradient
# Prédiction sur le tableau modifié
predM <- predict(modGLM,newdata=dataSpEnvMG,type="response")
# Plot de la courbe réponse. En 'x' le gradient, en 'y' les prédictions.
plot(x=dataSpEnvMG[,p],y=predM,type="l",ylab="Presence probability",xlab=p,
main="Response curve (GLM)",col="blue",ylim=c(0,1))
}
par(mfrow=c(2,2))
# Modèle RF: boucle itérative sur les prédicteurs.
for(p in preds){
# Afin de ne pas modifier notre tableau de médiane, nous allons en faire un
e copie appelée dataSpEnvMG (G pour gradient)
dataSpEnvMG <- dataSpEnvM
# Nous allons maintenant remplacer les valeurs de la colonne i par des vale
urs correspondant à un gradient allant de la valeur minimum à la valeur maxim
um, dont la longueur correspond aux nombre de lignes de notre tableau. Nous c
alculons ce gradient sur la base des valeurs initiales (dataSpEnv).
gradient <- seq(min(dataSpEnv[,p]),max(dataSpEnv[,p]),length.out = nrow(dat
aSpEnv))
dataSpEnvMG[,p] <- gradient
# Prédiction sur le tableau modifié. Nous sélectionnons la deuxième colonne
qui correspond aux probabilité de présence.
predM <- predict(modRF,newdata=dataSpEnvMG,type="prob")[,2]
# Plot de la courbe réponse. En 'x' le gradient, en 'y' les prédictions.
plot(x=dataSpEnvMG[,p],y=predM,type="l",ylab="Presence probability",xlab=p,
main="Response curve (RF)",col="blue",ylim=c(0,1))
}
Nous observons que les courbes réponses du Random Forest ne sont pas aussi lisses que celle
du GLM. Ceci est dû au fait que les arbres décisionnels se forment sur la base de partition à
partir de seuils (ex. température > 5°C). Nous observons donc des ruptures, parfois abruptes.

Partie V: Evaluation de la performance prédictive des modèles


Après avoir abordé l’évaluation de l’importance des variables et des courbes réponses
comme moyen d’interprétation des modèles d’un point de vue écologique, nous allons à
présent voir comment mesurer la performance de ces modèles. Cela nous permettra de savoir
si nos modèles sont fiables et/ou quelle technique entre le GLM et le Random Forest
fonctionne le mieux dans une logique prédictive. Comme nous avons vu plus haut (matrice
de confusion), l’idée est de comparer les prédictions et les observations et de se poser la
question suivante: “Est-ce que notre modèle prédit ce que l’on observe ?”. Pour faire simple,
Si la réponse est oui, le modèle est bon, si la réponse est non, le modèle est mauvais.
Évidemment, nous parlons là de prédictions sur des points d’observations connus. Si le
modèle est bon, alors on peut l’extrapoler et l’utiliser pour prédire à une plus grande échelle.
Cependant, il existe un risque de surapprentissage, surtout avec des techniques permettant
la calibration de modèles complexes telles que le Random Forest. Rappelons que le
surapprentissage permet de très bien prédire sur les points d’observations utilisés pour la
calibration (le bruit est pris en compte), mais les modèles ne sont pas extrapolables et les
prédictions sur d’autres points ne sont donc pas fiables. La seule manière de détecter un
potentiel surapprentissage est de tester nos prédictions sur des points qui n’ont pas été pris
en compte lors de la calibration. L’idée est donc d’avoir une série de points d’observations
pour la calibration, et une autre série pour l’évaluation. Avoir un jeu de données
complètement indépendant qui ne serait pas utilisé pour calibrer nos modèles serait l’idéal,
mais la plupart du temps, nous ne disposons pas d’un tel jeu de données. C’est pourquoi, une
méthode assez répandue est de séparer notre tableau initial en deux parties. La première
partie étant utilisée pour calibrer nos modèles, et la deuxième pour les tester/évaluer. Ceci
correspond à une technique (parmi d’autres) de validation croisée. Nous allons voir comment
procéder en prenant comme exemple le GLM.
# Nous allons utiliser la fonction sampleMat2 du package 'biomod2' qui permet
de séparer de manière aléatoire un vecteur de présence-absence (binaire) de t
elle manière à maintenir la même prévalence (pourcentage de présence) dans le
s deux groupes. Un paramètre 'ratio' permet de définir la proportion d'observ
ation que l'on souhaite garder pour la calibration. En règle générale, cette
proportion va de 0.6 à 0.8.
calibEval <- SampleMat2(dataSpEnv$VulpesVulpes,ratio = 0.7)
# L'objet issu de la fonction sampleMat2 est une liste de deux vecteurs. Le p
remier (appelé calibration) indique les numéros des lignes prévus pour la cal
ibration et le deuxième (appelé evaluation), le numéro des lignes prévus pour
le test.
# On crée un tableau (déstiné à la partie calibration) avec les lignes du tab
leau initial indiquées par le vecteur calibEval$calibration
calib <- dataSpEnv[calibEval$calibration,]
# On crée un tableau (déstiné à la partie test) avec les lignes du tableau in
itial indiquées par le vecteur calibEval$evalution
eval <- dataSpEnv[calibEval$evaluation,]
# Calibration du GLM. Le nom de la variable réponse en fonction de toutes les
variables (~.) contenues dans le tableau (data=). Nous spécifions aussi la fa
mille de distribution (binomial) dont la fonction lien est la fonction 'logit
'. Cette fois-ci, nous spécifions data=calib.
modGLM <- glm(VulpesVulpes~.,data=calib,family = binomial("logit"))
# Prédiction sur la partie test. Les valeurs environnementales du tableau 'ev
al' sont utilisées par le modèle pour prédire. Il est important de spécifier
type="response" afin d'obtenir les valeurs après transformation grâce à la fo
nction lien (voir théorie GLM). Les valeurs prédites seront comprises entre 0
et 1.
predTest <- predict(modGLM,newdata=eval,type="response")
print(summary(predTest))

## Min. 1st Qu. Median Mean 3rd Qu. Max.


## 0.0000232 0.0525036 0.5171246 0.4839794 0.8778916 0.9923205

Les valeurs préditent sont comprisent en 0 et 1 (modèle binomial) et correspondent à des


probabilités de présence. Comment comparer des probabilités à des observations binaires (0
ou 1) ? Car nous aimerions comparer nos prédictions aux observations et dans le jeu de
données ‘eval’ issu du tableau initial, ce sont bien des données binaires que nous avons. Une
solution consiste à transformer ces probabilités en binaire, selon un seuil. Par exemple, d’une
manière arbitraire, nous pouvons décider que tout ce qui est au-dessus de 0.5 devient 1 et ce
qui est dessous devient 0.
# Avec la fonction ifelse, nous créons un vecteur binaire sur la base des pro
babilités prédites (sur la partie test). La fonction requiert trois éléments:
une condition, le résultat si la condition est remplie, le résultat si la con
dition n'est pas remplie.
bin <- ifelse(predTest>=0.5,1,0)

Nous avons là donc deux vecteurs binaires, celui des observations et celui des prédictions, et
nous serions donc capables de remplir la matrice de confusion. Plusieurs indices peuvent être
calculés sur la base de cette matrice, par exemple la sensibilité (pourcentage de présences
correctement prédites), la spécificité (pourcentage d’absences correctement prédites), ou
encore des indices composés tel que l’indice True Skill Statistics (TSS) qui n’est autre que la
somme de la sensibilité et de la spécificité moins 1 (SE+SP-1).
# La fonction Find.Optim.Stat nous permet de calculer plusieurs indices de pe
rformance prédictive d'un modèle. Pour cela, il faut une vecteur de prédictio
n (en probabilités) et un vecteur d'observation (binaire). En l'occurence, no
us avons décidé de fixer le seuil à 0.5, et la fonction s'occupera de transfo
rmer nos probabilités en valeurs binaires (comme nous l'avont fait précédemme
nt).
tss <- bm_FindOptimStat("TSS",eval$VulpesVulpes,predTest,nb.thresh = 0.5)
print(tss)

## best.stat cutoff sensitivity specificity


## TSS 0 0.5 85.87571 81.12245

Le résultat de cette fonction nous informe sur la valeur de l’indice TSS (best.stat), le seuil
utilisé (cutoff), la sensibilité et la spécificité. Pour cet indice, une valeur entre 0.5 et 0.7
indique que le modèle est ‘bon’, entre 0.7 et 0.85 ‘très bon’, et au-delà de 0.85 il est considéré
‘excellent’. Dans cet exemple, nous avons défini un seuil de manière arbitraire, mais d’autres
seuils pourraient potentiellement améliorer notre indice. La même fonction permet de tester
différents seuils.
# La fonction Find.Optim.Stat nous permet de calculer plusieurs indices de pe
rformance prédictive d'un modèle. Pour cela, il faut une vecteur de prédictio
n (en probabilités) et un vecteur d'observation (binaire). Contrairement à l'
étape précédente, nous allons demander à la fonction de tester différents seu
ils, allant de 0 à 1 avec un pas de 0.01 .
tss <- bm_FindOptimStat("TSS",eval$VulpesVulpes,predTest,threshold = seq(0,1,
by = 0.01))
print(tss)

## best.stat cutoff sensitivity specificity


## TSS 0.675271 0.44 88.70056 78.82653

Nous avons là l’indication du seuil qui maximisme cet indice (cutoff) et la valeur de l’indice
en tenant compte de ce seuil (best.stat). Un autre indice fréquemment utilisé est l’AUC (Area
Under the Curve) basée sur le ROC (Relative Operating Characteristic). Au-delà de ces termes
techniques, le principe est relativement simple. On place deux axes, le taux de faux positifs
(égal au pourcentage d’absences mal prédites) sur l’axe des X et le taux de vrais positifs
(pourcentage de présences bien prédites) sur l’axe des Y. Chaque seuil donné correspondra
à un point différent sur le graphique. Par exemple, le seuil de 0 (une probabilité supérieure à
0 devient 1; 100% de présence) rendra le taux de faux positifs ainsi que le taux de vrais
positifs maximums. Le point serait donc placé dans le coin en haut à droite du graphique. En
effet, toutes les absences seront codées comme étant des présences (taux de faux positifs =
1), mais toutes les présences seront codées comme étant présentes (taux de vrais positifs =
1). A l’inverse, un seuil de 1 éliminerait les faux positifs mais il n’y aurait pas non plus de vrais
positifs. La courbe sera donc celle qui reliera tous les points obtenus selon tous les seuils
possibles. Et plus la courbe se rapprochera de la prédiction parfaite (taux de faux positifs de
0 et taux de vrais positifs de 1), plus l’aire sous la courbe (AUC) sera proche de 1, plus notre
modèle sera considéré comme étant bon. La même fonction Find.Optim.Stat permet d’obtenir
la valeur de l’AUC. Le ‘cutoff’ indiqué dans ce cas sera celui qui maximise la sensibilité et la
spécifité, mais il n’a pas d’influence sur l’AUC, qui est calculé en tenant compte de tous les
seuils.
# La fonction Find.Optim.Stat nous permet de calculer l'AUC (appelé ROC dans
le cas de cette fonction).
auc <- bm_FindOptimStat("ROC",eval$VulpesVulpes,predTest)
## Setting levels: control = 0, case = 1
print(auc)

## best.stat cutoff sensitivity specificity


## ROC 0.9163496 0.452651 88.41808 79.33673

La séparation en deux parties de notre tableau initial se fait de manière aléatoire. Les valeurs
de TSS, d’AUC ou d’autres indices peuvent donc varier. Il est dès lors important de répéter la
même opération plusieurs fois afin d’observer une tendance fiable. Nous allons donc
effectuer un ‘split’ (une partition) une dizaine de fois. A chaque itération nous allons calibrer
un GLM et un Random Forest puis nous allons calculer les valeurs de TSS. Les résultats seront
sauvegardés dans un tableau.
# Nombre d'itérations
nIter <- 10
# Création d'un tableau dont les lignes correspondent au nombre d'itération e
t les colonnes aux deux techniques, GLM et RF. Nous créons d'abord une matric
e remplie de NA, pour laquelle il est facile de spécifier le nombre de lignes
(nrow=) et le nombre de colonnes (ncol=). Nous transformons ensuite cette mat
rice en data.frame.
tssTable <- data.frame(matrix(NA,nrow=nIter,ncol=2))
# On nomme les colonnes.
colnames(tssTable) <- c("GLM","RF")
# Itération (i prendra la valeur de l'itération, de 1 au nombre indiqué plus
haut).
for(i in 1:nIter){
# Nous allons utiliser la fonction sampleMat2 du package 'biomod2' qui perm
et de séparer de manière aléatoire un vecteur de présence-absence (binair
e) de telle manière à maintenir la même prévalence (pourcentage de présence)
dans les deux groupes. Un paramètre 'ratio' permet de définir la proportion d
'observation que l'on souhaite garder pour la calibration. En règle générale,
cette proportion va de 0.6 à 0.8.
calibEval <- SampleMat2(dataSpEnv$VulpesVulpes,ratio = 0.7)
# L'objet issu de la fonction sampleMat2 est une liste de deux vecteurs. Le
premier (appelé calibration) indique les numéros des lignes prévus pour la ca
libration et le deuxième (appelé evaluation), le numéro des lignes prévus pou
r le test.
# On crée un tableau (déstiné à la partie calibration) avec les lignes du t
ableau initial indiquées par le vecteur calibEval$calibration.
calib <- dataSpEnv[calibEval$calibration,]
# On crée un tableau (déstiné à la partie test) avec les lignes du tableau
initial indiquées par le vecteur calibEval$evalution.
eval <- dataSpEnv[calibEval$evaluation,]

# GLM
# Calibration du GLM. Le nom de la variable réponse en fonction de toutes l
es variables (~.) contenues dans le tableau (data=). Nous spécifions aussi la
famille de distribution (binomial) dont la fonction lien est la fonction 'log
it'. Cette fois-ci, nous spécifions data=calib.
modGLM <- glm(VulpesVulpes~.,data=calib,family = binomial("logit"))
# Prédiction sur la partie test. Les valeurs environnementales du tableau '
eval' sont utilisées par le modèle pour prédire. Il est important de spécifie
r type="response" afin d'obtenir les valeurs après transformation grâce à la
fonction lien (voir théorie GLM). Les valeurs prédites seront comprises entre
0 et 1.
predTest <- predict(modGLM,newdata=eval,type="response")
# Calcul du TSS comme vu précédemment. Nous sauvegardons le premier élément
[1] de l'objet issu de la fonction bm_FindOptimStat qui correspond à la valeu
r du TSS.
tss <- bm_FindOptimStat("TSS",eval$VulpesVulpes,predTest,threshold = seq(0,
1,by = 0.01))[1]
# Nous sauvegardons la valeur de l'objet tss à la ligne i qui correspond un
numéro de l'itération en cours et à la colonne "GLM"
tssTable[i,"GLM"] <- tss

# Random Forest
# Calibration du Random Forest. Nous aimerions utiliser le mode 'classifica
tion', pour cela nous devons spécifier que la colonne VulpesVulpes est en fac
tor (catégorie 1 et catégorie 0). Nous calibrons notre modèle sur le jeu de d
onnées 'calib'.
modRF <- randomForest(as.factor(VulpesVulpes)~.,data=calib)
# Prédiction sur la partie test. Les valeurs environnementales du tableau '
eval' sont utilisées par le modèle pour prédire. Nous sélectionnons la deuxiè
me colonne qui correspond aux probabilité de présence.
predTest <- predict(modRF,newdata=eval,type="prob")[,2]
# Calcul du TSS comme vu précédemment. Nous sauvegardons le premier élément
[1] de l'objet issu de la fonction bm_FindOptimStat qui correspond à la valeu
r du TSS.
tss <- bm_FindOptimStat("TSS",eval$VulpesVulpes,predTest,threshold = seq(0,
1,by = 0.01))[1]
# Nous sauvegardons la valeur de l'objet tss à la ligne i qui correspond un
numéro de l'itération en cours et à la colonne "RF"
tssTable[i,"RF"] <- tss
}
Nous pouvons dès lors comparer les valeurs de TSS (validation croisée) obtenues selon les
deux techniques.
# Distribution des valeurs selon la technique.
boxplot(tssTable$GLM,tssTable$RF,names=c("GLM","RF"),ylab="TSS")

# Test statistique permettant de montrer que les deux techniques donnent des
valeurs de TSS significativement différentes (si p-value < 0.05).
print(wilcox.test(tssTable$GLM,tssTable$RF))

##
## Wilcoxon rank sum exact test
##
## data: tssTable$GLM and tssTable$RF
## W = 0, p-value = 1.083e-05
## alternative hypothesis: true location shift is not equal to 0

Selon les valeurs de TSS obtenues, nous pouvons conclure, dans notre cas, que les deux
techniques donnent de très bons résultats. Cependant, le Random Forest semble supérieur
en termes de performance prédictive avec un TSS médian très élevé.

Partie VI: Prédictions à l’échelle globale et conclusion


Nous allons maintenant utiliser nos modèles pour prédire à l’échelle du globe, en utilisant la
fonction ‘predict’ du package raster. Cette fonction permet de prédire des raster pour autant
que les noms des rasters en entrées (variables environnementales) contiennent les noms des
variables utilisées pour la calibration du modèle.
# Noms des rasters en entrée. Ils contiennent bien les noms de nos prédicteur
s utilisés pour calibrer nos modèles (objet preds).
names(dataEnv)

## [1] "bio3" "bio4" "bio7" "bio11" "bio12"

# Calibration du GLM sur toutes nos données. Le nom de la variable réponse en


fonction de toutes les variables (~.) contenues dans le tableau (data=). Nous
spécifions aussi la famille de distribution (binomial) dont la fonction lien
est la fonction 'logit'.
modGLM <- glm(VulpesVulpes~.,data=dataSpEnv,family = binomial)
# Prediction avec notre GLM. Il est important de spécifier type="response" af
in d'obtenir les valeurs après transformation grâce à la fonction lien (voir
théorie GLM). Les valeurs prédites seront comprises entre 0 et 1.
# Nous utilisons la syntaxe raster::predict pour s'assurer que R utilise bien
la fonction predict du package 'raster'. Rapellons que dataEnv correspond à l
a pile de raster qui correspond aux variables environnementales et qui couvre
toute la planète
predictGLM <- raster::predict(dataEnv,modGLM,type="response")
# Afficher raster
plot(predictGLM,main="Vulpes vulpes (GLM)")

Comme précédemment, utilisons notre modèle pour prédire à l’échelle du globe.


# Calibration du RF sur toutes nos données. Nous aimerions utiliser le mode '
classification', pour cela nous devons spécifier que la colonne VulpesVulpes
est en factor (catégorie 1 et catégorie 0).
modRF <- randomForest(as.factor(VulpesVulpes)~.,data=dataSpEnv)
# Prediction avec notre RF. Il est important de spécifier type="prob" afin d'
obtenir des valeurs de probabilités et non pas binaires. Le paramètre index=2
permet d'obtenir la probabilité de présence, index=1 donnerait la probabilité
d'absence.
predictRF <- raster::predict(dataEnv,modRF,type="prob",index=2)
plot(predictRF,main="Vulpes vulpes (RF)")

En comparant ces deux cartes, on remarque des différences significatives, principalement en


Afrique du Nord, en Amérique du Sud et en Australie. Sur la base de notre évaluation de la
performance prédictive, on pourrait dire que la carte obtenue grâce au modèle Random
Forest est plus fiable. En revanche, l’interprétation d’un point de vue écologique des courbes
réponses issues du Random Forest est plus difficile. Chaque technique à ses avantages et ses
inconvénients. Il existe une multitude de techniques (GLM, GAM, MaxENT, Random Forest,
Gradient Boosted Trees, SVC, etc.). Une tendance récente est de combiner plusieurs
techniques pour créer ce que l’on appelle des ‘modèles d’ensemble’. Dans notre cas, il serait
par exemple possible de calculer une moyenne pondérée (selon les valeurs de TSS ou d’AUC)
des prédictions du GLM et du Random Forest. Il existe aussi souvent plusieurs manières de
paramétrer une technique. Par exemple, nous avons calibré un GLM simple, mais il nous
aurait été possible d’ajouter un effet quadratique ou des interactions entre les variables. Par
ailleurs, nous avons aussi toute une panoplie de méthodes permettant l’évaluation de la
performance prédictive d’un modèle (différents indices, mais aussi différentes manières de
partitionner notre jeu de données). En général, les choix dépendent principalement des
objectifs, des données à disposition, mais aussi des compétences et habitudes de chacun.

Vous aimerez peut-être aussi