An application of spatial Gaussian process

Mathieu Genu & Matthieu Authier

mathieu.genu@univ-lr.fr
Observatoire Pelagis - UAR 3462 - La Rochelle Université

12 décembre 2024

Présentation

Mathieu Genu

ingénieur d’études à l’observatoire pelagis

  • Fabrication de package
  • Appui technique en analyse de données au sein du labo
  • Création de rapports automatisés / scripts de verification

Initié à l’approche bayésienne avec STAN (grâce/à cause de) :

Matthieu Authier

Contexte

Depuis 2017, un pic d’échouage à lieu chaque hiver sur les côtes de France métropolitaine.

La campagne CAPECET

Echantillonner la mégafaune marine au large des côtes françaises.

  • zone CAPECET : 35 183 km² (13.52% de la ZEE Atlantique de la France métropolitaine)

La Campagne CAPECET

Transect aérien

La Campagne CAPECET

Transect aérien

La Campagne CAPECET

⚠️ Les sessions n’ont pas lieu au même moment de l’année entre les campagnes

La Campagne CAPECET

L’échantillonnage théorique :

La Campagne CAPECET

Les fenêtres météorolgiques ne permettent pas de réaliser l’ensemble des survols

La Campagne CAPECET

Les conditions d’observations peuvent être trop dégradées (Beaufort + appréciation des observateurs)

La Campagne CAPECET

Au final, l’échantillonnage n’est pas spatiallement uniforme entre les sessions

“Données mitées”

Les observations

Interpolation CDS (Conventionnal Distance Sampling)

La méthode :

CDS pour les Petits delphininés

Fonction de détection : Loi demi-normale (half normal) \(f(x)=e^{\frac{-x^2}{2\sigma^2}}\)

Effective strip width : \(esw=\int_{0}^{w} f(x)\,{\rm d}x\)

CDS pour les Petits delphininés




Peu d’individus en janvier et février et une plus forte abondance en mars



Une abondance qui augmente de janvier à février et qui diminue en mars



Une abondance assez faible en janvier et février qui augmente en mars

Quelle distribution Spatiale

Ce qui nous intéresse c’est l’évolution de la distribution spatiale des petits delphininés

On souhaite fabriquer les cartes d’interpolations autour des observations, sauf que :

  • l’échantillonnage n’est pas uniforme

  • Il y a une forte dispersion des tailles de groupes (or en CDS \(\mu_{taille de groupe}\))

Taille de groupe
year session min moy med max sd dispersion*
2020 1 0 0.96 0 40 4.56 21.63
2 0 1.15 0 17 2.82 6.94
3 0 0.55 0 13 2.04 7.57
4 0 3.09 0 100 8.71 24.52
2023 1 0 0.72 0 10 2.06 5.87
2 0 1.71 0 18 3.26 6.22
3 0 2.24 0 30 3.98 7.05
4 0 3.10 1 32 5.12 8.44
5 0 2.19 0 30 3.84 6.71
6 0 1.76 0 25 3.49 6.93
2024 1 0 1.22 0 20 3.12 7.98
2 0 1.67 0 18 3.44 7.10
3 0 1.80 1 13 2.59 3.74
4 0 3.84 1 40 6.11 9.72

*\(\frac{\sigma^2}{\mu}\)

Modélisation de krigeage par processus gaussien

Intérêt d’utiliser l’approche bayésienne

Cela permet d’intégrer :

  • l’hétérogénéité de l’échantillonnage, en utilisant un modèle autorégressif
  • la forte dispersion dans les tailles des groupes en utilisant une distribution béta-binomiale négative

Le modèle autoregressif d’ordre 1

Au cours d’une année, ce qui se passe au cours d’une session est le résultat de ce qui s’est passé la session d’avant plus ou moins quelque chose :

\(X_t = \varphi_i X_{t-1} + \varepsilon_t\)

Structure du modèle

Structure du modèle

Intégration des distributions aisée avec STAN

