Official code repository for the paper Grazing Detection using Deep Learning and Sentinel-2 Time Series Data, summarizing the outcomes of a project conducted by RISE Research Institutes of Sweden and the Swedish Board of Agriculture (SBA), with funding from the Swedish National Space Agency (SNSA). Code mainly developed by Aleksis Pirinen (RISE), with contributions from Delia Fano Yela and Smita Chakraborty (both at RISE). Erik Källman (RISE) was the project leader. We thank the SBA, and Niklas Boke Olen in particular, for their valuable contributions, including key parts of the data used for this work.
- Our work got presented at the Swedish Climate Symposium 2026 in Lund!
- Our work will be presented at the ELLIS UnConference Workshop - AI for Earth and Climate Sciences in December 2025!
- Our work got accepted at AICC: Workshop on AI for Climate and Conservation at EurIPS 2025!
- Code has been changed so that satellite data is not by default normalized as (img - 1000) / 10000 for post-Jan-2022 data, instead simply doing img / 10000 (see e.g. the file
inspect_poly_timeseries.py). Thanks Isak Randahl and Linnea Sartorius for flagging this!
The polygons and associated labels in this project were obtained from the SBA -- please contact their GIS department (Gis.Support@jordbruksverket.se) if you want to ask for access to their polygons and labels, including the ones we used in this project. However, satellite data can be freely downloaded from the Digital Earth Sweden platform using scripts provided within this code repository, where you could of course specify regions of interest with polygons of your own.
Pre-trained ML models that give ~80% accuracy can be downloaded here (extract and put into the log folder in the repository).
- Code, models and data for the cloud detection pipeline used in this work is available here. The paper describing the pipeline is available here.
First, clone this repo. Then, see the included requirements.txt file for all Python packages used on a fresh Ubuntu 24.04.2 machine that is equipped with a modern Nvidia-5090 GPU (install the packages in the requirements file with the command: pip install -r requirements.txt). Note that you might want and have to change the torch-versions in the requirements file if you have another (older) GPU, or if you don't intend to use a GPU at all. Tip: It might be a good idea to first set up a virtual environment on your machine, prior to installing packages from requirements.txt.
config.py is the main file for setting various parameters in the other files to be run.
train_ml.py is the main file for training an ML-based satellite image time series classifier (Sentinel 2 L2A data assumed). It assumes a dataset of time series with associated binary labels (1 = grazing activity | 0 = no grazing activity), where a single label is given per full time series. The dataset was provided as polygons from the SBA, and then associated time series satellite imagery was downloaded from Digital Earth Sweden using the script download_and_process_gpkgs_as_processes.py (described below), and the downloaded data was in turn made ML-ready using the script prepare_sen2_ml_dataset.py (described below). Note: Models can also be evaluated using train_ml.py, by setting the EVAL_ONLY flag in config.py to True, and pointing MODEL_LOAD_PATH_BASE in config.py to the folder containing trained model weights. Pre-trained ML models that give ~80% accuracy can be downloaded here (extract and put into the log folder in the repository).
plot_results.py can be used for plotting some results, generated e.g. from the training statistics within train_ml.py (see above).
download_and_process_gpkgs_as_processes.py is the script that is used to download data from Digital Earth Sweden. Details should be quite clear by looking within the file.
explore-2022-jv-data.py and explore-2024-jv-data.py are scripts for investigating the polygons from the SBA, where we have labels for each time series. Before using any of these two scripts, download the content of this folder and place it into a folder called country-borders that is outside (one level "up") of this repository. You also need access to the polygon data from SBA (see Data above).
prepare_sen2_ml_dataset.py takes the data by the SBA (which can be explored in the files explore-2022-jv-data.py and explore-2024-jv-data.py) and makes it into a format that can then be ML-trained within the file train_ml.py (see above). Note that cloud predictions is also performed as a preprocessing step, and by default, only polygons without clouds are kept in the time series.
inspect_poly_timeseries.py is a file that visualizes various polygon tile time series that were downloaded using the script download_and_process_gpkgs_as_processes.py.
utils.py is a basic file with various utilities (imported by other scripts in the repo). It's best understood by checking examining the file contents.
Running the default train_ml.py code with EVAL_MODE=True and MODEL_LOAD_PATH_BASE = 'log/2025-07-06_10-40-23' in config.py (and having downloaded ML models, extracted them and put them into the log directory), should give this output on the data from the SBA:
Mean CE_loss tot: 0.22250, ma: 0.22250, last: 0.22250
Mean Accuracy tot: 0.90000, ma: 0.90000, last: 0.90000
Mean Accuracy_grazing tot: 1.00000, ma: 1.00000, last: 1.00000
Mean Accuracy_no_activity tot: 0.83333, ma: 0.83333, last: 0.83333
Mean F1_score tot: 0.89899, ma: 0.89899, last: 0.89899
Mean Precision tot: 0.90000, ma: 0.90000, last: 0.90000
Mean Recall tot: 0.91667, ma: 0.91667, last: 0.91667
Mean Precision_grazing tot: 0.80000, ma: 0.80000, last: 0.80000
Mean Recall_grazing tot: 1.00000, ma: 1.00000, last: 1.00000
Mean Precision_no_activity tot: 1.00000, ma: 1.00000, last: 1.00000
Mean Recall_no_activity tot: 0.83333, ma: 0.83333, last: 0.83333
Mean Accuracy_val tot: 0.79661, ma: 0.79661, last: 0.79661
Mean Accuracy_grazing_val tot: 0.86667, ma: 0.86667, last: 0.86667
Mean Accuracy_no_activity_val tot: 0.72414, ma: 0.72414, last: 0.72414
Mean F1_score_val tot: 0.79514, ma: 0.79514, last: 0.79514
Mean Precision_val tot: 0.80235, ma: 0.80235, last: 0.80235
Mean Recall_val tot: 0.79540, ma: 0.79540, last: 0.79540
Mean Precision_grazing_val tot: 0.76471, ma: 0.76471, last: 0.76471
Mean Recall_grazing_val tot: 0.86667, ma: 0.86667, last: 0.86667
Mean Precision_no_activity_val tot: 0.84000, ma: 0.84000, last: 0.84000
Mean Recall_no_activity_val tot: 0.72414, ma: 0.72414, last: 0.72414
- Slightly changed loss computation, so that the last 4 time step predictions are used within the loss, not only the last step prediction. Please refer to Line 137 and onwards within
train_ml.pyfor more on this.
If you use this repository and/or find our paper useful, please cite the following:
@article{pirinen2025grazing,
title={Grazing Detection using Deep Learning and Sentinel-2 Time Series Data},
author={Pirinen, Aleksis and Yela, Delia Fano and Chakraborty, Smita and K{\"a}llman, Erik},
journal={arXiv preprint arXiv:2510.14493},
year={2025}
}
This project is released under the MIT License.
Copyright (c) 2025, RISE Research Institutes of Sweden.
See the full text in the license file.