Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
2 changes: 0 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,3 @@
"runArgs": ["--gpus", "all", "--shm-size=8g"],
"remoteUser": "root"
}


2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ htmlcov
build/
dist/
*.egg-info
*.egg
*.egg
2 changes: 1 addition & 1 deletion .env_example
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ COMET_PROJECT_NAME="project_name"
COMET_WORKSPACE="workspace_name"
COMET_GIT_DIRECTORY="path/to/dir/"

HYDRA_FULL_ERROR=1
HYDRA_FULL_ERROR=1
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ tmp/
tests/data/toy_dataset.hdf5


# new trained model and config
trained_model_assets/LargeDataset-LidarHD-100mPatch_7cl_randlanet-Epoch_072.ckpt
trained_model_assets/LargeDataset-LidarHD-100mPatch_7cl_randlanet-Epoch_072-inference-Myria3DV3.10.0.yaml

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
# CHANGELOG
## 3.10.0
- Add config to handle 100 m x 100 m patches

- Add Focal and Lovasz Losses and config

- Add preprocessing steps during hdf5 creation as they do not change at batch selection level (for example,GridSampling will always select the same points as it is deterministic)

- Add config parameters to set model size, i.e a larger model for a larger dataset

### Not yet released
- Check that las/laz output can be read by pdal when running prediction.

- Clean mamba build to reduce Docker image size (14.6GB to 9.2GB)

### 3.9.1
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ Myria3D is a deep learning library designed with a focused scope: the multiclass
The library implements the training of 3D Segmentation neural networks, with optimized data-processing and evaluation logics at fit time. Inference on unseen, large scale point cloud is also supported.
It allows for the evaluation of single-class IoU on the full point cloud, which results in reliable model evaluation.

