Skip to content
Open
Show file tree
Hide file tree
Changes from 71 commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
b6150da
add RegressionSystem
Zathimo Jul 25, 2024
c4bd970
add poverty example
Zathimo Jul 25, 2024
701edbc
add datasets and outputs to gitignore
Zathimo Jul 25, 2024
06a5518
change description project poverty
LilBabines Jul 31, 2024
5dc5159
add datset landsat
LilBabines Jul 31, 2024
092d882
add datset_poverty modif
LilBabines Jul 31, 2024
7cf0c8e
add datset , .tiff
LilBabines Jul 31, 2024
f446276
display poverty images / bands
LilBabines Jul 31, 2024
19d22c7
modif MSDataset
LilBabines Jul 31, 2024
4af7c49
add label.csv
LilBabines Jul 31, 2024
5e08b87
remove dataset from ignore
LilBabines Jul 31, 2024
4574e1a
write LightningDataModule
LilBabines Jul 31, 2024
9eeca80
add main test
LilBabines Jul 31, 2024
1dfcc81
add observation
LilBabines Jul 31, 2024
71bf40d
rename
LilBabines Jul 31, 2024
38f8725
update description
LilBabines Jul 31, 2024
2572ea9
modifications test_dataset
Zathimo Aug 1, 2024
87fe8f1
add *.tif, landsat_tiles
LilBabines Aug 1, 2024
fed4d58
avancement
LilBabines Aug 1, 2024
51a5511
test
LilBabines Aug 1, 2024
b2f94d5
changes
LilBabines Aug 1, 2024
f583e0d
uptade impot __init__
LilBabines Aug 1, 2024
8925b22
add config
LilBabines Aug 1, 2024
7572e64
works ?
LilBabines Aug 1, 2024
29d7517
changes
LilBabines Aug 1, 2024
87f02ff
add torchmetrics import
LilBabines Aug 2, 2024
8a01f14
add print debugg
LilBabines Aug 2, 2024
6b508d5
add sys.path.append to work with malpolon root package
LilBabines Aug 2, 2024
e0b71ec
changes
LilBabines Aug 2, 2024
594117c
works ??
LilBabines Aug 2, 2024
e2862b9
changes
LilBabines Aug 2, 2024
194f0d4
test
LilBabines Aug 2, 2024
a681826
duplicate data to debugg
LilBabines Aug 2, 2024
61f3980
debugg add print
LilBabines Aug 2, 2024
043f4ec
ca marche pas
LilBabines Aug 2, 2024
7a09c28
remove sample_data
LilBabines Aug 5, 2024
a803476
changes
LilBabines Aug 5, 2024
119e6c4
add normalize mean std
LilBabines Aug 5, 2024
9c3c459
clean main
LilBabines Aug 5, 2024
e1f8e45
clean config
LilBabines Aug 5, 2024
6168e7d
add normalizer transform
LilBabines Aug 5, 2024
e6f89f6
clean print
LilBabines Aug 5, 2024
11dc58f
chabge files names
LilBabines Aug 6, 2024
db17b35
k folds
Zathimo Aug 8, 2024
df1fa9b
k folds merge
Zathimo Aug 8, 2024
7459bfd
train dans la boucle
Zathimo Aug 9, 2024
941ff4a
update de plantnet
Zathimo Aug 9, 2024
ea4d698
sΓ©paration des folds dans le logging
Zathimo Aug 9, 2024
e85835f
add jitter
LilBabines Aug 19, 2024
fdfd415
try debugg jitter
LilBabines Aug 20, 2024
9f57470
launch for distance server
Zathimo Aug 21, 2024
b2b283f
test link with Marbec Data
Zathimo Aug 21, 2024
0283864
k folds with test dataset
Zathimo Aug 21, 2024
096ca76
test new lr and fix example sentinel
Zathimo Aug 22, 2024
39adf00
random split and AdamW optimizer with scheduler
Zathimo Aug 26, 2024
75ef082
random split and DHS fold + test_split
Zathimo Aug 27, 2024
4ea51f6
scheduler CyclicLR
Zathimo Aug 27, 2024
008e0f1
PovertyDataModule inherits BaseDataModule
Zathimo Aug 29, 2024
aa75d08
export_predict_csv
Zathimo Aug 29, 2024
5061221
change metrics name (loss/val to loss_val)
Zathimo Aug 30, 2024
8bf2538
plot results for all 5 folds
Zathimo Aug 30, 2024
f2bd221
Merge branch 'refs/heads/main' into Poverty
Zathimo Sep 9, 2024
b81d9e2
correction bug merge
Zathimo Sep 9, 2024
213459d
additional documentation for PR
Zathimo Sep 11, 2024
ec35bcf
remove / in where="./"
Zathimo Sep 17, 2024
99a68ae
remove the sys path changes
Zathimo Sep 17, 2024
ef68619
swap long/lat columns in observation file
Zathimo Sep 20, 2024
2a5b635
example with no cross-val for PR
Zathimo Oct 10, 2024
1785b4e
adjusted documentation
Zathimo Oct 11, 2024
c8eb216
deleted unnecessary imports
Zathimo Oct 11, 2024
8ee2f21
Merge branch 'poverty' into PR
tlarcher Nov 8, 2024
7fe8257
change request
Zathimo Nov 12, 2024
2f47792
remove poverty example
Zathimo Nov 12, 2024
a3f2b1f
Merge branch 'plantnet:main' into PR
Zathimo Nov 13, 2024
0b087be
Updated glc24_pre_extracted pretrained weights link to address pos_we…
tlarcher Nov 14, 2024
7662e16
Updated setup.py for v2.1.1
tlarcher Nov 14, 2024
4687bf1
Merge pull request #72 from plantnet/dev
tlarcher Nov 14, 2024
8a58c3a
Update README.md
tlarcher Nov 14, 2024
1f41877
Merge branch 'dev'
tlarcher Nov 14, 2024
0d6294a
Fixed broken links in root Reamde
tlarcher Nov 15, 2024
194a18e
git push
tlarcher Nov 15, 2024
a8fd4ed
delete data.to(device)
Zathimo Nov 20, 2024
abc1004
Merge remote-tracking branch 'origin/PR' into PR
Zathimo Nov 20, 2024
a377812
Merge branch 'plantnet:main' into PR
Zathimo Nov 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ examples/benchmarks/cifar-10/outputs/*
dist/
build/

# Training / Inference outputs
outputs/

# Resources
docs/resources/Amap_logo.png
docs/resources/Malpolon_python_v2_image.png
Expand All @@ -48,4 +51,7 @@ examples/custom_train/sentinel-2a-rgbnir/test_bug_rasterio.md
# Miscellaneous
packages_malpolon.png
classes_malpolon.png
classes_yourpackage.png
classes_yourpackage.png

*.tif
landsat_tiles/
Binary file added docs/resources/angola_2015.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions examples/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
outputs

landsat_tiles
*.tif
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@

from __future__ import annotations

import os

import hydra
import pytorch_lightning as pl
from omegaconf import DictConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ trainer:
# gpus: 1 # Deprecated since pytorchlightning 1.7, removed in 2.0. Replaced by the 2 next attributes
accelerator: "gpu"
devices: 1
max_epochs: 3
max_epochs: 10
# val_check_interval: 2
check_val_every_n_epoch: 1
log_every_n_steps: 10
Expand Down Expand Up @@ -78,6 +78,6 @@ optim:
# kwargs:
# num_classes: *num_classes
multilabel_accuracy:
# callable: 'Fmetrics.classification.multilabel_accuracy'
callable: 'Fmetrics.classification.multilabel_accuracy'
kwargs:
num_labels: ${data.num_classes}
192 changes: 192 additions & 0 deletions examples/poverty/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
<a name="readme-top"></a>

# Landsat rasters example (training)

This example performs regression of the Asset Wealth Index (AWI) using a CNN on Landsat raster over Africa between 2013 and 2020.

## Data

### Sample data

The sample data used in this example consists of:
- **Satellite images**: MS (Multi-Spectral) 7 bands Landsat8 image satellite. Numerous GeoTiff files of resolution XXXm distributed across various countries, years and clusters.

<div align="center">
<figure>
<img src="../../docs/resources/angola_2015.png" width="300">
<br/>
<figcaption>Landsat8 composite patch of a village in Angola in 2015 </figcaption>
</figure>
</div>

- **Observations**: a CSV file containing all labels and corresponding data necessary for matching the GeoTiffs. The CSV file contains the following columns:
- `country`, (ex : angola, etc.)
- `year`, (2013 to 2019)
- `cluster`, cluster ID
- `lat` : latitude of the cluster,
- `lon` : longitude of the cluster,
- `households` : number of households in the cluster,
- `wealthpooled`, the poverty indicator we want to regress
- `urban_rural`, 0 if rural, 1 if urban
- `subset`, train, validation or test

The sample data is based on the Demographic and Health Surveys undertaken in Africa since 2013.


### Data loading

- **Satellite images**

The LandSat patches are looked for in the `example/poverty/dataset` directory, and they are loaded based on a `PovertyDataModule` and `MSDataset` (cf. [python file](datamodule/landsat_poverty.py) ).
They are to be downloaded beforehand in a TIF format and placed in the `dataset` directory.
The images were downloaded from the Google Earth Engine platform and preprocessed using [this method](https://github.com/mpa-poverty/2-mpa/tree/main/preprocessing).

## Usage

Examples are **ready-to-use scripts** that can be executed by a simple Python command. Every data, model and training parameters are specified in a `.yaml` configuration file located in the `config/` directory.
As stated in the previous section, the data needs to be downloaded and placed in the `dataset` directory.

### Training

To train an example's model such as `resnet18` in `cnn_on_ms_poverty.py`, run the following command:

```script
python examples/poverty/cnn_on_ms_poverty.py
```

You can also specify any of your config parameters within your command through arguments such as:

```script
python examples/poverty/cnn_on_ms_poverty.py data.dataset_path=<DATASET_PATH> trainer.gpus=1
```

Config parameters provided in this example are listed in the [Parameters](#parameters) section.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

### Prediction

This example is configured to run in training mode by default but if you want to re-use it for prediction, follow these steps:

- Change config file parameter `run.predict` to `true`
- Specify a path to your model checkpoint in parameter `run.checkpoint_path`

Note that any of these parameters can also be passed through command line like shown in the previous section and overrule those of the config file.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

### Parameters

All hyperparameters are specified in a `.yaml` configuration file located in a `config/` directory, which is read and transformed into a dictionary by the [**Hydra**](https://hydra.cc/docs/intro/) library.

You can parametrize your models and your training routine through your `.yaml` config file which is split in main sections :

- **trainer** : parameters to tweak your training session via PyTorchLightning Trainer class\
This section is passed on to your PyTorchLightning trainer.
- **run** : parameters related to prediction and transfer learning\
This section is passed on to your PyTorchLightning checkpoint loading method.
- **model** : defines which model you want to load, from which source, and contains models hyperparameters. You can pass any model hyperparameter listed in your provider's model builder.\
This section is passed on to your prediction system _(e.g. `RegressionSystem`)_.
- **optimizer** : your optimizer and metrics hyperparameters.\
This section is passed on to your prediction system _(e.g. `RegressionSystem`)_.
- **task** : defines the type of deep learning task chosen for your experiment (currently only supporting any of `['classification_binary', 'classification_multiclass', 'classification_multilabel', 'regression']`)\
This section is passed on to your prediction system _(e.g. `RegressionSystem`)_.
- **data** : data related information such as the path to your dataset or batch size.\
This section is passed on to your data module _(e.g. `PovertyDataModule`)_.

Hereafter is a detailed list of every sub parameters :

<details>
<summary><i><u>Click here to expand sub parameters</u></i></summary>

- **trainer**
- **accelerator** _(str)_ : Selects the type of hardware you want your example to run on. Either `'gpu'` or `'cpu'`.
- **devices** _(int)_ : Defines how many accelerator devices you want to use for parallelization.
- **max_epochs** _(int)_ : The maximum number of training epochs.
- **check_val_every_n_epoch** _(int)_ : Defines the interval of epochs on which validation should be performed throughout training.
- **run**
- **predict** _(bool)_ : If set to `true`, runs your example in inference mode; if set to `false`, runs your example in training mode.
- **checkpoint\_path** _(str)_ : Path to the PyTorch checkpoint you wish to load weights from either for inference mode, for resuming training or perform transfer learning.
- **model**
- **provider\_name** _(str)_ : Defines the source you want to load your models from. Models from the timm and torchvision repositories can be downloaded with or without pre-trained weights and are fully PyTorch compatible. Either `'timm'` or `'torchvision'`.
- **model\_name** _(str)_ : Name of the model you wish your provider to retrieve. For a complete list of available models, please refer to [timm's](https://timm.fast.ai/) and [torchvision's](https://pytorch.org/vision/stable/models.html) documentations.
- **model_kwargs**\
Parameters forwarded to the model constructor. You may add any parameter in this section belonging to your model's constructor. Leave empty (None) to use the model's default parameter value.
- **pretrained** _(bool)_ : If `true`, your model will be retrieved with pre-trained weights; if `false`, your model will be retrieved with no weights and training will have to be conducted from scratch.
- **num_classes** _(int)_ : Number of classes for you classification task.
- **in\_chans** _(int)_ : Number of input channels.
- **output\_stride** _(int)_ : Output stride value for CNN models. This parameter defines how much the convolution window is shifted when performing convolution.
- **global\_pool** _(str)_ : Type of global pooling. Takes any value in [`'avg'`, `'max'`, `'avgmax'`, `'catavgmax'`].
- ...
- **modifiers**\
Malpolon's modifiers you can call to modify your model's structure or behavior.
- **change_last_layer**
- **num\_outputs** _(int)_ : Number of output channels you would like your model to have instead of its default value.

- **optimizer**
- **lr** (_float)_ : Learning rate.
- **weight\_decay** _(float)_ : Model's regularization parameter that penalizes large weights. Takes any floating value in `[0, 1]`.
- **momentum** _(float)_ : Model's momentum factor which acts on the model's gradient descent by minimizing its oscillations thus accelerating the convergence and avoiding being trapped in local minimas. Takes ano floating value in `[0, 1]`.
- **nesterov** _(bool)_ : If `true`, adopts nesterov momentum; if `false`, adopts PyTorch's default strategy.
- **metrics**
- **_\<metric name\>_** : The name of your metric. Can either be a custom name or one of the keys listed in `malpolon.models.utils.FMETRICS_CALLABLES`. In the latter case, the _callable_ argument is not required.
- **callable** (optional) _(str)_ : Name of the TorchMetrics functional metric to call _(e.g.: `'torchmetrics.functional.classification.multiclass_accuracy'`)_. Find all functional metrics on the TorchMetrics documentation page such as [here](https://torchmetrics.readthedocs.io/en/stable/classification/accuracy.html#functional-interface) in the "functional Interface" section. Learn more about functional metrics [here](https://lightning.ai/docs/torchmetrics/stable/pages/quickstart.html#functional-metrics). Takes a string as input.
- **_kwargs_** (optional) : any key-value arguments compatible with the selected metric such as `num_classes` or `threshold`. See [TorchMetrics documentation](https://lightning.ai/docs/torchmetrics/stable/all-metrics.html) for the complete list of kwargs to your metric.

- **task**
- **task** _(str)_ : deep learning task to be performed. At the moment, can take any value in [`'classification_binary'`, `'classification_multiclass'`, `'classification_multilabel'`].

- **data**
- **dataset\_path** _(str)_ : path to the dataset. At the moment, patches and rasters should be directly put in this directory.
- **train\_batch\_size** _(int)_ : size of train batches.
- **inference\_batch\_size** _(int)_ : size of inference batches.
- **num\_workers** _(int)_ : number of worker processes to use for loading the data. When you set the β€œnumber of workers” parameter to a value greater than 0, the DataLoader will load data in parallel using multiple worker processes.

</details>

<p align="right">(<a href="#readme-top">back to top</a>)</p>

### Transfer learning

- **Resuming training (same model)**

To resume a training or perform transfer learning with the same model without changing its channels, update your configuration file checkpoint path, and run your script in training mode:

```yaml
run:
predict: false
checkpoint_path: <PATH_TO_CHECKPOINT>
```

A new output folder will be generated.

- **Transfer with model modifications**

Be aware that for now there are no tools provided to easily freeze or manage intermediate layers during training. Thus you may encounter challenges when trying to train a model with pre-trained weights _(e.g. from ImageNet)_ on 4-channels (or more) data like RGB-IR as most of the pre-trained models are done over 3-channels RGB images.

However, Malpolon provides methods to modify your **first** and **last** model layers. These methods are located in `malpolon.models.model_builder.py`:

- `change_first_convolutional_layer_modifier()`
- `change_last_layer_modifier()`
- `change_last_layer_to_identity_modifier()`

Furthermore to perform transfer learning with model modifications you can :
- Train from scratch by setting config hyperparameter `model.model_kwargs.pretrained` to false
- Manually change your model and use a freeze strategy before `trainer.fit` (in your main script) to only train 3 bands at once
- Restrain your trainings to 3 bands and merge several output features

Future updates will aim at making this step easier.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

## Additional notes
### Debugging

For debugging purposes, using the `trainer.fast_dev_run=true` and `hydra.job.name=test` parameters can be handy:

```bash
python cnn_on_rgb_patches.py data.dataset_path=<DATASET_PATH> trainer.gpus=1 +trainer.fast_dev_run=true +hydra.job.name=test
```

<p align="right">(<a href="#readme-top">back to top</a>)</p>
```
74 changes: 74 additions & 0 deletions examples/poverty/cnn_on_ms_poverty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""Main script to run training or inference on Poverty Marbec Dataset.

This script will run the Poverty dataset by default.

Author: Auguste Verdier <auguste.verdier@umontpellier.fr>
Isabelle Mornard <isabelle.mornard@umontpellier.fr>
"""

from __future__ import annotations

import os

import hydra
import pytorch_lightning as pl
from omegaconf import DictConfig
from pytorch_lightning.callbacks import ModelCheckpoint, LearningRateMonitor
import torch

torch.set_float32_matmul_precision('medium')
from malpolon.data.datasets import PovertyDataModule
from malpolon.logging import Summary
from malpolon.models import RegressionSystem

import warnings
from rasterio.errors import NotGeoreferencedWarning

warnings.filterwarnings("ignore", category=NotGeoreferencedWarning)


@hydra.main(version_base="1.3", config_path="config", config_name="cnn_on_ms_torchgeo_config")
def main(cfg: DictConfig) -> None:
"""Run main script used for either training or inference.

Parameters
----------
cfg : DictConfig
hydra config dictionary created from the .yaml config file
associated with this script.
"""

log_dir = hydra.core.hydra_config.HydraConfig.get().runtime.output_dir
log_dir = os.path.join(log_dir)
logger_csv = pl.loggers.CSVLogger(log_dir, name="", version="")
logger_csv.log_hyperparams(cfg)
logger_tb = pl.loggers.TensorBoardLogger(log_dir, name="tensorboard_logs", version="")
logger_tb.log_hyperparams(cfg)

datamodule = PovertyDataModule(**cfg.data, **cfg.task)
model = RegressionSystem(cfg.model, **cfg.optimizer, **cfg.task)

callbacks = [
Summary(),
ModelCheckpoint(
dirpath=log_dir,
filename="{epoch:02d}-{step}-{" + f"{next(iter(model.metrics.keys()))}_val" + ":.4f}",
monitor=f"{next(iter(model.metrics.keys()))}_val",
mode="max",
save_on_train_epoch_end=True,
save_last=True,
every_n_train_steps=10,
),
LearningRateMonitor()
]
print(cfg.trainer)
trainer = pl.Trainer(logger=[logger_csv, logger_tb], log_every_n_steps=1, callbacks=callbacks,
**cfg.trainer)

trainer.fit(model, datamodule=datamodule, ckpt_path=cfg.run.checkpoint_path)
trainer.validate(model, datamodule=datamodule)
trainer.test(model, datamodule=datamodule)


if __name__ == "__main__":
main()
53 changes: 53 additions & 0 deletions examples/poverty/config/cnn_on_ms_torchgeo_config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
hydra:
run:
dir: outputs/${hydra.job.name}/${now:%Y-%m-%d_%H-%M-%S}

run:
predict: false
checkpoint_path:

data:
num_classes: 1
dataset_path: examples/poverty/dataset/
labels_name: observations_2013+.csv
train_batch_size: 64
inference_batch_size: 64
num_workers: 8
val_split: 0.2
test_split: 0.2
dhs_folds: True

task:
task: regression

trainer:
accelerator: gpu
devices: 1
max_epochs: 30
check_val_every_n_epoch: 1

model:
provider_name: torchvision
model_name: resnet18
model_kwargs:
weights: ResNet18_Weights.DEFAULT
num_classes: null
in_chans: null
output_stride: null
global_pool: null
modifiers:
change_first_convolutional_layer:
num_input_channels: 7
change_last_layer:
num_outputs: 1

optimizer:
lr: 1.0e-04
weight_decay: 1.0e-05
momentum: 0.9
nesterov: true
metrics:
regression_R2score:
callable: Fmetrics.regression.r2_score
kwargs: null

Loading