Skip to content

Commit

Permalink
Merge pull request #90 from allenai/yawenz/landsat_public_doc
Browse files Browse the repository at this point in the history
add doc for Landsat
  • Loading branch information
yawenzzzz authored Jan 17, 2025
2 parents ebb3468 + e225d30 commit 941cd76
Show file tree
Hide file tree
Showing 37 changed files with 205 additions and 12 deletions.
4 changes: 2 additions & 2 deletions ai2_docs/landsat_vessels/model_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ Note: The evaluation metrics are reported for the two-stage model (detector + cl
---

## Model Configurations
- **Detector**: `rslearn_projects/data/landsat_vessels/config.yaml`
- **Classifier**: `rslearn_projects/landsat/recheck_landsat_labels/phase123_config.yaml`
- **Detector**: `rslearn_projects/data/landsat_vessels/config_detector.yaml`
- **Classifier**: `rslearn_projects/data/landsat_vessels/config_classifier.yaml`
- **Filters**: marine infrastructure `rslearn_projects/rslp/utils/filter.py`

---
Expand Down
6 changes: 3 additions & 3 deletions ai2_docs/landsat_vessels/train_eval.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ This detects vessels in Landsat imagery using two models:

The object detector can be trained like this:

python -m rslp.rslearn_main model fit --config data/landsat_vessels/config.yaml
python -m rslp.rslearn_main model fit --config data/landsat_vessels/config_detector.yaml

The dataset was originally labeled in siv and has been converted to rslearn dataset
using the code in `landsat/existing_dataset_to_utm/`.

The classifier can be trained like this:

python -m rslp.rslearn_main model fit --config landsat/recheck_landsat_labels/phase123_config.yaml
python -m rslp.rslearn_main model fit --config data/landsat_vessels/config_classifier.yaml

The data collection process for the classifier is described in
`landsat/recheck_landsat_labels/README.md`.
`one_off_projects/landsat/recheck_landsat_labels/README.md`.

---

Expand Down
105 changes: 105 additions & 0 deletions data/landsat_vessels/config_classifier.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
model:
class_path: rslearn.train.lightning_module.RslearnLightningModule
init_args:
model:
class_path: rslearn.models.multitask.MultiTaskModel
init_args:
encoder:
- class_path: rslearn.models.swin.Swin
init_args:
input_channels: 7
output_layers: [1, 3, 5, 7]
pretrained: true
decoders:
class:
- class_path: rslearn.models.pooling_decoder.PoolingDecoder
init_args:
in_channels: 1024
out_channels: 2
- class_path: rslearn.train.tasks.classification.ClassificationHead
lr: 0.0001
plateau_factor: 0.1
plateau_patience: 10
plateau_min_lr: 0
plateau_cooldown: 0
restore_config:
restore_path: gcs://rslearn-eai/datasets/landsat_vessel_detection/artifacts/2024-03-13-landsat-vessels/vessel02_satlas_freeze_crop512_nosatlas_b8first2/best.pth
remap_prefixes:
- ["backbone.backbone.", "encoder.0.model."]
data:
class_path: rslearn.train.data_module.RslearnDataModule
init_args:
path: gcs://rslearn-eai/datasets/landsat_vessel_detection/classifier/dataset_20240905/
inputs:
image:
data_type: "raster"
layers: ["landsat"]
bands: ["B8", "B2", "B3", "B4", "B5", "B6", "B7"]
passthrough: true
label:
data_type: "vector"
layers: ["label"]
is_target: true
task:
class_path: rslearn.train.tasks.multi_task.MultiTask
init_args:
tasks:
class:
class_path: rslearn.train.tasks.classification.ClassificationTask
init_args:
property_name: "label"
classes: ["correct", "incorrect"]
allow_invalid: true
skip_unknown_categories: true
prob_property: "prob"
positive_class: "correct"
positive_class_threshold: 0.85
input_mapping:
class:
label: "targets"
batch_size: 16
num_workers: 16
default_config:
transforms:
- class_path: rslearn.train.transforms.normalize.Normalize
init_args:
mean: 0
std: 255
- class_path: rslearn.train.transforms.pad.Pad
init_args:
mode: "center"
size: 32
- class_path: rslearn.train.transforms.flip.Flip
groups: ["selected_copy", "phase2a_completed", "phase3a_selected"]
train_config:
tags:
split: train
sampler:
class_path: rslearn.train.dataset.WeightedRandomSamplerFactory
init_args:
option_key: "weight"
num_samples: 1000
val_config:
groups: ["phase2a_completed"]
tags:
split: val
test_config:
groups: ["phase2a_completed"]
tags:
split: val
predict_config:
groups: ["classify_predict"]
skip_targets: true
trainer:
max_epochs: 64
callbacks:
- class_path: lightning.pytorch.callbacks.LearningRateMonitor
init_args:
logging_interval: "epoch"
- class_path: rslearn.train.prediction_writer.RslearnWriter
init_args:
path: gcs://rslearn-eai/datasets/landsat_vessel_detection/classifier/dataset_20240905/
output_layer: output
selector: ["class"]
rslp_project: rslearn-landsat-recheck
rslp_experiment: phase123_20240919_01_copy
File renamed without changes.
Binary file added docs/images/landsat_vessels/prediction.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 91 additions & 0 deletions docs/landsat_vessels.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
Landsat Vessel Detection
---------------------------

The Landsat vessel detection model detects ships in Landsat 8/9 scenes. We use Level-1 data since they are released with a lower latency, and latency is
important for [Skylight](https://www.skylight.global/) (which is the primary use of
this model within Ai2).

The model includes of a detector and a classifier: the detector detects ship-like objects, and the classifier refines these detections by pruning ones that it is confident are not ships. The detector is trained on a dataset consisting of 7,954 Landsat patches (ranging from 384x384 to 768x768) with 18,509 ship labels. The classifier is trained on a dataset consisting of 1,733 annotated detections, with each detection represented as a 64x64 patch centered at the position of a detected ship. See our paper for more details about the model and dataset.

<div style="text-align: center;">
<img src="./images/landsat_vessels/prediction.png"
alt="Image showing a Landsat image with predicted positions of ships from the model overlayed."
style="max-width: 60%; height: auto; margin: auto;">
</div>


Inference
---------

First, download the detector and classifier checkpoints to the `RSLP_PREFIX` directory.

cd rslearn_projects
mkdir -p project_data/projects/landsat_vessels/data_20240924_model_20240924_imagenet_patch512_flip_03/checkpoints/
wget https://storage.googleapis.com/ai2-rslearn-projects-data/landsat_vessels/detector/best.ckpt -O project_data/projects/landsat_vessels/data_20240924_model_20240924_imagenet_patch512_flip_03/checkpoints/last.ckpt

mkdir -p project_data/projects/rslearn-landsat-recheck/phase123_20240919_01_copy/checkpoints/
wget https://storage.googleapis.com/ai2-rslearn-projects-data/landsat_vessels/classifer/best.ckpt -O project_data/projects/rslearn-landsat-recheck/phase123_20240919_01_copy/checkpoints/last.ckpt

The easiest way to apply the model is using the prediction pipeline in `rslp/landsat_vessels/predict_pipeline.py`. You can download the Landsat scene files, e.g. from USGS EarthExplorer or AWS, and then create a configuration file for the prediction pipeline, here is an example:

```json
{
"image_files": {
"B2": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B2.TIF",
"B3": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B3.TIF",
"B4": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B4.TIF",
"B5": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B5.TIF",
"B6": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B6.TIF",
"B7": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B7.TIF",
"B8": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B8.TIF",
},
"scratch_path": "/home/data/scratch/",
"json_path": "/home/data/vessels.json",
"crop_path": "/home/data/crops/"
}
```

This specifies the arguments to
`rslp.landsat_vessels.predict_pipeline.predict_pipeline` via `jsonargparse`.

Now we can run the pipeline:

python -m rslp.main landsat_vessels predict --config /path/to/config.json

Here, `scratch_path` saves the rslearn dataset, `crop_path` saves the cropped RGB images centered around the detected ships, and `json_path` saves the JSON output of the detected ships, all of which are optional, depending on whether the user wants to save the intermediate results or not.

The prediction pipeline also accepts a Landsat scene ID and automatically downloads the scene images from [AWS](https://aws.amazon.com/marketplace/pp/prodview-ivr4jeq6flk7u#resources). You will need to set up your AWS account for accessing Landsat data. Use the command below to run the pipeline with scene ID:

python -m rslp.main landsat_vessels predict --scene_id LC08_L1TP_125059_20240727_20240801_02_T1


Training
--------

First, download the training dataset for detector:

cd rslearn_projects
mkdir -p project_data/datasets/landsat_vessels/
wget https://storage.googleapis.com/ai2-rslearn-projects-data/landsat_vessels/landsat_vessels_detector.tar -0 project_data/datasets/landsat_vessels_detector.tar
tar xvf project_data/datasets/landsat_vessels_detector.tar --directory project_data/datasets/landsat_vessels/

It is an rslearn dataset consisting of window folders like `windows/labels_utm/41984_2354176_f7c057a567ee40b694d0a77ea59ef81a_6359/`. Inside each window folder:

- `layers/landsat/` contains different Landsat bands used by the model.
- `layers/label/data.geojson` contains the positions of ships. These are offset from
the bounds of the window which are in `metadata.json`, so subtract the window's
bounds to get pixel coordinates relative to the image.

Use the command below to train the detector. Note that Weights & Biases is needed. You can
disable W&B with `--no_log true` but then it may be difficult to track the metrics.

python -m rslp.rslearn_main model fit --config data/landsat_vessels/config_detector.yaml --data.init_args.path project_data/datasets/landsat_vessels/dataset_20240924/

Second, download the training dataset for classifier:

wget https://storage.googleapis.com/ai2-rslearn-projects-data/landsat_vessels/landsat_vessels_classifier.tar -0 project_data/datasets/landsat_vessels_classifier.tar
tar xvf project_data/dataset/landsat_vessels_classifier.tar --directory project_data/datasets/landsat_vessels/

Use the command below to train the classifier.

python -m rslp.rslearn_main model fit --config data/landsat_vessels/config_classifier.yaml --data.init_args.path project_data/datasets/landsat_vessels/dataset_20240905/
File renamed without changes.
File renamed without changes.
File renamed without changes.
11 changes: 4 additions & 7 deletions rslp/landsat_vessels/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,9 @@
LANDSAT_LAYER_NAME = "landsat"
LANDSAT_RESOLUTION = 15

# Detector config
# Data config
LOCAL_FILES_DATASET_CONFIG = "data/landsat_vessels/predict_dataset_config.json"
AWS_DATASET_CONFIG = "data/landsat_vessels/predict_dataset_config_aws.json"
DETECT_MODEL_CONFIG = "data/landsat_vessels/config.yaml"
DETECT_MODEL_EVAL_CONFIG = (
"data/landsat_vessels/config_eval.yaml" # config for evaluation
)

# Extract Landsat bands from local config file
with open(LOCAL_FILES_DATASET_CONFIG) as f:
Expand All @@ -21,8 +17,9 @@
band["bands"][0] for band in json_data["layers"][LANDSAT_LAYER_NAME]["band_sets"]
]

# Classifier config
CLASSIFY_MODEL_CONFIG = "landsat/recheck_landsat_labels/phase123_config.yaml"
# Model config
DETECT_MODEL_CONFIG = "data/landsat_vessels/config_detector.yaml"
CLASSIFY_MODEL_CONFIG = "data/landsat_vessels/config_classifier.yaml"
CLASSIFY_WINDOW_SIZE = 64

# Filter config
Expand Down

0 comments on commit 941cd76

Please sign in to comment.