Myria3D is built upon [PyTorch](https://pytorch.org/). It keeps the standard data format
from [Pytorch-Geometric](https://pytorch-geometric.readthedocs.io/).
Myria3D is built upon [PyTorch](https://pytorch.org/). It keeps the standard data format
from [Pytorch-Geometric](https://pytorch-geometric.readthedocs.io/).
Its structure was bootstraped from [this code template](https://github.com/ashleve/lightning-hydra-template),
which heavily relies on [Hydra](https://hydra.cc/) and [Pytorch-Lightning](https://github.com/PyTorchLightning/pytorch-lightning) to enable flexible and rapid iterations of deep learning experiments.

Although the library can be extended with new neural network architectures or new data signatures, it makes some opiniated choices in terms of neural network architecture, data processing logics, and inference logic. Indeed, it is initially built with the [French "Lidar HD" project](https://geoservices.ign.fr/lidarhd) in mind, with the ambition to map France in 3D with 10 pulse/m² aerial Lidar by 2025. The data will be openly available, including a semantic segmentation with a minimal number of classes: ground, vegetation, buildings, vehicles, bridges, others.
Although the library can be extended with new neural network architectures or new data signatures, it makes some opiniated choices in terms of neural network architecture, data processing logics, and inference logic. Indeed, it is initially built with the [French "Lidar HD" project](https://geoservices.ign.fr/lidarhd) in mind, with the ambition to map France in 3D with 10 pulse/m² aerial Lidar by 2025. The data will be openly available, including a semantic segmentation with a minimal number of classes: ground, vegetation, buildings, vehicles, bridges, others.

> → For installation and usage, please refer to [**Documentation**](https://ignf.github.io/myria3d/).

Expand All @@ -41,4 +41,4 @@ Please cite Myria3D if it helped your own research. Here is an example BibTex en
year={2022},
note={IGN (French Mapping Agency)},
}
```
```
10 changes: 5 additions & 5 deletions configs/callbacks/default.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Override with "none" to deactivate.
# Override with "none" to deactivate.

log_code:
_target_: myria3d.callbacks.comet_callbacks.LogCode
Expand All @@ -8,15 +8,15 @@ log_logs_dir:
_target_: myria3d.callbacks.comet_callbacks.LogLogsPath

lr_monitor:
_target_: pytorch_lightning.callbacks.LearningRateMonitor
_target_: pytorch_lightning.callbacks.LearningRateMonitor
logging_interval: "step"
log_momentum: true

model_checkpoint:
_target_: pytorch_lightning.callbacks.ModelCheckpoint
monitor: "val/loss_epoch" # name of the logged metric which determines when model is improving
mode: "min" # can be "max" or "min"
save_top_k: 1 # save k best models (determined by above metric)
save_top_k: 5 # save k best models (determined by above metric)
save_last: True # additionaly always save model from last epoch
verbose: True
dirpath: "checkpoints/"
Expand All @@ -29,7 +29,7 @@ early_stopping:
mode: "min" # can be "max" or "min"
patience: 6 # how many validation epochs of not improving until training stops
min_delta: 0 # minimum change in the monitored metric needed to qualify as an improvement

model_detailed_metrics:
_target_: myria3d.callbacks.metric_callbacks.ModelMetrics
num_classes: ${model.num_classes}
num_classes: ${model.num_classes}
6 changes: 3 additions & 3 deletions configs/callbacks/finetuning.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
defaults:
- default.yaml

# Override
# Override
finetune:
_target_: myria3d.callbacks.finetuning_callbacks.FinetuningFreezeUnfreeze
d_in: ${model.d_in}
num_classes: ${model.num_classes}
unfreeze_fc_end_epoch: ??? # full end fc is unfrozen later than the last MLP.
unfreeze_decoder_train_epoch: ??? # decoder is unfrozen later than last FC layer.
unfreeze_fc_end_epoch: ??? # full end fc is unfrozen later than the last MLP.
unfreeze_decoder_train_epoch: ??? # decoder is unfrozen later than last FC layer.
8 changes: 4 additions & 4 deletions configs/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ ignore_warnings: True

# specify here default training configuration
defaults:
- _self_ # for hydra legacy reasons
- _self_ # for hydra legacy reasons

- trainer: default.yaml
- datamodule: hdf5_datamodule.yaml
- dataset_description: 20220607_151_dalles_proto.yaml # describes input features and classes
- dataset_description: 20220607_151_dalles_proto.yaml # describes input features and classes
- callbacks: default.yaml # set this to null if you don't want to use callbacks
- model: pyg_randla_net_model.yaml

- logger: comet # set logger here or use command line (e.g. `python run.py logger=wandb`)
- task: default.yaml
- predict: default.yaml

- experiment: RandLaNetDebug.yaml # default run is for debugging.
- experiment: RandLaNetDebug.yaml # default run is for debugging.

- hydra: default.yaml

Expand Down
10 changes: 6 additions & 4 deletions configs/datamodule/hdf5_datamodule.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
_target_: myria3d.pctl.datamodule.hdf5.HDF5LidarDataModule

# A standalone precomputed HDF5 dataset can be used without source files by setting data_dir and split_csv_path to null.
data_dir: null # data directory containing LAS files
data_dir: null # data directory containing LAS files
epsg: null
split_csv_path: null # csv specifying split, with schema basename, split (where split is one out of train/val/test)
hdf5_file_path: "path/to/dataset_file.hdf5" # where to create a HDF5 dataset file from LAS and CSV sources.
split_csv_path: null # csv specifying split, with schema basename, split (where split is one out of train/val/test)
hdf5_file_path: "path/to/dataset_file.hdf5" # where to create a HDF5 dataset file from LAS and CSV sources.

# functions used to load and preprocess LAS data points into a pytorch geometric Data object.
points_pre_transform:
Expand All @@ -14,7 +14,7 @@ points_pre_transform:

pre_filter:
_target_: functools.partial
_args_:
_args_:
- "${get_method:myria3d.pctl.dataset.utils.pre_filter_below_n_points}"
min_num_nodes: 1

Expand All @@ -26,6 +26,8 @@ subtile_overlap_predict: "${predict.subtile_overlap}"
batch_size: 32
num_workers: 3
prefetch_factor: 3
pin_memory: true
persistent_workers: true

defaults:
- transforms: default.yaml
1 change: 0 additions & 1 deletion configs/datamodule/transforms/augmentations/heavy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
defaults:
- light.yaml


# Rotation around axis - sample should be centered for this.
RandomRotate:
_target_: torch_geometric.transforms.RandomRotate
Expand Down
4 changes: 2 additions & 2 deletions configs/datamodule/transforms/augmentations/light.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ x_flip:
_args_:
- 0
p: 0.5

y_flip:
_target_: torch_geometric.transforms.RandomFlip
_args_:
- 1
p: 0.5
p: 0.5
5 changes: 4 additions & 1 deletion configs/datamodule/transforms/default.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defaults:
- preparations: points_budget.yaml
- preparations: points_budget_patch_100mx100m.yaml
- augmentations: none.yaml
- normalizations: default.yaml

Expand All @@ -13,4 +13,7 @@ preparations_train_list: "${oc.dict.values: datamodule.transforms.preparations.t
preparations_eval_list: "${oc.dict.values: datamodule.transforms.preparations.eval}"
preparations_predict_list: "${oc.dict.values: datamodule.transforms.preparations.predict}"

# Deterministic transforms applied once, at HDF5-creation time, for the TRAIN split only.
preparations_train_bake_list: "${oc.dict.values: datamodule.transforms.preparations.train_bake}"

normalizations_list: "${oc.dict.values: datamodule.transforms.normalizations}"
2 changes: 1 addition & 1 deletion configs/datamodule/transforms/normalizations/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ NormalizePos:
subtile_width: "${datamodule.subtile_width}"

StandardizeRGBAndIntensity:
_target_: myria3d.pctl.transforms.transforms.StandardizeRGBAndIntensity
_target_: myria3d.pctl.transforms.transforms.StandardizeRGBAndIntensity
14 changes: 8 additions & 6 deletions configs/datamodule/transforms/preparations/fixed_num_points.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# default preparations with grid sampling and random sampling.

train:

# Deterministic transforms baked into the HDF5 file once, at dataset-creation time,
# for the TRAIN split only (applied in create_hdf5). They are therefore NOT recomputed
# every epoch, which is a large speed-up on big datasets.
# NB: regenerate the HDF5 file after changing this list.
train_bake:
TargetTransform:
_target_: myria3d.pctl.transforms.transforms.TargetTransform
_args_:
Expand All @@ -16,6 +19,7 @@ train:
_args_:
- 0.25

train:
FixedPoints:
_target_: torch_geometric.transforms.FixedPoints
_args_:
Expand All @@ -27,7 +31,6 @@ train:
_target_: torch_geometric.transforms.Center

eval:

CopyFullPos:
_target_: myria3d.pctl.transforms.transforms.CopyFullPos

Expand Down Expand Up @@ -61,9 +64,8 @@ eval:

Center:
_target_: torch_geometric.transforms.Center

predict:

predict:
CopyFullPos:
_target_: myria3d.pctl.transforms.transforms.CopyFullPos

Expand All @@ -86,4 +88,4 @@ predict:
_target_: myria3d.pctl.transforms.transforms.CopySampledPos

Center:
_target_: torch_geometric.transforms.Center
_target_: torch_geometric.transforms.Center
29 changes: 19 additions & 10 deletions configs/datamodule/transforms/preparations/points_budget.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
# default preparations with grid sampling and random sampling.

train:

# Maximum number of nodes (points) kept per subtile after sampling.
# This is the ONLY value that differs between points budget variants, so it is
# exposed here as a single parameter. Override it on the CLI with:
# datamodule.transforms.preparations.max_num_nodes=120000
# or inherit this file and override just this value (see points_budget_patch_100mx100m.yaml).
max_num_nodes: 40000

# Deterministic transforms baked into the HDF5 file once, at dataset-creation time,
# for the TRAIN split only (applied in create_hdf5). They are therefore NOT recomputed
# every epoch, which is a large speed-up on big datasets.
# NB: regenerate the HDF5 file after changing this list.
train_bake:
TargetTransform:
_target_: myria3d.pctl.transforms.transforms.TargetTransform
_args_:
Expand All @@ -15,7 +25,8 @@ train:
_target_: torch_geometric.transforms.GridSampling
_args_:
- 0.25


train:
MinimumNumNodes:
_target_: myria3d.pctl.transforms.transforms.MinimumNumNodes
_args_:
Expand All @@ -24,13 +35,12 @@ train:
MaximumNumNodes:
_target_: myria3d.pctl.transforms.transforms.MaximumNumNodes
_args_:
- 40000
- ${datamodule.transforms.preparations.max_num_nodes}

Center:
_target_: torch_geometric.transforms.Center

eval:

TargetTransform:
_target_: myria3d.pctl.transforms.transforms.TargetTransform
_args_:
Expand Down Expand Up @@ -59,16 +69,15 @@ eval:
MaximumNumNodes:
_target_: myria3d.pctl.transforms.transforms.MaximumNumNodes
_args_:
- 40000
- ${datamodule.transforms.preparations.max_num_nodes}

CopySampledPos:
_target_: myria3d.pctl.transforms.transforms.CopySampledPos

Center:
_target_: torch_geometric.transforms.Center

predict:

predict:
DropPointsByClass:
_target_: myria3d.pctl.transforms.transforms.DropPointsByClass

Expand All @@ -88,10 +97,10 @@ predict:
MaximumNumNodes:
_target_: myria3d.pctl.transforms.transforms.MaximumNumNodes
_args_:
- 40000
- ${datamodule.transforms.preparations.max_num_nodes}

CopySampledPos:
_target_: myria3d.pctl.transforms.transforms.CopySampledPos

Center:
_target_: torch_geometric.transforms.Center
_target_: torch_geometric.transforms.Center
Comment thread
leavauchier marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Same preparations as points_budget.yaml, but with a larger points budget suited
# to 100m x 100m patches. It inherits everything from points_budget.yaml and only
# overrides the single value that differs between the two: max_num_nodes.
defaults:
- points_budget
- _self_

max_num_nodes: 120000
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
_convert_: all # For omegaconf struct to be converted to python dictionnaries
_convert_: all # For omegaconf struct to be converted to python dictionnaries
# classification_preprocessing_dict = {source_class_code_int: target_class_code_int},
classification_preprocessing_dict: {59: 6, 50: 1}
classification_preprocessing_dict: { 59: 6, 50: 1 }
# classification_dict = {code_int: name_str, ...} and MUST be sorted (increasing order).
classification_dict: {1: "unclassified", 2: "ground", 6: "building"}
classification_dict: { 1: "unclassified", 2: "ground", 6: "building" }

# Input and output dims of neural net are dataset dependant:
d_in: 12
num_classes: 3
num_classes: 3
Loading
Loading