rslearn 0.0.2__tar.gz → 0.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rslearn-0.0.2/rslearn.egg-info → rslearn-0.0.3}/PKG-INFO +355 -278
- rslearn-0.0.3/README.md +508 -0
- rslearn-0.0.3/pyproject.toml +106 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/config/__init__.py +2 -2
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/config/dataset.py +156 -99
- rslearn-0.0.3/rslearn/const.py +17 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/aws_landsat.py +216 -70
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/aws_open_data.py +64 -78
- rslearn-0.0.3/rslearn/data_sources/aws_sentinel1.py +142 -0
- rslearn-0.0.3/rslearn/data_sources/climate_data_store.py +303 -0
- rslearn-0.0.3/rslearn/data_sources/copernicus.py +973 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/data_source.py +2 -4
- rslearn-0.0.3/rslearn/data_sources/earthdaily.py +489 -0
- rslearn-0.0.3/rslearn/data_sources/earthdata_srtm.py +300 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/gcp_public_data.py +435 -159
- rslearn-0.0.3/rslearn/data_sources/google_earth_engine.py +637 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/local_files.py +97 -74
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/openstreetmap.py +6 -16
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/planet.py +7 -26
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/planet_basemap.py +52 -59
- rslearn-0.0.3/rslearn/data_sources/planetary_computer.py +764 -0
- rslearn-0.0.3/rslearn/data_sources/raster_source.py +23 -0
- rslearn-0.0.3/rslearn/data_sources/usda_cdl.py +206 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/usgs_landsat.py +84 -56
- rslearn-0.0.3/rslearn/data_sources/utils.py +319 -0
- rslearn-0.0.3/rslearn/data_sources/worldcereal.py +456 -0
- rslearn-0.0.3/rslearn/data_sources/worldcover.py +142 -0
- rslearn-0.0.3/rslearn/data_sources/worldpop.py +156 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/xyz_tiles.py +141 -78
- rslearn-0.0.3/rslearn/dataset/__init__.py +12 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/dataset/dataset.py +28 -3
- rslearn-0.0.3/rslearn/dataset/index.py +173 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/dataset/manage.py +129 -46
- rslearn-0.0.3/rslearn/dataset/materialize.py +591 -0
- rslearn-0.0.3/rslearn/dataset/window.py +379 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/main.py +235 -78
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/clip.py +2 -2
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/conv.py +7 -7
- rslearn-0.0.3/rslearn/models/croma.py +270 -0
- rslearn-0.0.3/rslearn/models/detr/__init__.py +5 -0
- rslearn-0.0.3/rslearn/models/detr/box_ops.py +103 -0
- rslearn-0.0.3/rslearn/models/detr/detr.py +493 -0
- rslearn-0.0.3/rslearn/models/detr/matcher.py +107 -0
- rslearn-0.0.3/rslearn/models/detr/position_encoding.py +114 -0
- rslearn-0.0.3/rslearn/models/detr/transformer.py +429 -0
- rslearn-0.0.3/rslearn/models/detr/util.py +24 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/faster_rcnn.py +8 -0
- rslearn-0.0.3/rslearn/models/module_wrapper.py +91 -0
- rslearn-0.0.3/rslearn/models/moe/distributed.py +262 -0
- rslearn-0.0.3/rslearn/models/moe/soft.py +676 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/molmo.py +2 -2
- rslearn-0.0.3/rslearn/models/multitask.py +392 -0
- rslearn-0.0.3/rslearn/models/pick_features.py +46 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/simple_time_series.py +14 -4
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/singletask.py +8 -4
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/ssl4eo_s12.py +1 -1
- rslearn-0.0.3/rslearn/models/task_embedding.py +250 -0
- rslearn-0.0.3/rslearn/models/terramind.py +219 -0
- rslearn-0.0.3/rslearn/models/trunk.py +280 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/unet.py +17 -3
- rslearn-0.0.3/rslearn/models/use_croma.py +508 -0
- rslearn-0.0.3/rslearn/py.typed +0 -0
- rslearn-0.0.3/rslearn/tile_stores/__init__.py +71 -0
- rslearn-0.0.3/rslearn/tile_stores/default.py +382 -0
- rslearn-0.0.3/rslearn/tile_stores/tile_store.py +328 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/callbacks/freeze_unfreeze.py +29 -17
- rslearn-0.0.3/rslearn/train/callbacks/gradients.py +109 -0
- rslearn-0.0.3/rslearn/train/callbacks/peft.py +116 -0
- rslearn-0.0.3/rslearn/train/data_module.py +562 -0
- rslearn-0.0.3/rslearn/train/dataset.py +1183 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/lightning_module.py +151 -45
- rslearn-0.0.3/rslearn/train/optimizer.py +31 -0
- rslearn-0.0.3/rslearn/train/prediction_writer.py +335 -0
- rslearn-0.0.3/rslearn/train/scheduler.py +62 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/tasks/classification.py +4 -4
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/tasks/detection.py +27 -22
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/tasks/multi_task.py +23 -8
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/tasks/regression.py +105 -17
- rslearn-0.0.3/rslearn/train/tasks/segmentation.py +547 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/tasks/task.py +2 -2
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/transforms/concatenate.py +3 -3
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/transforms/crop.py +2 -2
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/transforms/normalize.py +25 -5
- rslearn-0.0.3/rslearn/train/transforms/transform.py +131 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/__init__.py +0 -3
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/feature.py +1 -1
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/geometry.py +60 -5
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/get_utm_ups_crs.py +2 -3
- rslearn-0.0.3/rslearn/utils/jsonargparse.py +33 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/raster_format.py +207 -100
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/vector_format.py +142 -80
- {rslearn-0.0.2 → rslearn-0.0.3/rslearn.egg-info}/PKG-INFO +355 -278
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn.egg-info/SOURCES.txt +31 -4
- rslearn-0.0.3/rslearn.egg-info/requires.txt +49 -0
- rslearn-0.0.2/README.md +0 -447
- rslearn-0.0.2/extra_requirements.txt +0 -17
- rslearn-0.0.2/pyproject.toml +0 -50
- rslearn-0.0.2/requirements.txt +0 -15
- rslearn-0.0.2/rslearn/const.py +0 -23
- rslearn-0.0.2/rslearn/data_sources/copernicus.py +0 -188
- rslearn-0.0.2/rslearn/data_sources/google_earth_engine.py +0 -300
- rslearn-0.0.2/rslearn/data_sources/raster_source.py +0 -319
- rslearn-0.0.2/rslearn/data_sources/utils.py +0 -131
- rslearn-0.0.2/rslearn/dataset/__init__.py +0 -6
- rslearn-0.0.2/rslearn/dataset/materialize.py +0 -271
- rslearn-0.0.2/rslearn/dataset/window.py +0 -193
- rslearn-0.0.2/rslearn/models/module_wrapper.py +0 -43
- rslearn-0.0.2/rslearn/models/multitask.py +0 -65
- rslearn-0.0.2/rslearn/models/pick_features.py +0 -33
- rslearn-0.0.2/rslearn/tile_stores/__init__.py +0 -37
- rslearn-0.0.2/rslearn/tile_stores/file.py +0 -245
- rslearn-0.0.2/rslearn/tile_stores/tile_store.py +0 -236
- rslearn-0.0.2/rslearn/train/data_module.py +0 -170
- rslearn-0.0.2/rslearn/train/dataset.py +0 -680
- rslearn-0.0.2/rslearn/train/prediction_writer.py +0 -189
- rslearn-0.0.2/rslearn/train/tasks/segmentation.py +0 -233
- rslearn-0.0.2/rslearn/train/transforms/transform.py +0 -129
- rslearn-0.0.2/rslearn/utils/utils.py +0 -30
- rslearn-0.0.2/rslearn.egg-info/requires.txt +0 -33
- {rslearn-0.0.2 → rslearn-0.0.3}/LICENSE +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/__init__.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/__init__.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/geotiff.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/data_sources/vector_source.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/dataset/add_windows.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/dataset/remap.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/log_utils.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/__init__.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/fpn.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/pooling_decoder.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/registry.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/sam2_enc.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/satlaspretrain.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/swin.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/models/upsample.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/__init__.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/callbacks/__init__.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/tasks/__init__.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/transforms/__init__.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/transforms/flip.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/train/transforms/pad.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/array.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/fsspec.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/grid_index.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/mp.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/rtree_index.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/spatial_index.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/sqlite_index.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn/utils/time.py +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn.egg-info/dependency_links.txt +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn.egg-info/entry_points.txt +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/rslearn.egg-info/top_level.txt +0 -0
- {rslearn-0.0.2 → rslearn-0.0.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: rslearn
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: A library for developing remote sensing datasets and models
|
|
5
5
|
Author-email: Favyen Bastani <favyenb@allenai.org>, Yawen Zhang <yawenz@allenai.org>, Patrick Beukema <patrickb@allenai.org>, Henry Herzog <henryh@allenai.org>, Piper Wolters <piperw@allenai.org>
|
|
6
6
|
License: Apache License
|
|
@@ -205,41 +205,57 @@ License: Apache License
|
|
|
205
205
|
See the License for the specific language governing permissions and
|
|
206
206
|
limitations under the License.
|
|
207
207
|
|
|
208
|
-
Requires-Python: >=3.
|
|
208
|
+
Requires-Python: >=3.11
|
|
209
209
|
Description-Content-Type: text/markdown
|
|
210
210
|
License-File: LICENSE
|
|
211
|
-
Requires-Dist: boto3>=1.
|
|
211
|
+
Requires-Dist: boto3>=1.39
|
|
212
212
|
Requires-Dist: class_registry>=2.1
|
|
213
213
|
Requires-Dist: fiona>=1.10
|
|
214
|
-
Requires-Dist: fsspec
|
|
215
|
-
Requires-Dist:
|
|
216
|
-
Requires-Dist:
|
|
214
|
+
Requires-Dist: fsspec==2025.3.0
|
|
215
|
+
Requires-Dist: jsonargparse>=4.35.0
|
|
216
|
+
Requires-Dist: lightning>=2.5.1.post0
|
|
217
|
+
Requires-Dist: Pillow>=11.3
|
|
217
218
|
Requires-Dist: pyproj>=3.7
|
|
218
219
|
Requires-Dist: python-dateutil>=2.9
|
|
219
220
|
Requires-Dist: pytimeparse>=1.1
|
|
220
221
|
Requires-Dist: rasterio>=1.4
|
|
221
|
-
Requires-Dist: shapely>=2.
|
|
222
|
-
Requires-Dist: torch>=2.
|
|
223
|
-
Requires-Dist: torchvision>=0.
|
|
224
|
-
Requires-Dist: tqdm>=4.
|
|
225
|
-
Requires-Dist: universal_pathlib>=0.2.
|
|
222
|
+
Requires-Dist: shapely>=2.1
|
|
223
|
+
Requires-Dist: torch>=2.7.0
|
|
224
|
+
Requires-Dist: torchvision>=0.22.0
|
|
225
|
+
Requires-Dist: tqdm>=4.67
|
|
226
|
+
Requires-Dist: universal_pathlib>=0.2.6
|
|
226
227
|
Provides-Extra: extra
|
|
227
|
-
Requires-Dist: accelerate>=1.
|
|
228
|
-
Requires-Dist:
|
|
228
|
+
Requires-Dist: accelerate>=1.10; extra == "extra"
|
|
229
|
+
Requires-Dist: cdsapi>=0.7.6; extra == "extra"
|
|
230
|
+
Requires-Dist: earthdaily[platform]>=1.0.0; extra == "extra"
|
|
231
|
+
Requires-Dist: earthengine-api>=1.6.3; extra == "extra"
|
|
229
232
|
Requires-Dist: einops>=0.8; extra == "extra"
|
|
230
|
-
Requires-Dist: gcsfs
|
|
231
|
-
Requires-Dist: google-cloud-bigquery>=
|
|
233
|
+
Requires-Dist: gcsfs==2025.3.0; extra == "extra"
|
|
234
|
+
Requires-Dist: google-cloud-bigquery>=3.35; extra == "extra"
|
|
232
235
|
Requires-Dist: google-cloud-storage>=2.18; extra == "extra"
|
|
233
|
-
Requires-Dist:
|
|
234
|
-
Requires-Dist: osmium>=
|
|
235
|
-
Requires-Dist: planet>=
|
|
236
|
+
Requires-Dist: netCDF4>=1.7.2; extra == "extra"
|
|
237
|
+
Requires-Dist: osmium>=4.0.2; extra == "extra"
|
|
238
|
+
Requires-Dist: planet>=3.1; extra == "extra"
|
|
239
|
+
Requires-Dist: planetary_computer>=1.0; extra == "extra"
|
|
236
240
|
Requires-Dist: pycocotools>=2.0; extra == "extra"
|
|
237
|
-
Requires-Dist:
|
|
238
|
-
Requires-Dist:
|
|
241
|
+
Requires-Dist: pystac_client>=0.9; extra == "extra"
|
|
242
|
+
Requires-Dist: rtree>=1.4; extra == "extra"
|
|
243
|
+
Requires-Dist: s3fs==2025.3.0; extra == "extra"
|
|
239
244
|
Requires-Dist: satlaspretrain_models>=0.3; extra == "extra"
|
|
240
|
-
Requires-Dist: scipy>=1.
|
|
241
|
-
Requires-Dist:
|
|
242
|
-
Requires-Dist:
|
|
245
|
+
Requires-Dist: scipy>=1.16; extra == "extra"
|
|
246
|
+
Requires-Dist: terratorch>=1.0.2; extra == "extra"
|
|
247
|
+
Requires-Dist: transformers>=4.55; extra == "extra"
|
|
248
|
+
Requires-Dist: wandb>=0.21; extra == "extra"
|
|
249
|
+
Provides-Extra: dev
|
|
250
|
+
Requires-Dist: interrogate>=1.7.0; extra == "dev"
|
|
251
|
+
Requires-Dist: mypy<2,>=1.17.1; extra == "dev"
|
|
252
|
+
Requires-Dist: pre-commit>=4.3.0; extra == "dev"
|
|
253
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
254
|
+
Requires-Dist: pytest_httpserver; extra == "dev"
|
|
255
|
+
Requires-Dist: ruff>=0.12.9; extra == "dev"
|
|
256
|
+
Requires-Dist: pytest-dotenv; extra == "dev"
|
|
257
|
+
Requires-Dist: pytest-xdist; extra == "dev"
|
|
258
|
+
Dynamic: license-file
|
|
243
259
|
|
|
244
260
|
Overview
|
|
245
261
|
--------
|
|
@@ -259,10 +275,11 @@ rslearn helps with:
|
|
|
259
275
|
|
|
260
276
|
|
|
261
277
|
Quick links:
|
|
262
|
-
- [CoreConcepts](CoreConcepts.md) summarizes key concepts in rslearn, including
|
|
278
|
+
- [CoreConcepts](docs/CoreConcepts.md) summarizes key concepts in rslearn, including
|
|
263
279
|
datasets, windows, layers, and data sources.
|
|
264
|
-
- [Examples](Examples.md) contains more examples, including customizing different
|
|
280
|
+
- [Examples](docs/Examples.md) contains more examples, including customizing different
|
|
265
281
|
stages of rslearn with additional code.
|
|
282
|
+
- [DatasetConfig](docs/DatasetConfig.md) documents the dataset configuration file.
|
|
266
283
|
|
|
267
284
|
|
|
268
285
|
Setup
|
|
@@ -270,9 +287,33 @@ Setup
|
|
|
270
287
|
|
|
271
288
|
rslearn requires Python 3.10+ (Python 3.12 is recommended).
|
|
272
289
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
290
|
+
```
|
|
291
|
+
git clone https://github.com/allenai/rslearn.git
|
|
292
|
+
cd rslearn
|
|
293
|
+
pip install .[extra]
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
Supported Data Sources
|
|
298
|
+
----------------------
|
|
299
|
+
|
|
300
|
+
rslearn supports ingesting raster and vector data from the following data sources. Even
|
|
301
|
+
if you don't plan to train models within rslearn, you can still use it to easily
|
|
302
|
+
download, crop, and re-project data based on spatiotemporal rectangles (windows) that
|
|
303
|
+
you define. See [Examples](docs/Examples.md) and [DatasetConfig](docs/DatasetConfig.md)
|
|
304
|
+
for how to setup these data sources.
|
|
305
|
+
|
|
306
|
+
- Sentinel-1
|
|
307
|
+
- Sentinel-2 L1C and L2A
|
|
308
|
+
- Landsat 8/9 OLI-TIRS
|
|
309
|
+
- National Agriculture Imagery Program
|
|
310
|
+
- OpenStreetMap
|
|
311
|
+
- Xyz (Slippy) Tiles (e.g., Mapbox tiles)
|
|
312
|
+
- Planet Labs (PlanetScope, SkySat)
|
|
313
|
+
- ESA WorldCover 2021
|
|
314
|
+
|
|
315
|
+
rslearn can also be used to easily mosaic, crop, and re-project any sets of local
|
|
316
|
+
raster and vector files you may have.
|
|
276
317
|
|
|
277
318
|
|
|
278
319
|
Example Usage
|
|
@@ -286,28 +327,25 @@ Let's start by defining a region of interest and obtaining Sentinel-2 images. Cr
|
|
|
286
327
|
directory `/path/to/dataset` and corresponding configuration file at
|
|
287
328
|
`/path/to/dataset/config.json` as follows:
|
|
288
329
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}
|
|
330
|
+
```json
|
|
331
|
+
{
|
|
332
|
+
"layers": {
|
|
333
|
+
"sentinel2": {
|
|
334
|
+
"type": "raster",
|
|
335
|
+
"band_sets": [{
|
|
336
|
+
"dtype": "uint8",
|
|
337
|
+
"bands": ["R", "G", "B"]
|
|
338
|
+
}],
|
|
339
|
+
"data_source": {
|
|
340
|
+
"name": "rslearn.data_sources.gcp_public_data.Sentinel2",
|
|
341
|
+
"index_cache_dir": "cache/sentinel2/",
|
|
342
|
+
"sort_by": "cloud_cover",
|
|
343
|
+
"use_rtree_index": false
|
|
304
344
|
}
|
|
305
|
-
},
|
|
306
|
-
"tile_store": {
|
|
307
|
-
"name": "file",
|
|
308
|
-
"root_dir": "tiles"
|
|
309
345
|
}
|
|
310
346
|
}
|
|
347
|
+
}
|
|
348
|
+
```
|
|
311
349
|
|
|
312
350
|
Here, we have initialized an empty dataset and defined a raster layer called
|
|
313
351
|
`sentinel2`. Because it specifies a data source, it will be populated automatically. In
|
|
@@ -319,8 +357,10 @@ choosing the scenes with minimal cloud cover.
|
|
|
319
357
|
Next, let's create our spatiotemporal windows. These will correspond to training
|
|
320
358
|
examples.
|
|
321
359
|
|
|
322
|
-
|
|
323
|
-
|
|
360
|
+
```
|
|
361
|
+
export DATASET_PATH=/path/to/dataset
|
|
362
|
+
rslearn dataset add_windows --root $DATASET_PATH --group default --utm --resolution 10 --grid_size 128 --src_crs EPSG:4326 --box=-122.6901,47.2079,-121.4955,47.9403 --start 2024-06-01T00:00:00+00:00 --end 2024-08-01T00:00:00+00:00 --name seattle
|
|
363
|
+
```
|
|
324
364
|
|
|
325
365
|
This creates windows along a 128x128 grid in the specified projection (i.e.,
|
|
326
366
|
appropriate UTM zone for the location with 10 m/pixel resolution) covering the
|
|
@@ -332,9 +372,11 @@ We can now obtain the Sentinel-2 images by running prepare, ingest, and material
|
|
|
332
372
|
* Ingest: retrieve those items. This step populates the `tiles` directory within the dataset.
|
|
333
373
|
* Materialize: crop/mosaic the items to align with the windows. This populates the `layers` folder in each window directory.
|
|
334
374
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
375
|
+
```
|
|
376
|
+
rslearn dataset prepare --root $DATASET_PATH --workers 32 --batch-size 8
|
|
377
|
+
rslearn dataset ingest --root $DATASET_PATH --workers 32 --no-use-initial-job --jobs-per-process 1
|
|
378
|
+
rslearn dataset materialize --root $DATASET_PATH --workers 32 --no-use-initial-job
|
|
379
|
+
```
|
|
338
380
|
|
|
339
381
|
For ingestion, you may need to reduce the number of workers depending on the available
|
|
340
382
|
memory on your system.
|
|
@@ -342,32 +384,36 @@ memory on your system.
|
|
|
342
384
|
You should now be able to open the GeoTIFF images. Let's find the window that
|
|
343
385
|
corresponds to downtown Seattle:
|
|
344
386
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
387
|
+
```python
|
|
388
|
+
import shapely
|
|
389
|
+
from rslearn.const import WGS84_PROJECTION
|
|
390
|
+
from rslearn.dataset import Dataset
|
|
391
|
+
from rslearn.utils import Projection, STGeometry
|
|
392
|
+
from upath import UPath
|
|
393
|
+
|
|
394
|
+
# Define longitude and latitude for downtown Seattle.
|
|
395
|
+
downtown_seattle = shapely.Point(-122.333, 47.606)
|
|
396
|
+
|
|
397
|
+
# Iterate over the windows and find the closest one.
|
|
398
|
+
dataset = Dataset(path=UPath("/path/to/dataset"))
|
|
399
|
+
best_window_name = None
|
|
400
|
+
best_distance = None
|
|
401
|
+
for window in dataset.load_windows(workers=32):
|
|
402
|
+
shp = window.get_geometry().to_projection(WGS84_PROJECTION).shp
|
|
403
|
+
distance = shp.distance(downtown_seattle)
|
|
404
|
+
if best_distance is None or distance < best_distance:
|
|
405
|
+
best_window_name = window.name
|
|
406
|
+
best_distance = distance
|
|
407
|
+
|
|
408
|
+
print(best_window_name)
|
|
409
|
+
```
|
|
366
410
|
|
|
367
411
|
It should be `seattle_54912_-527360`, so let's open it in qgis (or your favorite GIS
|
|
368
412
|
software):
|
|
369
413
|
|
|
370
|
-
|
|
414
|
+
```
|
|
415
|
+
qgis $DATASET_PATH/windows/default/seattle_54912_-527360/layers/sentinel2/R_G_B/geotiff.tif
|
|
416
|
+
```
|
|
371
417
|
|
|
372
418
|
|
|
373
419
|
### Adding Land Cover Labels
|
|
@@ -377,152 +423,164 @@ the ESA WorldCover land cover map as labels.
|
|
|
377
423
|
|
|
378
424
|
Start by downloading the WorldCover data from https://worldcover2021.esa.int
|
|
379
425
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
426
|
+
```
|
|
427
|
+
wget https://worldcover2021.esa.int/data/archive/ESA_WorldCover_10m_2021_v200_60deg_macrotile_N30W180.zip
|
|
428
|
+
mkdir world_cover_tifs
|
|
429
|
+
unzip ESA_WorldCover_10m_2021_v200_60deg_macrotile_N30W180.zip -d world_cover_tifs/
|
|
430
|
+
```
|
|
383
431
|
|
|
384
432
|
It would require some work to write a script to re-project and crop these GeoTIFFs so
|
|
385
433
|
that they align with the windows we have previously defined (and the Sentinel-2 images
|
|
386
434
|
we have already ingested). We can use the LocalFiles data source to have rslearn
|
|
387
435
|
automate this process. Update the dataset `config.json` with a new layer:
|
|
388
436
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
"worldcover": {
|
|
394
|
-
"type": "raster",
|
|
395
|
-
"band_sets": [{
|
|
396
|
-
"dtype": "uint8",
|
|
397
|
-
"bands": ["B1"]
|
|
398
|
-
}],
|
|
399
|
-
"resampling_method": "nearest",
|
|
400
|
-
"data_source": {
|
|
401
|
-
"name": "rslearn.data_sources.local_files.LocalFiles",
|
|
402
|
-
"src_dir": "file:///path/to/world_cover_tifs/"
|
|
403
|
-
}
|
|
404
|
-
}
|
|
437
|
+
```json
|
|
438
|
+
"layers": {
|
|
439
|
+
"sentinel2": {
|
|
440
|
+
...
|
|
405
441
|
},
|
|
406
|
-
|
|
442
|
+
"worldcover": {
|
|
443
|
+
"type": "raster",
|
|
444
|
+
"band_sets": [{
|
|
445
|
+
"dtype": "uint8",
|
|
446
|
+
"bands": ["B1"]
|
|
447
|
+
}],
|
|
448
|
+
"resampling_method": "nearest",
|
|
449
|
+
"data_source": {
|
|
450
|
+
"name": "rslearn.data_sources.local_files.LocalFiles",
|
|
451
|
+
"src_dir": "file:///path/to/world_cover_tifs/"
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
...
|
|
456
|
+
```
|
|
407
457
|
|
|
408
458
|
Repeat the materialize process so we populate the data for this new layer:
|
|
409
459
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
460
|
+
```
|
|
461
|
+
rslearn dataset prepare --root $DATASET_PATH --workers 32 --batch-size 8
|
|
462
|
+
rslearn dataset ingest --root $DATASET_PATH --workers 32 --no-use-initial-job --jobs-per-process 1
|
|
463
|
+
rslearn dataset materialize --root $DATASET_PATH --workers 32 --no-use-initial-job
|
|
464
|
+
```
|
|
413
465
|
|
|
414
466
|
We can visualize both the GeoTIFFs together in qgis:
|
|
415
467
|
|
|
416
|
-
|
|
468
|
+
```
|
|
469
|
+
qgis $DATASET_PATH/windows/default/seattle_54912_-527360/layers/*/*/geotiff.tif
|
|
470
|
+
```
|
|
417
471
|
|
|
418
472
|
|
|
419
473
|
### Training a Model
|
|
420
474
|
|
|
421
475
|
Create a model configuration file `land_cover_model.yaml`:
|
|
422
476
|
|
|
477
|
+
```yaml
|
|
478
|
+
model:
|
|
479
|
+
class_path: rslearn.train.lightning_module.RslearnLightningModule
|
|
480
|
+
init_args:
|
|
481
|
+
# This part defines the model architecture.
|
|
482
|
+
# Essentially we apply the SatlasPretrain Sentinel-2 backbone with a UNet decoder
|
|
483
|
+
# that terminates at a segmentation prediction head.
|
|
484
|
+
# The backbone outputs four feature maps at different scales, and the UNet uses
|
|
485
|
+
# these to compute a feature map at the input scale.
|
|
486
|
+
# Finally the segmentation head applies per-pixel softmax to compute the land
|
|
487
|
+
# cover class.
|
|
423
488
|
model:
|
|
424
|
-
class_path: rslearn.
|
|
489
|
+
class_path: rslearn.models.singletask.SingleTaskModel
|
|
425
490
|
init_args:
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
491
|
+
encoder:
|
|
492
|
+
- class_path: rslearn.models.satlaspretrain.SatlasPretrain
|
|
493
|
+
init_args:
|
|
494
|
+
model_identifier: "Sentinel2_SwinB_SI_RGB"
|
|
495
|
+
decoder:
|
|
496
|
+
- class_path: rslearn.models.unet.UNetDecoder
|
|
497
|
+
init_args:
|
|
498
|
+
in_channels: [[4, 128], [8, 256], [16, 512], [32, 1024]]
|
|
499
|
+
# We use 101 classes because the WorldCover classes are 10, 20, 30, 40
|
|
500
|
+
# 50, 60, 70, 80, 90, 95, 100.
|
|
501
|
+
# We could process the GeoTIFFs to collapse them to 0-10 (the 11 actual
|
|
502
|
+
# classes) but the model will quickly learn that the intermediate
|
|
503
|
+
# values are never used.
|
|
504
|
+
out_channels: 101
|
|
505
|
+
conv_layers_per_resolution: 2
|
|
506
|
+
- class_path: rslearn.train.tasks.segmentation.SegmentationHead
|
|
507
|
+
# Remaining parameters in RslearnLightningModule define different aspects of the
|
|
508
|
+
# training process like initial learning rate.
|
|
509
|
+
lr: 0.0001
|
|
510
|
+
data:
|
|
511
|
+
class_path: rslearn.train.data_module.RslearnDataModule
|
|
512
|
+
init_args:
|
|
513
|
+
# Replace this with the dataset path.
|
|
514
|
+
path: /path/to/dataset/
|
|
515
|
+
# This defines the layers that should be read for each window.
|
|
516
|
+
# The key ("image" / "targets") is what the data will be called in the model,
|
|
517
|
+
# while the layers option specifies which layers will be read.
|
|
518
|
+
inputs:
|
|
519
|
+
image:
|
|
520
|
+
data_type: "raster"
|
|
521
|
+
layers: ["sentinel2"]
|
|
522
|
+
bands: ["R", "G", "B"]
|
|
523
|
+
passthrough: true
|
|
524
|
+
targets:
|
|
525
|
+
data_type: "raster"
|
|
526
|
+
layers: ["worldcover"]
|
|
527
|
+
bands: ["B1"]
|
|
528
|
+
is_target: true
|
|
529
|
+
task:
|
|
530
|
+
# Train for semantic segmentation.
|
|
531
|
+
# The remap option is only used when visualizing outputs during testing.
|
|
532
|
+
class_path: rslearn.train.tasks.segmentation.SegmentationTask
|
|
457
533
|
init_args:
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
data_type: "raster"
|
|
471
|
-
layers: ["worldcover"]
|
|
472
|
-
bands: ["B1"]
|
|
473
|
-
is_target: true
|
|
474
|
-
task:
|
|
475
|
-
# Train for semantic segmentation.
|
|
476
|
-
# The remap option is only used when visualizing outputs during testing.
|
|
477
|
-
class_path: rslearn.train.tasks.segmentation.SegmentationTask
|
|
534
|
+
num_classes: 101
|
|
535
|
+
remap_values: [[0, 1], [0, 255]]
|
|
536
|
+
batch_size: 8
|
|
537
|
+
num_workers: 32
|
|
538
|
+
# These define different options for different phases/splits, like training,
|
|
539
|
+
# validation, and testing.
|
|
540
|
+
# Here we use the same transform across splits except training where we add a
|
|
541
|
+
# flipping augmentation.
|
|
542
|
+
# For now we are using the same windows for training and validation.
|
|
543
|
+
default_config:
|
|
544
|
+
transforms:
|
|
545
|
+
- class_path: rslearn.train.transforms.normalize.Normalize
|
|
478
546
|
init_args:
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
default_config:
|
|
489
|
-
transforms:
|
|
490
|
-
- class_path: rslearn.train.transforms.normalize.Normalize
|
|
491
|
-
init_args:
|
|
492
|
-
mean: 0
|
|
493
|
-
std: 255
|
|
494
|
-
train_config:
|
|
495
|
-
transforms:
|
|
496
|
-
- class_path: rslearn.train.transforms.normalize.Normalize
|
|
497
|
-
init_args:
|
|
498
|
-
mean: 0
|
|
499
|
-
std: 255
|
|
500
|
-
- class_path: rslearn.train.transforms.flip.Flip
|
|
501
|
-
init_args:
|
|
502
|
-
image_selectors: ["image", "target/classes", "target/valid"]
|
|
503
|
-
groups: ["default"]
|
|
504
|
-
val_config:
|
|
505
|
-
groups: ["default"]
|
|
506
|
-
test_config:
|
|
507
|
-
groups: ["default"]
|
|
508
|
-
predict_config:
|
|
509
|
-
groups: ["predict"]
|
|
510
|
-
load_all_patches: true
|
|
511
|
-
skip_targets: true
|
|
512
|
-
patch_size: 512
|
|
513
|
-
trainer:
|
|
514
|
-
max_epochs: 10
|
|
515
|
-
callbacks:
|
|
516
|
-
- class_path: lightning.pytorch.callbacks.ModelCheckpoint
|
|
547
|
+
mean: 0
|
|
548
|
+
std: 255
|
|
549
|
+
train_config:
|
|
550
|
+
transforms:
|
|
551
|
+
- class_path: rslearn.train.transforms.normalize.Normalize
|
|
552
|
+
init_args:
|
|
553
|
+
mean: 0
|
|
554
|
+
std: 255
|
|
555
|
+
- class_path: rslearn.train.transforms.flip.Flip
|
|
517
556
|
init_args:
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
557
|
+
image_selectors: ["image", "target/classes", "target/valid"]
|
|
558
|
+
groups: ["default"]
|
|
559
|
+
val_config:
|
|
560
|
+
groups: ["default"]
|
|
561
|
+
test_config:
|
|
562
|
+
groups: ["default"]
|
|
563
|
+
predict_config:
|
|
564
|
+
groups: ["predict"]
|
|
565
|
+
load_all_patches: true
|
|
566
|
+
skip_targets: true
|
|
567
|
+
patch_size: 512
|
|
568
|
+
trainer:
|
|
569
|
+
max_epochs: 10
|
|
570
|
+
callbacks:
|
|
571
|
+
- class_path: lightning.pytorch.callbacks.ModelCheckpoint
|
|
572
|
+
init_args:
|
|
573
|
+
save_top_k: 1
|
|
574
|
+
save_last: true
|
|
575
|
+
monitor: val_accuracy
|
|
576
|
+
mode: max
|
|
577
|
+
```
|
|
522
578
|
|
|
523
579
|
Now we can train the model:
|
|
524
580
|
|
|
525
|
-
|
|
581
|
+
```
|
|
582
|
+
rslearn model fit --config land_cover_model.yaml
|
|
583
|
+
```
|
|
526
584
|
|
|
527
585
|
|
|
528
586
|
### Apply the Model
|
|
@@ -533,22 +591,26 @@ windows along a grid, we just create one big window. This is because we are just
|
|
|
533
591
|
to run the prediction over the whole window rather than use different windows as
|
|
534
592
|
different training examples.
|
|
535
593
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
594
|
+
```
|
|
595
|
+
rslearn dataset add_windows --root $DATASET_PATH --group predict --utm --resolution 10 --src_crs EPSG:4326 --box=-122.712,45.477,-122.621,45.549 --start 2024-06-01T00:00:00+00:00 --end 2024-08-01T00:00:00+00:00 --name portland
|
|
596
|
+
rslearn dataset prepare --root $DATASET_PATH --workers 32 --batch-size 8
|
|
597
|
+
rslearn dataset ingest --root $DATASET_PATH --workers 32 --no-use-initial-job --jobs-per-process 1
|
|
598
|
+
rslearn dataset materialize --root $DATASET_PATH --workers 32 --no-use-initial-job
|
|
599
|
+
```
|
|
540
600
|
|
|
541
601
|
We also need to add an RslearnPredictionWriter to the trainer callbacks in the model
|
|
542
602
|
configuration file, as it will handle writing the outputs from the model to a GeoTIFF.
|
|
543
603
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
604
|
+
```yaml
|
|
605
|
+
trainer:
|
|
606
|
+
callbacks:
|
|
607
|
+
- class_path: lightning.pytorch.callbacks.ModelCheckpoint
|
|
608
|
+
...
|
|
609
|
+
- class_path: rslearn.train.prediction_writer.RslearnWriter
|
|
610
|
+
init_args:
|
|
611
|
+
path: /path/to/dataset/
|
|
612
|
+
output_layer: output
|
|
613
|
+
```
|
|
552
614
|
|
|
553
615
|
Because of our `predict_config`, when we run `model predict` it will apply the model on
|
|
554
616
|
windows in the "predict" group, which is where we added the Portland window.
|
|
@@ -556,39 +618,46 @@ windows in the "predict" group, which is where we added the Portland window.
|
|
|
556
618
|
And it will be written in a new output_layer called "output". But we have to update the
|
|
557
619
|
dataset configuration so it specifies the layer:
|
|
558
620
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
},
|
|
567
|
-
"output": {
|
|
568
|
-
"type": "raster",
|
|
569
|
-
"band_sets": [{
|
|
570
|
-
"dtype": "uint8",
|
|
571
|
-
"bands": ["output"]
|
|
572
|
-
}]
|
|
573
|
-
}
|
|
621
|
+
```json
|
|
622
|
+
"layers": {
|
|
623
|
+
"sentinel2": {
|
|
624
|
+
...
|
|
625
|
+
},
|
|
626
|
+
"worldcover": {
|
|
627
|
+
...
|
|
574
628
|
},
|
|
629
|
+
"output": {
|
|
630
|
+
"type": "raster",
|
|
631
|
+
"band_sets": [{
|
|
632
|
+
"dtype": "uint8",
|
|
633
|
+
"bands": ["output"]
|
|
634
|
+
}]
|
|
635
|
+
}
|
|
636
|
+
},
|
|
637
|
+
```
|
|
575
638
|
|
|
576
639
|
Now we can apply the model:
|
|
577
640
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
641
|
+
```
|
|
642
|
+
# Find model checkpoint in lightning_logs dir.
|
|
643
|
+
ls lightning_logs/*/checkpoints/last.ckpt
|
|
644
|
+
rslearn model predict --config land_cover_model.yaml --ckpt_path lightning_logs/version_0/checkpoints/last.ckpt
|
|
645
|
+
```
|
|
581
646
|
|
|
582
647
|
And visualize the Sentinel-2 image and output in qgis:
|
|
583
648
|
|
|
584
|
-
|
|
649
|
+
```
|
|
650
|
+
qgis $DATASET_PATH/windows/predict/portland/layers/*/*/geotiff.tif
|
|
651
|
+
```
|
|
585
652
|
|
|
586
653
|
|
|
587
654
|
### Defining Train and Validation Splits
|
|
588
655
|
|
|
589
656
|
We can visualize the logged metrics using Tensorboard:
|
|
590
657
|
|
|
591
|
-
|
|
658
|
+
```
|
|
659
|
+
tensorboard --logdir=lightning_logs/
|
|
660
|
+
```
|
|
592
661
|
|
|
593
662
|
However, because our training and validation data are identical, the validation metrics
|
|
594
663
|
are not meaningful.
|
|
@@ -602,57 +671,61 @@ We will use the second approach. The script below sets a "split" key in the opti
|
|
|
602
671
|
dict (which is stored in each window's `metadata.json` file) to "train" or "val"
|
|
603
672
|
based on the SHA-256 hash of the window name.
|
|
604
673
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
674
|
+
```python
|
|
675
|
+
import hashlib
|
|
676
|
+
import tqdm
|
|
677
|
+
from rslearn.dataset import Dataset, Window
|
|
678
|
+
from upath import UPath
|
|
679
|
+
|
|
680
|
+
ds_path = UPath("/path/to/dataset/")
|
|
681
|
+
dataset = Dataset(ds_path)
|
|
682
|
+
windows = dataset.load_windows(show_progress=True, workers=32)
|
|
683
|
+
for window in tqdm.tqdm(windows):
|
|
684
|
+
if hashlib.sha256(window.name.encode()).hexdigest()[0] in ["0", "1"]:
|
|
685
|
+
split = "val"
|
|
686
|
+
else:
|
|
687
|
+
split = "train"
|
|
688
|
+
if "split" in window.options and window.options["split"] == split:
|
|
689
|
+
continue
|
|
690
|
+
window.options["split"] = split
|
|
691
|
+
window.save()
|
|
692
|
+
```
|
|
622
693
|
|
|
623
694
|
Now we can update the model configuration file to use these splits:
|
|
624
695
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
696
|
+
```yaml
|
|
697
|
+
default_config:
|
|
698
|
+
transforms:
|
|
699
|
+
- class_path: rslearn.train.transforms.normalize.Normalize
|
|
700
|
+
init_args:
|
|
701
|
+
mean: 0
|
|
702
|
+
std: 255
|
|
703
|
+
train_config:
|
|
704
|
+
transforms:
|
|
705
|
+
- class_path: rslearn.train.transforms.normalize.Normalize
|
|
706
|
+
init_args:
|
|
707
|
+
mean: 0
|
|
708
|
+
std: 255
|
|
709
|
+
- class_path: rslearn.train.transforms.flip.Flip
|
|
710
|
+
init_args:
|
|
711
|
+
image_selectors: ["image", "target/classes", "target/valid"]
|
|
712
|
+
groups: ["default"]
|
|
713
|
+
tags:
|
|
714
|
+
split: train
|
|
715
|
+
val_config:
|
|
716
|
+
groups: ["default"]
|
|
717
|
+
tags:
|
|
718
|
+
split: val
|
|
719
|
+
test_config:
|
|
720
|
+
groups: ["default"]
|
|
721
|
+
tags:
|
|
722
|
+
split: val
|
|
723
|
+
predict_config:
|
|
724
|
+
groups: ["predict"]
|
|
725
|
+
load_all_patches: true
|
|
726
|
+
skip_targets: true
|
|
727
|
+
patch_size: 512
|
|
728
|
+
```
|
|
656
729
|
|
|
657
730
|
The `tags` option that we are adding here tells rslearn to only load windows with a
|
|
658
731
|
matching key and value in the window options.
|
|
@@ -660,13 +733,17 @@ matching key and value in the window options.
|
|
|
660
733
|
Previously when we run `model fit`, it should show the same number of windows for
|
|
661
734
|
training and validation:
|
|
662
735
|
|
|
663
|
-
|
|
664
|
-
|
|
736
|
+
```
|
|
737
|
+
got 4752 examples in split train
|
|
738
|
+
got 4752 examples in split val
|
|
739
|
+
```
|
|
665
740
|
|
|
666
741
|
With the updates, it should show different numbers like this:
|
|
667
742
|
|
|
668
|
-
|
|
669
|
-
|
|
743
|
+
```
|
|
744
|
+
got 4167 examples in split train
|
|
745
|
+
got 585 examples in split val
|
|
746
|
+
```
|
|
670
747
|
|
|
671
748
|
|
|
672
749
|
### Visualizing with `model test`
|