functions {

  matrix kron_mvprod(matrix A, matrix B, matrix V)
  {
    return transpose(A*transpose(B*V));
  }

  matrix gp(int N_rows, int N_columns, real[] rows_idx, real[] columns_index,
  real delta0,
  real alpha_gp,
  real rho_gp1, real rho_gp2,
  matrix z1)
  {

    matrix[N_rows,N_columns] GP;

    matrix[N_rows, N_rows] K1;
    matrix[N_rows, N_rows] L_K1;

    matrix[N_columns, N_columns] K2;
    matrix[N_columns, N_columns] L_K2;

    for(i in 1:N_rows) {
      for(j in 1:N_rows) {
        K1[i, j] = alpha_gp * (1 + fabs(i - j) * sqrt(3) / rho_gp1) * exp(-fabs(i - j) * sqrt(3) / rho_gp1);
      }
    }
    K1 = K1 + diag_matrix(rep_vector(delta0, N_rows));

    for(i in 1:N_columns) {
      for(j in 1:N_columns) {
        K2[i, j] = alpha_gp * (1 + fabs(i - j) * sqrt(3) / rho_gp2) * exp(-fabs(i - j) * sqrt(3) / rho_gp2);
      }
    }
    K2 = K2 + diag_matrix(rep_vector(delta0, N_columns));

    L_K1 = cholesky_decompose(K1);
    L_K2 = cholesky_decompose(K2);

    GP = kron_mvprod(L_K2, L_K1, z1);

    return(GP);
  }

  real beta_neg_binomial_lpmf(int y, real size_param, real shape_param, real location_param) {
    // size is the size parameter of the negative binomial distribution
    // prob is the probability parameter of the the negative binomial distribution
    // shape the first shape parameter of the beta distribution
    // shape2 the second shape parameter of the beta distribution
    // location is the mean of the beta-negative-binomial parameter
    real value;
    real shape2 = (shape_param - 1) * location_param / size_param;

    // sanity checks
    if (size_param > 1E8) {
      value = negative_infinity();
    } else if (shape_param > 1E8) {
      value = negative_infinity();
    } else if (shape2 > 1E8) {
      value = negative_infinity();
    } else if (size_param <= 1E-8) {
      value = negative_infinity();
    } else if (shape_param <= 1E-8) {
      value = negative_infinity();
    } else if (shape2 <= 1E-8) {
      value = negative_infinity();
    } else {
      // numerator
      value = lgamma(y + size_param) - lgamma(y + 1) - lgamma(size_param);
      // and denominator
      value += lbeta(shape_param + size_param, shape2 + y) - lbeta(shape_param, shape2);
    }
    return value;
  }
}

data {
  // distance sampling
  int<lower = 1> n_det;
  int<lower = 1> n_level;
  real BEAUFORT[n_level];
  real<lower = 0.0> w; // truncation distance
  int<lower = 1> BEAUFORT_det[n_det];
  vector<lower = 0.0, upper = w>[n_det] DISTANCE;
  real<lower = 0.0> prior_scale_sigma;
  // density surface model
  int<lower = 1> n_seg;
  int<lower = 1> n_year;
  int<lower = 1> n_session;
  int<lower = 0> COUNT[n_seg];                    // response variable
  vector<lower = 0.0>[n_seg] EFFORT;              // offset
  int<lower = 1> BEAUFORT_seg[n_seg];
  int<lower = 1, upper = n_year> YEAR[n_seg];     // year
  int<lower = 1, upper = n_session> SESSION[n_seg];// session
  real prior_location_intercept;
  real<lower = 0.0> prior_scale_intercept;
  // spatial: BSplines to approximate GP
  int<lower = 1> n_cell;
  int<lower = 1> n_row;
  int<lower = 1> n_col;
  int<lower = 0, upper = n_cell> IDROW[n_seg];
  int<lower = 0, upper = n_cell> IDCOL[n_seg];
  int num_basis_rows;
  int num_basis_columns;
  matrix[num_basis_rows, n_row] BASIS_ROWS;
  matrix[num_basis_columns, n_col] BASIS_COLUMNS;
  real IDX_BASIS_ROWS[num_basis_rows];
  real IDX_BASIS_COLUMNS[num_basis_columns];
}

transformed data {
  real eps = 1e-9;
  real prior_scale_delta = log2() / 2;
}

parameters {
  vector[n_session] unscaled_intercept[n_year];
  // overdispersion
  real<lower = 0.0, upper = 1.0> inv_alpha;
  // temporal
  real<lower = -1.0, upper = 1.0> temporal_range[n_year];
  // spatial
  real<lower = 0.0> rho_1;
  real<lower = 0.0> rho_2;
  real<lower = 0.0> alpha_gp;
  matrix[num_basis_rows, num_basis_columns] eta[n_year, n_session];
  // distance sampling
  vector<lower = 0.0>[2] unscaled_sigma2;
  vector<lower = 0.0>[2] tau;
  real unscaled_delta;
}

