25/07, 2020

Carguemos paquetes

library(BIEN)
library(dismo)
library(ENMeval)
library(maxnet)
library(raster)
library(rworldxtra)
library(sf)
library(tidyverse)

Que son los SDM (Species Distribution Models)

Objetivos

  • Entender que modelan las SDM
  • Diferenciando Maxent de otros algoritmos
    • Parametros de regularización
    • Pseudoaucencias vs Background
  • Respuestas (Lineal, Cuadrática, Bisagra, Producto)
  • Recomendaciones según número de presencias

Que modelan las SDM

  • Distribución potencial, no real
  • No considera disperción
  • No es tan fácil dividir en presencia y ausencia

Primero obtengamos presencias

  • Paquete BIEN para plantas
  • Para animales y otros rgbif, pero hay que hacerse cuenta

N_pumilio <- BIEN_occurrence_species(species = "Nothofagus pumilio")

Generaremos un Buffer para el background y bajamos capas

N_pumilio_SF <- N_pumilio %>% st_as_sf(coords = c(3, 2), crs = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0")
Hull <- N_pumilio_SF %>% st_union() %>% st_convex_hull()
Buffer <- Hull %>% st_buffer(dist = 1) %>% st_as_sf()
data("countriesHigh")
SA <- countriesHigh %>% st_as_sf() %>% st_make_valid() %>% st_crop(Buffer)
Bioclimatic <- getData(name = "worldclim", var = "bio", res = 0.5, 
    lon = -70, lat = -50)
## capas climaticas
Bioclimatic <- Bioclimatic %>% crop(Buffer) %>% trim()
## Cortamos el Tile
names(Bioclimatic) <- str_remove_all(names(Bioclimatic), "_43")

Como se ve

Para generar un modelo necesitamos Backgrounds

set.seed(2020)
Pres <- N_pumilio %>% dplyr::select(longitude, latitude) %>% 
    mutate(Pres = 1)
Aus <- dismo::randomPoints(mask = Bioclimatic[[1]], n = 5000) %>% 
    as.data.frame() %>% rename(longitude = x, latitude = y) %>% 
    mutate(Pres = 0)
Pres_Aus <- bind_rows(Pres, Aus)
Pres_Aus_Sf <- Pres_Aus %>% st_as_sf(coords = c(1, 2), crs = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +towgs84=0,0,0")

Así se vé

Extracción de datos

Condiciones <- raster::extract(Bioclimatic, Pres_Aus_Sf) %>% 
    as.data.frame() %>% bind_cols(Pres_Aus)

Dudas hasta ahora

Empezemos a modelar

  • La forma mas sencilla maxnet
set.seed(2020)
Mod1 <- maxnet(p = Condiciones$Pres, data = Condiciones[, 1:19], 
    regmult = 1, maxnet.formula(p = Condiciones$Pres, data = Condiciones[, 
        1:19], classes = "lq"))
  • Multiplicador de regularización (Número)
  • Classes entre “lqpt”

Respuestas

plot(Mod1, c("bio1", "bio2", "bio3"))

Respuestas (cloglog)

plot(Mod1, type = "cloglog", c("bio1", "bio2", "bio3", "bio12"))

Respuestas

Respuestas

Mod2 <- maxnet(p = Condiciones$Pres, data = Condiciones[, 1:19], 
    regmult = 1, maxnet.formula(p = Condiciones$Pres, data = Condiciones[, 
        1:19], classes = "l"))
Mod3 <- maxnet(p = Condiciones$Pres, data = Condiciones[, 1:19], 
    regmult = 1, maxnet.formula(p = Condiciones$Pres, data = Condiciones[, 
        1:19], classes = "lh"))

Repuestas lineales

plot(Mod2, c("bio1", "bio2", "bio3", "bio12"))

Repuestas bisagra

plot(Mod3, c("bio1", "bio2", "bio3", "bio12"))

Default

  • Si las presencias son < 10 “l”
  • Si las presencias son < 15 “lq”
  • Si las presencias son < 80 “lqh”
  • Si las presencias son >= 80 “lqph”
Mod4 <- maxnet(p = Condiciones$Pres, data = Condiciones[, 1:19], 
    regmult = 1)

Respuesta default

plot(Mod4, c("bio1", "bio2", "bio3", "bio12"))

Regularización

Regularizacion

  • Maxent es como un modelo binomial
  • Parte con una estimación para todas las variable
  • Va penalizando cada variable según su importancia
  • Quedamos con variables de valor 0
  • Se corta con crossvalidation

Así se ve la penalización

Prediccion

Prediccion

Prediction <- predict(Bioclimatic, Mod4, type = "cloglog")

Generando umbrales

Verdaderos positivos y verdaderos negativos

Eval <- dismo::evaluate(p = Pres[, 1:2], a = Aus[, 1:2], model = Mod4, 
    x = Bioclimatic, type = "cloglog")
EvalDF <- Eval@confusion %>% as.data.frame %>% mutate(Threshold = Eval@t) %>% 
    mutate(TP_TN = (tp/nrow(N_pumilio)) + (tn/5000))
head(EvalDF)
##    tp   fp fn tn  Threshold TP_TN
## 1 105 5000  0  0 -1.000e-04     1
## 2 105 5000  0  0 -9.999e-05     1
## 3 105 5000  0  0 -9.998e-05     1
## 4 105 5000  0  0 -9.997e-05     1
## 5 105 5000  0  0 -9.996e-05     1
## 6 105 5000  0  0 -9.995e-05     1

Eligiendo

Eligiendo

EvalThres <- EvalDF %>% dplyr::filter(TP_TN == max(TP_TN))

Eso genera:

Prediction <- Prediction %>% mutate(Binary = ifelse(layer >= 
    EvalThres$Threshold, "Presencia", "Ausencia"))

Que se vé

Seleccionando el mejor modelo

  • Tenemos que hacer crossvalidation
  • Probar distintos valores de regularización
  • Algunos candidatos de Features
  • ENMeval
Results <- ENMevaluate(occ = N_pumilio[, c(3, 2)], env = Bioclimatic, 
    RMvalues = c(0.75, 1, 1.25), n.bg = 5000, method = "randomkfold", 
    overlap = F, kfolds = 5, bin.output = T, fc = c("L", "LQ", 
        "LQP"), rasterPreds = T)
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |========                                                              |  11%
  |                                                                            
  |================                                                      |  22%
  |                                                                            
  |=======================                                               |  33%
  |                                                                            
  |===============================                                       |  44%
  |                                                                            
  |=======================================                               |  56%
  |                                                                            
  |===============================================                       |  67%
  |                                                                            
  |======================================================                |  78%
  |                                                                            
  |==============================================================        |  89%
  |                                                                            
  |======================================================================| 100%

Vemos los resultados

Models <- Results@results
Models$ID <- 1:nrow(Models)
Models <- Models %>% arrange(AICc)

Tabla

settings features rm train.AUC avg.test.AUC var.test.AUC avg.diff.AUC var.diff.AUC avg.test.orMTP var.test.orMTP avg.test.or10pct var.test.or10pct AICc delta.AICc w.AIC parameters AUC_bin.1 AUC_bin.2 AUC_bin.3 AUC_bin.4 AUC_bin.5 diff.AUC_bin.1 diff.AUC_bin.2 diff.AUC_bin.3 diff.AUC_bin.4 diff.AUC_bin.5 test.or10pct_bin.1 test.or10pct_bin.2 test.or10pct_bin.3 test.or10pct_bin.4 test.or10pct_bin.5 test.orMTP_bin.1 test.orMTP_bin.2 test.orMTP_bin.3 test.orMTP_bin.4 test.orMTP_bin.5 ID
LQP_1 LQP 1.00 0.9509714 0.9318305 0.0006626 0.0190886 0.0005317 0.0095238 0.0004535 0.1333333 0.0038549 2640.897 0.000000 0.7331287 31 0.9304857 0.9182857 0.9277143 0.9562571 0.9264095 0.0140214 0.0343333 0.0224357 0 0.0246524 0.1428571 0.1904762 0.0952381 0.047619 0.1904762 0.000000 0 0.047619 0 0 6
LQP_0.75 LQP 0.75 0.9531029 0.9343543 0.0006799 0.0188624 0.0004987 0.0095238 0.0004535 0.1428571 0.0056689 2642.918 2.021109 0.2668713 37 0.9303143 0.9200095 0.9278286 0.9585333 0.9350857 0.0166595 0.0343119 0.0237024 0 0.0196381 0.1428571 0.2380952 0.0952381 0.047619 0.1904762 0.000000 0 0.047619 0 0 3
LQP_1.25 LQP 1.25 0.9486267 0.9304914 0.0006098 0.0189910 0.0005849 0.0095238 0.0004535 0.1238095 0.0040816 2677.150 36.252830 0.0000000 33 0.9311238 0.9176857 0.9276762 0.9534381 0.9225333 0.0117643 0.0347048 0.0214024 0 0.0270833 0.0952381 0.1904762 0.0952381 0.047619 0.1904762 0.000000 0 0.047619 0 0 9
LQ_0.75 LQ 0.75 0.9359867 0.9090667 0.0043328 0.0304300 0.0031957 0.0000000 0.0000000 0.1333333 0.0083900 2738.829 97.931907 0.0000000 20 0.9176381 0.8812190 0.9256857 0.9566952 0.8640952 0.0134619 0.0608071 0.0096738 0 0.0682071 0.0952381 0.2380952 0.1428571 0.000000 0.1904762 0.000000 0 0.000000 0 0 2
LQ_1 LQ 1.00 0.9348457 0.9080495 0.0059549 0.0298657 0.0045001 0.0095238 0.0004535 0.1333333 0.0083900 2755.074 114.176469 0.0000000 21 0.9245810 0.8805905 0.9324762 0.9548190 0.8477810 0.0066333 0.0592167 0.0026881 0 0.0807905 0.0952381 0.2380952 0.1428571 0.000000 0.1904762 0.047619 0 0.000000 0 0 5
LQ_1.25 LQ 1.25 0.9324971 0.9073295 0.0072667 0.0295510 0.0055201 0.0095238 0.0004535 0.1142857 0.0097506 2761.419 120.521450 0.0000000 19 0.9298571 0.8797905 0.9368000 0.9527619 0.8374381 0.0007952 0.0581952 0.0000000 0 0.0887643 0.0952381 0.2380952 0.0476190 0.000000 0.1904762 0.047619 0 0.000000 0 0 8
L_1 L 1.00 0.8272971 0.8043390 0.0130629 0.0365438 0.0095193 0.0000000 0.0000000 0.1142857 0.0120181 2939.690 298.793065 0.0000000 9 0.8334190 0.7735905 0.8482571 0.8597524 0.7066762 0.0000000 0.0606738 0.0000000 0 0.1220452 0.0000000 0.2380952 0.1428571 0.000000 0.1904762 0.000000 0 0.000000 0 0 4
L_1.25 L 1.25 0.8251162 0.8044190 0.0135998 0.0370476 0.0096802 0.0000000 0.0000000 0.1142857 0.0120181 2941.124 300.226889 0.0000000 9 0.8359619 0.7703429 0.8505238 0.8593429 0.7059238 0.0000000 0.0625667 0.0000000 0 0.1226714 0.0000000 0.2380952 0.1428571 0.000000 0.1904762 0.000000 0 0.000000 0 0 7
L_0.75 L 0.75 0.8304667 0.8051562 0.0118044 0.0352948 0.0088293 0.0000000 0.0000000 0.1333333 0.0106576 2945.480 304.582495 0.0000000 12 0.8300952 0.7769905 0.8474095 0.8591048 0.7121810 0.0000000 0.0591357 0.0000000 0 0.1173381 0.0476190 0.2380952 0.1904762 0.000000 0.1904762 0.000000 0 0.000000 0 0 1

Seleccionando el mejor modelo

# Indice del mejor modelo
Models$ID[1]
## [1] 6
# Mejor modelo
BestModels <- Results@models[[Models$ID[1]]]
## Prediccion del mejor modelo
Prediction <- predict(Bioclimatic, BestModels, type = "cloglog") %>% 
    as("SpatialPixelsDataFrame") %>% as.data.frame()

Mejor modelo

Preguntas