diff --git a/workshop/README.md b/workshop/README.md index 87eb52a4..01ecdff8 100644 --- a/workshop/README.md +++ b/workshop/README.md @@ -45,7 +45,12 @@ This workshop provides a complete learning path for IBM Geospatial Studio, desig - Fine-tuning models - Deploying and monitoring -**Total Workshop Time**: 4.5 - 6 hours +5. **Lab 5: Multimodal Flood Detection with TerraMind** (90-120 minutes) + - Working with multimodal satellite data (SAR + Optical) + - Training TerraMind foundation model + - Advanced multimodal inference workflows + +**Total Workshop Time**: 6 - 8 hours ## 🚀 Quick Start diff --git a/workshop/docs/index.md b/workshop/docs/index.md index d2b2fabe..ea8778cc 100644 --- a/workshop/docs/index.md +++ b/workshop/docs/index.md @@ -18,7 +18,7 @@ This workshop is designed for beginners who have never heard of Geospatial Studi ## ⏱️ Workshop Duration -**Total Time:** Approximately 3-4 hours +**Total Time:** Approximately 5-6 hours - **Pre-work:** 1-1.5 hours (deployment and setup) - **Introduction:** 15 minutes (reading) @@ -26,6 +26,7 @@ This workshop is designed for beginners who have never heard of Geospatial Studi - **Lab 2 - Onboarding Pre-computed Examples:** 20 minutes (Beginner) - **Lab 3 - Upload Model Checkpoints and Run Inference:** 30 minutes (Intermediate) - **Lab 4 - Training a Custom Model for Wildfire Burn Scar Detection:** 60-90 minutes (Intermediate, includes model training) +- **Lab 5 - Training a Multimodal Model for Flood Detection:** 90-120 minutes (Advanced, includes multimodal training) ## 🎓 Target Audience @@ -49,7 +50,7 @@ cd geospatial-studio/workshop/docs/notebooks This repository includes: -- ✅ All lab notebooks (Lab 1-4) +- ✅ All lab notebooks (Lab 1-5) - ✅ JSON configuration files (model templates, datasets, backbones) - ✅ Sample data references - ✅ Complete workshop documentation @@ -109,6 +110,13 @@ Complete an end-to-end workflow: onboard a training dataset, fine-tune a foundat **Note:** This lab requires GPU access for model training. If GPUs are not available, you can use an existing fine-tuned model or train outside Studio using TerraTorch. +### Lab 5: Training a Multimodal Model for Flood Detection with TerraMind +Advanced multimodal workflow combining Sentinel-1 SAR and Sentinel-2 optical data. Learn to work with TerraMind foundation model, configure multimodal datasets, and run inference with multiple sensor modalities for robust flood detection. + +**Time:** 90-120 minutes (includes multimodal training) | **Difficulty:** Advanced + +**Note:** This lab uses TerraMind Tiny which can run on CPU (2-4 hours) or GPU (60-90 minutes). Demonstrates real-world disaster response scenarios with complementary sensor data. + ## 🚀 Getting Started 1. **Complete the Pre-work** - Deploy Geospatial Studio in your environment diff --git a/workshop/docs/introduction/welcome.md b/workshop/docs/introduction/welcome.md index 82752123..2921e7f4 100644 --- a/workshop/docs/introduction/welcome.md +++ b/workshop/docs/introduction/welcome.md @@ -55,6 +55,7 @@ graph LR C --> D[Lab 2
Onboard Examples] D --> E[Lab 3
Upload & Infer] E --> F[Lab 4
Train Model] + F --> G[Lab 5
Multimodal AI] style A fill:#0f62fe,stroke:#fff,color:#fff style B fill:#8a3ffc,stroke:#fff,color:#fff @@ -62,6 +63,7 @@ graph LR style D fill:#42be65,stroke:#fff,color:#fff style E fill:#ff7eb6,stroke:#fff,color:#fff style F fill:#fa4d56,stroke:#fff,color:#fff + style G fill:#ee5396,stroke:#fff,color:#fff ``` ## ⏱️ Time Breakdown @@ -74,7 +76,8 @@ graph LR | **Lab 2** | 20 minutes | Onboarding Pre-computed Examples (Beginner) | | **Lab 3** | 30 minutes | Upload Model Checkpoints and Run Inference (Intermediate) | | **Lab 4** | 60-90 minutes | Training a Custom Model for Wildfire Burn Scar Detection (Intermediate) | -| **Total** | ~3-4 hours | Including breaks | +| **Lab 5** | 90-120 minutes | Training a Multimodal Model for Flood Detection (Advanced) | +| **Total** | ~5-6 hours | Including breaks | ## 🎓 Workshop Format diff --git a/workshop/docs/notebooks/README.md b/workshop/docs/notebooks/README.md index 27758a6f..50f1d785 100644 --- a/workshop/docs/notebooks/README.md +++ b/workshop/docs/notebooks/README.md @@ -65,6 +65,23 @@ Complete an end-to-end workflow: --- +### Lab 5: Training a Multimodal Model for Flood Detection with TerraMind +**File:** `lab5-flood-multimodal-workflow.ipynb` + +Advanced multimodal workflow: +- Work with multimodal satellite data (Sentinel-1 SAR + Sentinel-2 optical) +- Onboard and configure multimodal training datasets +- Register and configure TerraMind foundation model +- Submit and monitor multimodal fine-tuning +- Run inference with multiple sensor modalities +- Understand complementary sensor fusion for robust predictions + +**Estimated Time:** 90-120 minutes (includes multimodal training) | **Difficulty:** Advanced + +**Note:** Uses TerraMind Tiny which can run on CPU (2-4 hours) or GPU (60-90 minutes). Demonstrates real-world disaster response scenarios. + +--- + ## How to Use These Notebooks ### Prerequisites @@ -93,7 +110,7 @@ jupyter notebook **Why the full repository is required:** -- ✅ Notebooks reference JSON configs from `populate-studio/payloads/` +- ✅ Notebooks reference JSON configs from shared directories - ✅ Proper directory structure for all file paths - ✅ Easy to update with `git pull` - ✅ Access to all workshop materials and shared resources @@ -130,6 +147,7 @@ These notebooks are adapted from the official Geospatial Studio examples: - **Lab 2:** Based on [`002-Add-Precomputed-Examples.ipynb`](https://github.com/terrastackai/geospatial-studio-toolkit/blob/main/examples/inference/002-Add-Precomputed-Examples.ipynb) - **Lab 3:** Based on [`001-Introduction-to-Inferencing.ipynb`](https://github.com/terrastackai/geospatial-studio-toolkit/blob/main/examples/inference/001-Introduction-to-Inferencing.ipynb) - **Lab 4:** Based on [`GeospatialStudio-Walkthrough-BurnScars.ipynb`](https://github.com/terrastackai/geospatial-studio-toolkit/blob/main/examples/e2e-walkthroughs/GeospatialStudio-Walkthrough-BurnScars.ipynb) +- **Lab 5:** Based on [`GeospatialStudio-Walkthrough-Flooding.ipynb`](https://github.com/terrastackai/geospatial-studio-toolkit/blob/main/examples/e2e-walkthroughs/GeospatialStudio-Walkthrough-Flooding.ipynb) --- diff --git a/workshop/docs/notebooks/lab5-flood-multimodal-workflow.ipynb b/workshop/docs/notebooks/lab5-flood-multimodal-workflow.ipynb new file mode 100644 index 00000000..dece2954 --- /dev/null +++ b/workshop/docs/notebooks/lab5-flood-multimodal-workflow.ipynb @@ -0,0 +1,1054 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ad8926e6-99fc-4043-8bc5-49e28170749e", + "metadata": {}, + "source": [ + "# Lab 5\n", + "\n", + "**Training a Multimodal Model for Flood Detection with TerraMind**\n", + "\n", + "⏱️ **Estimated Duration:** 90-120 minutes \n", + "📊 **Difficulty Level:** Advanced\n", + "\n", + "📥 **Getting the Lab Materials**\n", + "\n", + "**Getting the Lab Materials:** Clone the repository:\n", + "```bash\n", + "git clone https://github.com/terrastackai/geospatial-studio.git\n", + "cd geospatial-studio/workshop/docs/notebooks\n", + "jupyter notebook lab5-flood-multimodal-workflow.ipynb\n", + "```\n", + "\n", + "⚠️ **Note:** This lab requires multiple JSON configuration files. Cloning the repository ensures you have all necessary files.\n", + "\n", + "---\n", + "\n", + "## Overview\n", + "\n", + "In this advanced lab, you'll complete an **end-to-end multimodal machine learning workflow** for detecting floods from satellite imagery. This represents a real-world disaster response scenario where you need to:\n", + "\n", + "1. **Onboard multimodal training data** - Upload and configure a dataset with multiple sensor modalities\n", + "2. **Register a multimodal foundation model** - Set up TerraMind for fine-tuning\n", + "3. **Submit a fine-tuning job** - Train a custom model on your multimodal dataset\n", + "4. **Monitor training progress** - Track the training process\n", + "5. **Run inference** - Test your trained model on new data\n", + "6. **Visualize results** - View predictions in the UI\n", + "\n", + "## What You'll Learn\n", + "\n", + "- How to work with multimodal satellite data (Sentinel-1 SAR + Sentinel-2 optical)\n", + "- How to onboard and configure multimodal training datasets\n", + "- How to use TerraMind, a multimodal foundation model\n", + "- How to configure and submit multimodal fine-tuning jobs\n", + "- How to run inference with multimodal models\n", + "- Best practices for multimodal geospatial AI\n", + "\n", + "## Prerequisites\n", + "\n", + "### Required Resources\n", + "\n", + "- **GPU Access**: This lab requires GPU resources for model training\n", + "- **Training Data**: Sen1Floods11 multimodal dataset (automatically downloaded)\n", + "- **Completed Labs**: Labs 1-4 (for SDK familiarity and workflow understanding)\n", + "\n", + "### About the Dataset\n", + "\n", + "We'll use the **Sen1Floods11 dataset**, a multimodal flood detection dataset:\n", + "\n", + "**Sentinel-2 (Optical) Modality:**\n", + "- **13 spectral bands** including RGB, NIR, SWIR, and cloud mask\n", + "- **10-60m resolution** depending on band\n", + "- **Modality tag**: S2L2A\n", + "\n", + "**Sentinel-1 (SAR) Modality:**\n", + "- **2 polarization bands**: VV and VH\n", + "- **10m resolution**\n", + "- **Modality tag**: S1GRD\n", + "- **Weather-independent** - works through clouds\n", + "\n", + "**Labels:**\n", + "- **Binary classification**: Flood (1) vs No Flood (0)\n", + "- **Pixel-level segmentation**\n", + "\n", + "### Why Multimodal?\n", + "\n", + "Combining optical and SAR data provides complementary information:\n", + "- **Optical (Sentinel-2)**: Rich spectral information, but affected by clouds\n", + "- **SAR (Sentinel-1)**: Penetrates clouds, sensitive to water surfaces\n", + "- **Together**: More robust and accurate flood detection\n", + "\n", + "### 💻 CPU Training Support\n", + "\n", + "**This lab uses TerraMind Tiny for CPU compatibility:**\n", + "\n", + "- **TerraMind Tiny** is the smallest version and can run on CPU\n", + "- **Training time on CPU**: Approximately 2-4 hours (vs 60-90 minutes on GPU)\n", + "- **GPU recommended** but not required for this lab\n", + "- If you have a GPU available, training will be significantly faster\n", + "- For production workloads, consider using terramind_v1_base or terramind_v1_large with GPU\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "id": "setup-section", + "metadata": {}, + "source": [ + "## 1. Setup and Imports\n", + "\n", + "First, let's import the required libraries and set up our connection to Geospatial Studio." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "2a2322ba-9fb7-47d2-bf7f-eb7f142bcd7c", + "metadata": {}, + "outputs": [], + "source": [ + "# Import required packages\n", + "import json\n", + "import time\n", + "from IPython.display import display, Markdown\n", + "\n", + "import urllib3\n", + "urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)\n", + "\n", + "from geostudio import Client" + ] + }, + { + "cell_type": "markdown", + "id": "a1f8f898-61de-4a9c-a510-16ff93cf9a1a", + "metadata": {}, + "source": [ + "## 2. Connect to Geospatial Studio\n", + "\n", + "Use the same configuration file from Lab 1:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4237a518-45d6-4dd8-ad05-6b391953b0e9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using api key and base urls from geostudio config file\n", + "Using api key and base urls from geostudio config file\n", + "Using api key and base urls from geostudio config file\n", + "✅ Connected to Geospatial Studio!\n" + ] + } + ], + "source": [ + "# Initialize the client\n", + "client = Client(geostudio_config_file=\".geostudio_config_file\")\n", + "\n", + "print(\"✅ Connected to Geospatial Studio!\")" + ] + }, + { + "cell_type": "markdown", + "id": "workflow-overview", + "metadata": {}, + "source": [ + "## 3. Understanding the Multimodal Workflow\n", + "\n", + "Before we begin, let's understand the complete multimodal workflow:\n", + "\n", + "```mermaid\n", + "graph LR\n", + " A[Multimodal Foundation Model
TerraMind] --> D[Fine-tuning Job]\n", + " B[Multimodal Training Dataset
Sentinel-1 + Sentinel-2] --> D\n", + " C[TerraMind Task Template] --> D\n", + " D --> E[Trained Multimodal Model]\n", + " E --> F[Multimodal Inference]\n", + " F --> G[Flood Detection Results]\n", + " \n", + " style A fill:#1f77b4,stroke:#333,stroke-width:2px,color:#fff\n", + " style B fill:#1f77b4,stroke:#333,stroke-width:2px,color:#fff\n", + " style C fill:#1f77b4,stroke:#333,stroke-width:2px,color:#fff\n", + " style D fill:#ff7f0e,stroke:#333,stroke-width:2px,color:#fff\n", + " style E fill:#2ca02c,stroke:#333,stroke-width:2px,color:#fff\n", + " style F fill:#d62728,stroke:#333,stroke-width:2px,color:#fff\n", + " style G fill:#9467bd,stroke:#333,stroke-width:2px,color:#fff\n", + "```\n", + "\n", + "**Key Components:**\n", + "\n", + "1. **Multimodal Foundation Model (TerraMind)**: Pre-trained model that understands multiple sensor modalities\n", + "2. **Multimodal Training Dataset**: Labeled data with both Sentinel-1 SAR and Sentinel-2 optical imagery\n", + "3. **TerraMind Task Template**: Configuration for multimodal segmentation\n", + "4. **Fine-tuning Job**: Training process that customizes the model for flood detection\n", + "5. **Trained Model**: Your custom multimodal flood detection model\n", + "6. **Multimodal Inference**: Running predictions using both sensor types\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "id": "step1-backbone", + "metadata": {}, + "source": [ + "## 4. Step 1: Register the TerraMind Foundation Model\n", + "\n", + "First, we need to register the **TerraMind** multimodal foundation model as our base model.\n", + "\n", + "**About TerraMind:**\n", + "- **Multimodal architecture**: Designed to process multiple sensor types simultaneously\n", + "- **Pre-trained**: On diverse geospatial datasets with multiple modalities\n", + "- **Versions**: Available in tiny, base, and large sizes\n", + "- **Fusion strategy**: Learns optimal ways to combine information from different sensors\n", + "\n", + "For this lab, we'll use the **terramind_v1_tiny** model, which is the smallest version and can run on CPU, making it accessible for systems without GPU resources." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "onboard-backbone", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "📋 TerraMind Backbone Configuration:\n", + "{\n", + " \"name\": \"terramind_v1_tiny\",\n", + " \"description\": \"Terramind Multimodal tiny backbone base\",\n", + " \"checkpoint_filename\": \"terramind_v1_tiny/terramind_v1_tiny.pt\",\n", + " \"model_params\": {\n", + " \"backbone\": \"terramind_v1_tiny\",\n", + " \"model_category\": \"terramind\"\n", + " }\n", + "}\n" + ] + } + ], + "source": [ + "# Load the TerraMind tiny backbone configuration\n", + "with open(\"../../../populate-studio/payloads/backbones/backbone-terramind_tiny.json\", \"r\") as f:\n", + " backbone = json.load(f)\n", + "\n", + "print(\"📋 TerraMind Backbone Configuration:\")\n", + "print(json.dumps(backbone, indent=2))" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "create-backbone", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "✅ TerraMind foundation model registered successfully!\n", + "{\n", + " \"id\": \"235d4756-4afc-487f-8cd5-5714f70f2d18\"\n", + "}\n", + "\n", + "📌 Base Model ID: 235d4756-4afc-487f-8cd5-5714f70f2d18\n" + ] + } + ], + "source": [ + "# Register the backbone model\n", + "onboard_backbone_response = client.create_base_model(backbone)\n", + "\n", + "print(\"\\n✅ TerraMind foundation model registered successfully!\")\n", + "print(json.dumps(onboard_backbone_response, indent=2))\n", + "\n", + "# Save the base model ID for later use\n", + "base_model_id = onboard_backbone_response['id']\n", + "print(f\"\\n📌 Base Model ID: {base_model_id}\")" + ] + }, + { + "cell_type": "markdown", + "id": "step2-dataset", + "metadata": {}, + "source": [ + "## 5. Step 2: Onboard the Multimodal Training Dataset\n", + "\n", + "Now we'll onboard the Sen1Floods11 multimodal dataset. This process:\n", + "\n", + "1. **Downloads** the dataset from a remote URL\n", + "2. **Validates** both modalities and their alignment\n", + "3. **Indexes** the multimodal dataset for training\n", + "4. **Stores** metadata in the Studio catalog\n", + "\n", + "**Dataset Configuration:**\n", + "\n", + "**Sentinel-2 (S2L2A) Modality:**\n", + "- **13 bands**: B01-B12 + Cloud mask (CLD)\n", + "- **File suffix**: `_S2Hand.tif`\n", + "- **RGB bands**: B02 (Blue), B03 (Green), B04 (Red)\n", + "\n", + "**Sentinel-1 (S1GRD) Modality:**\n", + "- **2 bands**: VV and VH polarizations\n", + "- **File suffix**: `_S1Hand.tif`\n", + "- **Aligned dates**: Temporal alignment with Sentinel-2\n", + "\n", + "**Labels:**\n", + "- **2 categories**: No Floods (0), Floods (1)\n", + "- **File suffix**: `_LabelHand.tif`\n", + "\n", + "⚠️ **Note**: This process may take several minutes depending on network speed and cluster resources." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "load-dataset-config", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "📋 Multimodal Dataset Configuration:\n", + "{\n", + " \"dataset_name\": \"Sentinel Flood Multimodal Test\",\n", + " \"data_sources\": [\n", + " {\n", + " \"bands\": [\n", + " {\n", + " \"index\": \"0\",\n", + " \"band_name\": \"B01\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"1\",\n", + " \"band_name\": \"B02\",\n", + " \"RGB_band\": \"B\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"2\",\n", + " \"band_name\": \"B03\",\n", + " \"RGB_band\": \"G\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"3\",\n", + " \"band_name\": \"B04\",\n", + " \"RGB_band\": \"R\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"4\",\n", + " \"band_name\": \"B05\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"5\",\n", + " \"band_name\": \"B06\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"6\",\n", + " \"band_name\": \"B07\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"7\",\n", + " \"band_name\": \"B08\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"8\",\n", + " \"band_name\": \"B8A\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"9\",\n", + " \"band_name\": \"B09\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"10\",\n", + " \"band_name\": \"B11\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"11\",\n", + " \"band_name\": \"B12\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " },\n", + " {\n", + " \"index\": \"12\",\n", + " \"band_name\": \"CLD\",\n", + " \"description\": \"\",\n", + " \"scaling_factor\": \"1\"\n", + " }\n", + " ],\n", + " \"connector\": \"sentinelhub\",\n", + " \"collection\": \"s2_l2a\",\n", + " \"modality_tag\": \"S2L2A\",\n", + " \"file_suffix\": \"_S2Hand.tif\"\n", + " },\n", + " {\n", + " \"bands\": [\n", + " {\n", + " \"index\": \"0\",\n", + " \"band_name\": \"VV\",\n", + " \"description\": \"\"\n", + " },\n", + " {\n", + " \"index\": \"1\",\n", + " \"band_name\": \"VH\",\n", + " \"description\": \"\"\n", + " }\n", + " ],\n", + " \"connector\": \"sentinelhub\",\n", + " \"collection\": \"s1_grd\",\n", + " \"modality_tag\": \"S1GRD\",\n", + " \"align_dates\": \"true\",\n", + " \"file_suffix\": \"_S1Hand.tif\",\n", + " \"scaling_factor\": [\n", + " 1,\n", + " 1\n", + " ]\n", + " }\n", + " ],\n", + " \"label_categories\": [\n", + " {\n", + " \"id\": \"0\",\n", + " \"name\": \"No Floods\",\n", + " \"description\": \"Flooding assets\"\n", + " },\n", + " {\n", + " \"id\": \"1\",\n", + " \"name\": \"Floods\",\n", + " \"description\": \"Flooding assets\"\n", + " }\n", + " ],\n", + " \"dataset_url\": \"https://geospatial-studio-example-data.s3.us-east.cloud-object-storage.appdomain.cloud/sen1floods11_v1.1.4_zip.zip\",\n", + " \"description\": \"Flood data from places\",\n", + " \"label_suffix\": \"_LabelHand.tif\",\n", + " \"purpose\": \"Segmentation\"\n", + "}\n" + ] + } + ], + "source": [ + "# Load the multimodal dataset configuration\n", + "with open(\"../../../populate-studio/payloads/datasets/dataset-flooding_multimodal.json\", \"r\") as f:\n", + " flood_dataset = json.load(f)\n", + "\n", + "print(\"📋 Multimodal Dataset Configuration:\")\n", + "print(json.dumps(flood_dataset, indent=2))" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "onboard-dataset", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "🚀 Starting multimodal dataset onboarding...\n", + "This may take several minutes to download and process both modalities.\n", + "\n", + "✅ Multimodal dataset onboarding initiated!\n", + "{\n", + " \"Dataset\": \"submitting - adding dataset and labels\",\n", + " \"dataset_id\": \"geodata-m6mjazvh82c5spfqzzvqwq\",\n", + " \"dataset_url\": \"https://geospatial-studio-example-data.s3.us-east.cloud-object-storage.appdomain.cloud/sen1floods11_v1.1.4_zip.zip\"\n", + "}\n", + "\n", + "📌 Dataset ID: geodata-m6mjazvh82c5spfqzzvqwq\n" + ] + } + ], + "source": [ + "# Onboard the multimodal dataset\n", + "print(\"🚀 Starting multimodal dataset onboarding...\")\n", + "print(\"This may take several minutes to download and process both modalities.\\n\")\n", + "\n", + "onboard_dataset_response = client.onboard_dataset(data=flood_dataset)\n", + "\n", + "print(\"✅ Multimodal dataset onboarding initiated!\")\n", + "print(json.dumps(onboard_dataset_response, indent=2))\n", + "\n", + "# Save the dataset ID for later use\n", + "dataset_id = onboard_dataset_response['dataset_id']\n", + "print(f\"\\n📌 Dataset ID: {dataset_id}\")" + ] + }, + { + "cell_type": "markdown", + "id": "monitor-dataset", + "metadata": {}, + "source": [ + "### Monitor Dataset Onboarding\n", + "\n", + "The onboarding process runs as a background job. We'll poll the status until completion.\n", + "\n", + "**What's happening:**\n", + "- Downloading multimodal dataset from remote storage\n", + "- Extracting and validating files for both modalities\n", + "- Checking temporal alignment between Sentinel-1 and Sentinel-2\n", + "- Creating dataset index\n", + "- Generating metadata\n", + "\n", + "**Expected statuses:**\n", + "- `PENDING`: Job queued\n", + "- `RUNNING`: Processing data\n", + "- `COMPLETED`: Successfully onboarded\n", + "- `FAILED`: Error occurred (check logs)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "poll-dataset-status", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "⏳ Monitoring dataset onboarding progress...\n", + "\n", + "Succeeded - 421 secondss\n", + "Attempt 1/60 - Status: Succeeded\n", + "Succeeded - 451 seconds\n", + "Attempt 2/60 - Status: Succeeded\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[31m---------------------------------------------------------------------------\u001b[39m", + "\u001b[31mKeyboardInterrupt\u001b[39m Traceback (most recent call last)", + "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[8]\u001b[39m\u001b[32m, line 23\u001b[39m\n\u001b[32m 20\u001b[39m \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[32m 22\u001b[39m attempt += \u001b[32m1\u001b[39m\n\u001b[32m---> \u001b[39m\u001b[32m23\u001b[39m \u001b[43mtime\u001b[49m\u001b[43m.\u001b[49m\u001b[43msleep\u001b[49m\u001b[43m(\u001b[49m\u001b[32;43m30\u001b[39;49m\u001b[43m)\u001b[49m \u001b[38;5;66;03m# Wait 30 seconds before next check\u001b[39;00m\n\u001b[32m 25\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m attempt >= max_attempts:\n\u001b[32m 26\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[33m\"\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[33m⚠️ Timeout: Dataset onboarding is still in progress.\u001b[39m\u001b[33m\"\u001b[39m)\n", + "\u001b[31mKeyboardInterrupt\u001b[39m: " + ] + } + ], + "source": [ + "# Poll dataset onboarding status\n", + "print(\"⏳ Monitoring dataset onboarding progress...\\n\")\n", + "\n", + "max_attempts = 60 # 30 minutes with 30-second intervals\n", + "attempt = 0\n", + "\n", + "while attempt < max_attempts:\n", + " status_response = client.poll_onboard_dataset_until_finished(dataset_id)\n", + " status = status_response.get('status', 'UNKNOWN')\n", + " \n", + " print(f\"Attempt {attempt + 1}/{max_attempts} - Status: {status}\")\n", + " \n", + " if status in ['COMPLETED', 'Succeeded']:\n", + " print(\"\\n✅ Dataset onboarding completed successfully!\")\n", + " print(json.dumps(status_response, indent=2))\n", + " break\n", + " elif status in ['FAILED', 'Failed']:\n", + " print(\"\\n❌ Dataset onboarding failed!\")\n", + " print(json.dumps(status_response, indent=2))\n", + " break\n", + " \n", + " attempt += 1\n", + " time.sleep(30) # Wait 30 seconds before next check\n", + "\n", + "if attempt >= max_attempts:\n", + " print(\"\\n⚠️ Timeout: Dataset onboarding is still in progress.\")\n", + " print(\"Check the status manually using: client.get_dataset_status(dataset_id)\")" + ] + }, + { + "cell_type": "markdown", + "id": "step3-template", + "metadata": {}, + "source": [ + "## 6. Step 3: Register the TerraMind Task Template\n", + "\n", + "Now we need to register the task template that defines how to train with TerraMind.\n", + "\n", + "The TerraMind segmentation template is specifically designed for multimodal training and includes:\n", + "- Multimodal fusion configuration\n", + "- Decoder architecture settings\n", + "- Training hyperparameters optimized for TerraMind" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "load-template", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "📋 TerraMind Segmentation Template:\n", + "Name: terramind Segmentation\n", + "Description: Terramind multimodal task for Segmantation\n", + "Purpose: Segmentation\n", + "Model Category: terramind\n" + ] + } + ], + "source": [ + "# Load the TerraMind segmentation template\n", + "with open(\"../../../populate-studio/payloads/templates/template-terramind_seg.json\", \"r\") as f:\n", + " terramind_template = json.load(f)\n", + "\n", + "print(\"📋 TerraMind Segmentation Template:\")\n", + "print(f\"Name: {terramind_template['name']}\")\n", + "print(f\"Description: {terramind_template['description']}\")\n", + "print(f\"Purpose: {terramind_template['purpose']}\")\n", + "print(f\"Model Category: {terramind_template['extra_info']['model_category']}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "create-template", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "✅ TerraMind template registered successfully!\n", + "{\n", + " \"id\": \"21932c6c-62df-408e-ba87-3f0121d29a09\"\n", + "}\n", + "\n", + "📌 Template ID: 21932c6c-62df-408e-ba87-3f0121d29a09\n" + ] + } + ], + "source": [ + "# Register the template\n", + "template_response = client.create_task(terramind_template)\n", + "\n", + "print(\"\\n✅ TerraMind template registered successfully!\")\n", + "print(json.dumps(template_response, indent=2))\n", + "\n", + "# Save the template ID for later use\n", + "tune_template_id = template_response['id']\n", + "print(f\"\\n📌 Template ID: {tune_template_id}\")" + ] + }, + { + "cell_type": "markdown", + "id": "step4-finetune", + "metadata": {}, + "source": [ + "## 7. Step 4: Submit the Fine-Tuning Job\n", + "\n", + "Now we'll submit a fine-tuning job to train our multimodal flood detection model.\n", + "\n", + "**Training Configuration:**\n", + "- **Base Model**: TerraMind v1 Tiny (CPU-compatible)\n", + "- **Dataset**: Sen1Floods11 multimodal\n", + "- **Task**: Segmentation (pixel-level flood classification)\n", + "- **Epochs**: 10 (can be adjusted)\n", + "- **Learning Rate**: 6e-5 (optimized for TerraMind)\n", + "- **Batch Size**: 2 (suitable for CPU training)\n", + "\n", + "### 💻 CPU vs GPU Training\n", + "\n", + "**CPU Training (TerraMind Tiny):**\n", + "- ✅ No GPU required\n", + "- ✅ Works on any system\n", + "- ⏱️ Slower: 2-4 hours\n", + "- 📊 Good for learning and testing\n", + "\n", + "**GPU Training (Optional):**\n", + "- ⚡ Much faster: 60-90 minutes\n", + "- 🎯 Better for production\n", + "- 💰 Requires GPU resources\n", + "\n", + "**Note:** If you have a GPU available, the same code will automatically use it for faster training." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "create-tune-payload", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "📋 Fine-tuning Configuration:\n", + "{\n", + " \"name\": \"flood-multimodal-terramind\",\n", + " \"description\": \"Multimodal flood detection model trained with TerraMind on Sen1Floods11\",\n", + " \"dataset_id\": \"geodata-m6mjazvh82c5spfqzzvqwq\",\n", + " \"base_model_id\": \"235d4756-4afc-487f-8cd5-5714f70f2d18\",\n", + " \"tune_template_id\": \"21932c6c-62df-408e-ba87-3f0121d29a09\"\n", + "}\n" + ] + } + ], + "source": [ + "# Define the fine-tuning payload\n", + "tune_payload = {\n", + " \"name\": \"flood-multimodal-terramind\",\n", + " \"description\": \"Multimodal flood detection model trained with TerraMind on Sen1Floods11\",\n", + " \"dataset_id\": dataset_id,\n", + " \"base_model_id\": base_model_id,\n", + " \"tune_template_id\": tune_template_id\n", + "}\n", + "\n", + "print(\"📋 Fine-tuning Configuration:\")\n", + "print(json.dumps(tune_payload, indent=2))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "submit-tune", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "🚀 Submitting multimodal fine-tuning job...\n", + "\n", + "✅ Fine-tuning job submitted successfully!\n", + "{\n", + " \"tune_id\": \"geotune-v7zbfsjkmmszbiqtkjlwsy\",\n", + " \"mcad_id\": \"kjob-geotune-v7zbfsjkmmszbiqtkjlwsy\",\n", + " \"status\": \"In_progress\",\n", + " \"message\": null\n", + "}\n", + "\n", + "📌 Tune ID: geotune-v7zbfsjkmmszbiqtkjlwsy\n", + "\n", + "💡 Training will take approximately 60-90 minutes.\n", + "You can monitor progress in the MLflow UI or Studio UI.\n" + ] + } + ], + "source": [ + "# Submit the fine-tuning job\n", + "print(\"🚀 Submitting multimodal fine-tuning job...\\n\")\n", + "\n", + "tune_response = client.submit_tune(tune_payload, output='json')\n", + "\n", + "print(\"✅ Fine-tuning job submitted successfully!\")\n", + "print(json.dumps(tune_response, indent=2))\n", + "\n", + "# Save the tune ID for later use\n", + "tune_id = tune_response['tune_id']\n", + "print(f\"\\n📌 Tune ID: {tune_id}\")\n", + "print(f\"\\n💡 Training will take approximately 60-90 minutes.\")\n", + "print(f\"You can monitor progress in the MLflow UI or Studio UI.\")" + ] + }, + { + "cell_type": "markdown", + "id": "monitor-training", + "metadata": {}, + "source": [ + "## 8. Step 5: Monitor Training Progress\n", + "\n", + "Training a multimodal model takes time. We'll poll the status until completion.\n", + "\n", + "**What's happening during training:**\n", + "1. **Initialization**: Loading TerraMind base model and multimodal dataset\n", + "2. **Data Loading**: Processing both Sentinel-1 and Sentinel-2 modalities\n", + "3. **Training**: Iterating through epochs, learning multimodal fusion\n", + "4. **Validation**: Evaluating performance on validation set\n", + "5. **Checkpointing**: Saving model state periodically\n", + "6. **Completion**: Finalizing and storing the trained model\n", + "\n", + "**Expected Duration:**\n", + "- **CPU (TerraMind Tiny)**: 2-4 hours\n", + "- **GPU (V100/A100)**: 60-90 minutes\n", + "- **GPU (Older)**: 90-120 minutes\n", + "\n", + "**Note:** This lab uses TerraMind Tiny which is optimized for CPU training. Training will complete successfully on CPU, just takes longer." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "poll-tune-status", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "⏳ Monitoring training progress...\n", + "\n", + "This will take approximately 60-90 minutes.\n", + "You can also monitor in the Studio UI or MLflow.\n", + "\n", + "Finished - Epoch: None - 426 secondsnds\n", + "\n", + "✅ Training completed successfully!\n", + "Your trained model 'flood-multimodal-terramind' is now available in the Model Catalog.\n" + ] + } + ], + "source": [ + "# Poll training status\n", + "print(\"⏳ Monitoring training progress...\\n\")\n", + "print(\"This will take approximately 60-90 minutes.\")\n", + "print(\"You can also monitor in the Studio UI or MLflow.\\n\")\n", + "\n", + "client.poll_finetuning_until_finished(tune_id=tune_id)\n", + "\n", + "print(\"\\n✅ Training completed successfully!\")\n", + "print(f\"Your trained model '{tune_payload['name']}' is now available in the Model Catalog.\")" + ] + }, + { + "cell_type": "markdown", + "id": "step6-inference", + "metadata": {}, + "source": [ + "## 9. Step 6: Run Multimodal Inference\n", + "\n", + "Now let's test our trained multimodal model on new data!\n", + "\n", + "**Important**: For multimodal inference, you need a location where BOTH Sentinel-1 and Sentinel-2 data are available.\n", + "\n", + "For this example, we'll configure an inference request. You'll need to provide a test area with both sensor coverages." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "create-inference-payload", + "metadata": {}, + "outputs": [], + "source": [ + "# Define the multimodal inference payload\n", + "# Note: Adjust bbox and dates for your specific test area\n", + "inference_payload = {\n", + " \"model_display_name\": \"flood-multimodal-demo\",\n", + " \"location\": \"Flood Test Area\",\n", + " \"description\": \"Multimodal flood detection test\",\n", + " \"spatial_domain\": {\n", + " \"bbox\": [], # Add bbox: [min_lon, min_lat, max_lon, max_lat]\n", + " \"urls\": [],\n", + " \"tiles\": [],\n", + " \"polygons\": []\n", + " },\n", + " \"temporal_domain\": [\"2024-01-15\"], # Adjust date\n", + " \"pipeline_steps\": [\n", + " {\"status\": \"READY\", \"process_id\": \"sentinelhub-connector\", \"step_number\": 0},\n", + " {\"status\": \"WAITING\", \"process_id\": \"terratorch-inference\", \"step_number\": 1},\n", + " {\"status\": \"WAITING\", \"process_id\": \"postprocess-generic\", \"step_number\": 2},\n", + " {\"status\": \"WAITING\", \"process_id\": \"push-to-geoserver\", \"step_number\": 3}\n", + " ],\n", + " \"model_input_data_spec\": [\n", + " {\n", + " \"bands\": [\n", + " {\"index\": \"0\", \"band_name\": \"B01\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"1\", \"band_name\": \"B02\", \"RGB_band\": \"B\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"2\", \"band_name\": \"B03\", \"RGB_band\": \"G\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"3\", \"band_name\": \"B04\", \"RGB_band\": \"R\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"4\", \"band_name\": \"B05\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"5\", \"band_name\": \"B06\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"6\", \"band_name\": \"B07\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"7\", \"band_name\": \"B08\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"8\", \"band_name\": \"B8A\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"9\", \"band_name\": \"B09\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"10\", \"band_name\": \"B11\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"11\", \"band_name\": \"B12\", \"scaling_factor\": \"1\"},\n", + " {\"index\": \"12\", \"band_name\": \"CLD\", \"scaling_factor\": \"1\"}\n", + " ],\n", + " \"connector\": \"sentinelhub\",\n", + " \"collection\": \"s2_l2a\",\n", + " \"modality_tag\": \"S2L2A\"\n", + " },\n", + " {\n", + " \"bands\": [\n", + " {\"index\": \"0\", \"band_name\": \"VV\"},\n", + " {\"index\": \"1\", \"band_name\": \"VH\"}\n", + " ],\n", + " \"connector\": \"sentinelhub\",\n", + " \"collection\": \"s1_grd\",\n", + " \"modality_tag\": \"S1GRD\",\n", + " \"align_dates\": \"true\"\n", + " }\n", + " ],\n", + " \"geoserver_push\": [\n", + " {\n", + " \"z_index\": 0,\n", + " \"workspace\": \"geofm\",\n", + " \"layer_name\": \"input_rgb\",\n", + " \"display_name\": \"Input RGB\",\n", + " \"filepath_key\": \"model_input_original_image_rgb\",\n", + " \"geoserver_style\": {\"rgb\": [\n", + " {\"label\": \"Red\", \"channel\": 1, \"maxValue\": 255, \"minValue\": 0},\n", + " {\"label\": \"Green\", \"channel\": 2, \"maxValue\": 255, \"minValue\": 0},\n", + " {\"label\": \"Blue\", \"channel\": 3, \"maxValue\": 255, \"minValue\": 0}\n", + " ]},\n", + " \"visible_by_default\": \"True\"\n", + " },\n", + " {\n", + " \"z_index\": 1,\n", + " \"workspace\": \"geofm\",\n", + " \"layer_name\": \"pred\",\n", + " \"display_name\": \"Flood Prediction\",\n", + " \"filepath_key\": \"model_output_image\",\n", + " \"geoserver_style\": {\"segmentation\": [\n", + " {\"color\": \"#000000\", \"label\": \"no-flood\", \"opacity\": 0, \"quantity\": \"0\"},\n", + " {\"color\": \"#0080FF\", \"label\": \"flood\", \"opacity\": 0.7, \"quantity\": \"1\"}\n", + " ]},\n", + " \"visible_by_default\": \"True\"\n", + " }\n", + " ]\n", + "}\n", + "\n", + "print(\"📋 Inference Configuration Ready\")\n", + "print(f\"Modalities: S2L2A + S1GRD\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "submit-inference", + "metadata": {}, + "outputs": [], + "source": [ + "# Submit the inference request\n", + "print(\"🚀 Submitting multimodal inference...\\n\")\n", + "\n", + "inference_response = client.try_out_tune(tune_id=tune_id, data=inference_payload)\n", + "\n", + "print(\"✅ Inference submitted successfully!\")\n", + "print(json.dumps(inference_response, indent=2))\n", + "\n", + "print(\"\\n💡 View results in the Studio UI under Model & Tunes > History\")" + ] + }, + { + "cell_type": "markdown", + "id": "results-section", + "metadata": {}, + "source": [ + "## 10. Viewing Results\n", + "\n", + "Your multimodal flood detection results are now available in the UI!\n", + "\n", + "**To view:**\n", + "1. Navigate to Model Catalog in Studio UI\n", + "2. Find \"flood-multimodal-terramind\"\n", + "3. Click History tab\n", + "4. View your inference on the map\n", + "\n", + "**What to observe:**\n", + "- Blue overlay shows detected floods\n", + "- Compare with RGB input\n", + "- Notice SAR helps through clouds\n", + "- Assess multimodal fusion benefits" + ] + }, + { + "cell_type": "markdown", + "id": "conclusion", + "metadata": {}, + "source": [ + "## 11. Conclusion\n", + "\n", + "Congratulations! You've successfully set up a multimodal flood detection workflow using TerraMind.\n", + "\n", + "### What You've Accomplished\n", + "\n", + "1. **Registered TerraMind**: Set up a multimodal foundation model\n", + "2. **Onboarded Multimodal Data**: Configured Sen1Floods11 dataset with Sentinel-1 and Sentinel-2\n", + "3. **Understanding**: Learned about multimodal fusion and its benefits\n", + "\n", + "### Next Steps\n", + "\n", + "To complete the full workflow:\n", + "1. Load and register the TerraMind segmentation template\n", + "2. Submit a fine-tuning job with your multimodal dataset\n", + "3. Monitor training progress (60-90 minutes)\n", + "4. Run inference on new multimodal data\n", + "5. Visualize and evaluate results\n", + "\n", + "### Key Takeaways\n", + "\n", + "- **Multimodal Advantage**: Combining SAR and optical data provides more robust predictions\n", + "- **TerraMind**: Specialized architecture for processing multiple sensor types\n", + "- **Data Alignment**: Critical to ensure temporal alignment between modalities\n", + "- **Applications**: Flood detection, disaster response, climate monitoring\n", + "\n", + "### Resources\n", + "\n", + "- **Documentation**: [Geospatial Studio Docs](https://terrastackai.github.io/geospatial-studio/)\n", + "- **SDK Reference**: [Geospatial Studio SDK](https://terrastackai.github.io/geospatial-studio-toolkit/)\n", + "- **Dataset**: [Sen1Floods11](https://github.com/cloudtostreet/Sen1Floods11)\n", + "- **Models**: [IBM Geospatial Models](https://huggingface.co/ibm-nasa-geospatial)\n", + "\n", + "---\n", + "\n", + "## 🎓 Lab Complete!\n", + "\n", + "Thank you for completing Lab 5! You've learned how to work with multimodal geospatial data and TerraMind foundation models.\n", + "\n", + "**Questions or Feedback?**\n", + "- Open an issue on [GitHub](https://github.com/terrastackai/geospatial-studio)\n", + "- Join our community discussions\n", + "\n", + "Happy mapping! 🌍🛰️🌊" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.14.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/workshop/docs/resources/faq.md b/workshop/docs/resources/faq.md index 697aefd1..ce71eab0 100644 --- a/workshop/docs/resources/faq.md +++ b/workshop/docs/resources/faq.md @@ -40,7 +40,7 @@ By completing this workshop, you will: ### How long does the workshop take? -**Total time:** 3-4 hours +**Total time:** 5-6 hours - **Pre-work (deployment):** 1-1.5 hours - **Introduction:** 15 minutes @@ -48,6 +48,7 @@ By completing this workshop, you will: - **Lab 2 (Onboarding Pre-computed Examples):** 20 minutes - **Lab 3 (Upload Model Checkpoints and Run Inference):** 30 minutes - **Lab 4 (Training a Custom Model for Wildfire Burn Scar Detection):** 60-90 minutes +- **Lab 5 (Training a Multimodal Model for Flood Detection):** 90-120 minutes You can complete labs at your own pace and take breaks as needed. diff --git a/workshop/docs/resources/next-steps.md b/workshop/docs/resources/next-steps.md index ec4f1640..1d061ce3 100644 --- a/workshop/docs/resources/next-steps.md +++ b/workshop/docs/resources/next-steps.md @@ -402,6 +402,7 @@ while True: - [Lab 2: Onboarding Pre-computed Examples](../notebooks/lab2-onboarding-examples.ipynb) - [Lab 3: Upload Model Checkpoints and Run Inference](../notebooks/lab3-running-inference.ipynb) - [Lab 4: Training a Custom Model for Wildfire Burn Scar Detection](../notebooks/lab4-burnscars-workflow.ipynb) +- [Lab 5: Training a Multimodal Model for Flood Detection](../notebooks/lab5-flood-multimodal-workflow.ipynb) ## 🚀 Your Journey Continues diff --git a/workshop/mkdocs.yml b/workshop/mkdocs.yml index 93268761..6e78bcc2 100644 --- a/workshop/mkdocs.yml +++ b/workshop/mkdocs.yml @@ -32,6 +32,7 @@ nav: - Lab 2: notebooks/lab2-onboarding-examples.ipynb - Lab 3: notebooks/lab3-running-inference.ipynb - Lab 4: notebooks/lab4-burnscars-workflow.ipynb + - Lab 5: notebooks/lab5-flood-multimodal-workflow.ipynb - Resources: - Additional Resources: resources/additional-resources.md - Troubleshooting: resources/troubleshooting.md