transformed parameters {
  matrix[num_basis_rows,num_basis_columns] beta[n_year, n_session];
  matrix[n_row, n_col] latent[n_year, n_session];
  real r = 1 / (unscaled_sigma2[2] / tau[2]); // size parameter, https://github.com/stan-dev/rstanarm/issues/275
  real alpha = 1 / inv_alpha; // shape parameter > 1
  vector[n_session] intercept[n_year];
  vector[n_seg] log_lik;
  // distance sampling
  real delta = unscaled_delta * prior_scale_delta;
  vector[n_level] sigma;
  vector[n_level] esw;
  for(k in 1:n_level) {
    sigma[k] = prior_scale_sigma * sqrt(unscaled_sigma2[1] / tau[1]) * exp(delta * BEAUFORT[k]);
    esw[k] = (normal_cdf(w, 0.0, sigma[k]) - 0.5) * exp(-normal_lpdf(0.0| 0.0, sigma[k]));
  }
  // spatial effects
  for(k in 1:n_year) {
    intercept[k] = prior_location_intercept + prior_scale_intercept * unscaled_intercept[k];
    for(l in 1:n_session) {
      beta[k, l] = gp(num_basis_rows, num_basis_columns,
                      IDX_BASIS_ROWS, IDX_BASIS_COLUMNS,
                      eps, alpha_gp, rho_1,  rho_2,
                      eta[k, l]);
    }
    // temporal correlation
    latent[k, 1] = sqrt(1 - square(temporal_range[k])) * ((BASIS_ROWS') * beta[k, 1] * BASIS_COLUMNS); // initial condition
    for(l in 2:n_session) {
      latent[k, l] = temporal_range[k] * latent[k, l - 1] + ((BASIS_ROWS') * beta[k, l] * BASIS_COLUMNS);
    }
  }
  // linear predictor
  for(i in 1:n_seg) {
    log_lik[i] = beta_neg_binomial_lpmf(COUNT[i]| r, alpha, (2 * EFFORT[i] * esw[BEAUFORT_seg[i]]) * exp(intercept[YEAR[i], SESSION[i]] + latent[YEAR[i], SESSION[i], IDROW[i], IDCOL[i]]));
  }
}

model {
  rho_1 ~ inv_gamma(5.0, 5.0);
  rho_2 ~ inv_gamma(5.0, 5.0);
  alpha_gp ~ std_normal();
  for(i in 1:num_basis_rows) {
    for(j in 1:num_basis_columns) {
      for(k in 1:n_year) {
        for(l in 1:n_session) {
          eta[k, l, i, j] ~ std_normal();
        }
      }
    }
  }
  for(k in 1:n_year) {
    unscaled_intercept[k] ~ std_normal();
  }
  for(i in 1:n_seg) {
    target += log_lik[i];
  }
  // distance sampling
  unscaled_delta ~ normal(0.0, 1.0);
  unscaled_sigma2 ~ gamma(0.5, 1.0);
  tau ~ gamma(1.0, 1.0);
  for(j in 1:n_det) {
    target += normal_lpdf(DISTANCE[j]| 0.0, sigma[BEAUFORT_det[j]]);
  }
}

Comparaison de modèle

Poisson vs Bêta-bionmiale négative

Modèle avec distribution Poisson, autorégression sur les sessions et effet année

Modèle avec distribution bêta-binomiale négative, autorégression et effet année

Le modèle Poisson ne permet pas d’aboutir à de bonnes prédictions comparé au modèle avec la bêta-binomiale négative

Validité du modèle

Résultats du modèle

La distribution des petits delphininés est plus côtière en 2023 et 2024 comparé à 2020

Pour Conclure

sur la problématique :

  • Les petits delphinidés semblent se rapprocher de plus en plus des côtes en hiver


Concernant la méthode

STAN est un outil permettant :

  • de facilement intégrer de nouvelles distributions
  • d’utiliser des modèles joints (krigeage + Distance sampling + modèle autoregressif)

Pour Conclure