plot(predictors)
Reliable validation of spatial machine learning
Earth Observation Summer School 2026, Istanbul, 2026-08-19


We have this:

We want to predict here:

We have this:

Our predictor distributions are similar here:

We have this:

We want to predict here:

We have this:

Our predictor distributions are a bit different here:




Identify areas where the environment is not well represented, making predictions less trustworthy (Area of Applicability – AoA, Meyer and Pebesma, 2021); also local point density (LPD, Schumacher et al., 2025)




Area of applicability for different sampling designs

Extract predictor values for the sample points and prepare training data:
Calculate the Area of Applicability (AoA) for the sample points:






k-Nearest Neighbor Distance Matching (kNNDM, Linnenbrink et al., 2024) matches folds to the prediction scenario using distance structure (either in geographic or predictor space).



Evaluation results for different validation strategies

Create a baseline random forest model:
Create a random cross-validation strategy:
Create a kNNDM cross-validation strategy:
Compare the RMSE of the random and kNNDM cross-validation strategies
Random cross-validation:
Given that this is a simulation study, we can also compare the RMSE of the cross-validation strategies to the true RMSE of the model predictions across the whole area of interest.
Apply the Area of Applicability (AoA) analysis to the kNNDM model predictions:
Error profiles show how expected error (based on DI or LPD) relates to true error. They can be used to identify where predictions are more or less trustworthy, and to adjust the AoA threshold or interpret LPD values.






| Evaluation approach | Lowland-area weight (%) | Highland-area weight (%) | Overall RMSE |
|---|---|---|---|
| Germany domain (target distribution) | 50 | 50 | 0.667 |
| Preferential sample (unweighted) | 89 | 11 | 0.541 |
| Preferential sample (reweighted) | 50 | 50 | 0.667 |
Target-Weighted Cross-Validation (TWCV, Brenning and Suesse, 2026) adjusts cross-validation weights to align evaluation with the prediction domain rather than the sampled data distribution.


Effect of weighting validation points 
This time we have a preferential sample.
kn <- CAST::knndm(tpoints = pref_samples_df,
modeldomain = predictors[[1]], k = 5)
ctrl_knndm <- trainControl(
method = "cv", index = kn$indx_train,
indexOut = kn$indx_test, savePredictions = "final",
verboseIter = FALSE
)
pref_rf_knndm <- train(
x = pref_train_data, y = pref_samples_df[[response]],
method = "ranger", trControl = ctrl_knndm,
tuneGrid = grid, metric = "RMSE",
num.trees = 300, importance = "impurity"
)
pref_knndm_rmse <- calc_rmse(pref_rf_knndm$pred$pred,
pref_rf_knndm$pred$obs)
pref_knndm_rmse[1] 0.6411687
The PredictionMatching package is still under heavy development, and the API may change in the future. Please check the PredictionMatching GitHub repository
library(PredictionMatching) # pak::pak("JanLinnenbrink/PredictionMatching")
w <- tw_calculate_weights(tpoints = pref_train_data, modeldomain = predictors)
pe <- tw_pointwise_error(obs = pref_rf_knndm$pred$obs, pred = pref_rf_knndm$pred$pred,
id = pref_rf_knndm$pred$rowIndex)
plot(w, pointwise_error = pe)[[2]]| RMSE | |
|---|---|
| True RMSE | 0.782 |
| KNN-DM RMSE | 0.641 |
| Weighted RMSE | 0.721 |
Key components:

Open questions remain, including how to mix these three components together (e.g., how to weight folds, should we define the prediction domain in advance before constructing folds, etc.).
Our current related work: Nowosad et al., 2026, Linnenbrink et al., 2026
Slides:

