Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

GeoAI with scikit-learn: Supervised Land Cover Classification

GeoAI with scikit-learn: Supervised Land Cover Classification

1. Introduction

Geospatial Artificial Intelligence (GeoAI) refers to the integration of machine learning techniques with spatial data. In practice, this means using algorithms to discover patterns, make predictions, or classify geographic phenomena from remotely sensed imagery and other spatial datasets.

In this notebook, we will build a complete supervised land cover classification workflow using a Sentinel-2 composite image and labeled training polygons. Rather than relying on specialized GeoAI libraries, we will use scikit-learn, a general-purpose machine learning library.

This approach is intentional. It allows us to clearly understand what happens under the hood when we apply machine learning to raster data.


2. Why Use scikit-learn for GeoAI?

scikit-learn is one of the most widely used machine learning libraries in Python. Although it is not inherently spatial, it becomes extremely powerful once we transform raster data into tabular form.

In other words:

  • A raster image becomes a matrix of features (spectral bands).

  • Training polygons provide class labels.

  • Machine learning models learn the relationship between spectral signatures and land cover types.

This transformation—from spatial raster to feature matrix—is the core idea behind many GeoAI workflows.

By using scikit-learn, we emphasize:

  • Conceptual clarity

  • Reproducibility

  • Model transparency

  • Strong evaluation practices


3. Dataset Overview

We will use two datasets:

1. Sentinel-2 Composite Image data/S2_JFM_2025.tif A multispectral composite covering January–March 2025.

Each pixel contains multiple spectral bands. These bands will serve as our predictive features.

2. Training Polygons data/training_polygons.shp A set of labeled polygons representing different land cover classes.

These polygons define the ground truth used to train our model.


4. Learning Objective

By the end of this notebook, you will be able to:

  • Convert raster data into a machine-learning-ready format

  • Extract training samples from labeled polygons

  • Train a supervised classification model

  • Evaluate model performance

  • Generate a classified land cover map

This notebook demonstrates the complete GeoAI pipeline:

Raster → Feature Matrix → Model Training → Evaluation → Full Image Prediction

Understanding this workflow is fundamental to applying machine learning in remote sensing and geospatial analysis.

5. From Raster Data to Machine Learning Features

Machine learning models in scikit-learn expect data in tabular form:

  • Rows represent samples

  • Columns represent features

However, raster data is not tabular. It is spatial.

A multispectral raster image can be thought of as a 3D array:

(height × width × bands)

Each pixel contains multiple spectral values, one for each band. For example, a Sentinel-2 image may contain:

  • Blue

  • Green

  • Red

  • Near Infrared (NIR)

  • Other spectral bands

From a machine learning perspective, each pixel can be treated as one observation (one sample), and each band becomes a feature.

This means we must transform the raster into a 2D feature matrix:

(number_of_pixels × number_of_bands)

In other words:

Every pixel → one row Every spectral band → one column

This transformation removes spatial structure temporarily so that a machine learning model can process the data.


What About Labels?

Supervised learning requires labels.

In our case, labels come from the training polygons. These polygons define known land cover types.

For pixels that fall inside a labeled polygon:

  • We extract their spectral values (features)

  • We assign the polygon’s land cover class (label)

This produces:

X → Feature matrix (spectral values) y → Label vector (land cover class)

The model then learns the relationship between spectral signatures and land cover categories.


Important Note on Spatial Context

At this stage, we are treating pixels independently. The model does not “know” where pixels are located in space.

This has important implications:

  • Spatial autocorrelation can inflate accuracy

  • Neighboring pixels often share similar spectral values

  • Random train-test splits may not reflect real-world performance

We will revisit these limitations later.

For now, the goal is to understand how spatial raster data becomes machine learning input.

6. Loading and Inspecting the Data

Before building a machine learning model, we must first understand the structure of our datasets.

We will:

  • Load the Sentinel-2 raster composite

  • Load the training polygons

  • Verify coordinate reference systems (CRS)

  • Inspect raster dimensions and band information

Understanding your data is a critical step in any GeoAI workflow.

8. Extracting Training Samples

We now convert the raster + training polygons into a tabular dataset for ML.

For each polygon:

  • Mask the raster to extract pixels inside the polygon

  • Remove zero or nodata pixels

  • Flatten pixel values into feature vectors

  • Assign the polygon’s class label

Output:

  • X → Feature matrix (n_samples × n_bands)

  • y → Label vector (n_samples)

9. Train-Test Split and RandomForest Classifier

We now split our dataset into training and testing subsets, fit a RandomForestClassifier, and evaluate its accuracy.

  • X_train_samples → features (spectral bands)

  • y_train_labels → labels (land cover classes)

Feature Importance Interpretation

From the RandomForest feature importance graph, the bands are ranked as follows:

Band 4 > Band 3 > Band 1 > Band 2

Band 4 is significantly higher than the others.

1. Band 4 (NIR) — Most Important

  • Near-infrared (NIR) is highly reflective for vegetation.

  • The model relies on it most to separate forest from built-up and water areas.

  • This is expected for Sentinel-2 imagery, as vegetation stands out strongly in NIR.

2. Band 3 (Red) — Second Most Important

  • Sensitive to chlorophyll absorption in vegetation.

  • Helps distinguish vegetation from soil or built-up areas.

3. Bands 1 (Blue) and 2 (Green) — Less Important

  • Blue helps with water detection.

  • Green contributes slightly to vegetation differentiation.

  • Both are less discriminative for land cover types in this study area.

Practical Takeaways

  • The model correctly leverages NIR to identify forested areas.

  • Bands 3 and 4 are critical; bands 1 and 2 are secondary.

  • For dimensionality reduction, focusing on bands 3 and 4 may retain most of the classification power.

  • This explains why the RandomForest performs well: it uses the bands with the strongest spectral signals for the target classes.

Notebook narrative example The feature importance plot shows Band 4 (NIR) is the most influential, followed by Red (Band 3), then Blue (Band 1) and Green (Band 2). NIR strongly separates vegetation (forest) from water and built-up areas, Red contributes to vegetation detection, and Bands 1 and 2 play smaller supporting roles.

10. Full-Raster Classification and Visualization

In this step, we apply the trained RandomForest model to the entire Sentinel-2 composite image to produce a classified land cover map.

Steps:

  1. Reshape the full raster from (bands, rows, cols) to a 2D array of shape (pixels, bands) so it can be used as input for the model.

  2. Use the trained RandomForest model (rf_model) to predict the class for each pixel.

  3. Reshape the predicted labels back to the raster’s original dimensions.

  4. Visualize the resulting land cover classification map, assigning a distinct color to each class.

This allows us to see how the model generalizes from the training polygons to the entire image, producing a spatially continuous land cover map.

11. Fast Full-Raster Classification

For large rasters, predicting all pixels at once can be slow. Here, we implement a faster approach by:

  1. Optionally downsampling the raster for quick visualization.

  2. Splitting the raster into smaller chunks for prediction.

  3. Using the trained RandomForest model (rf_model) to classify pixels efficiently.

This allows us to generate a land cover map without overwhelming memory or CPU.

Exercise: Improve Land Cover Classification with NDVI

Goal: Improve the RandomForest land cover classification by adding NDVI as an additional feature. NDVI helps distinguish vegetation (forest, crops) from non-vegetated classes (water, bare soil).


Instructions

  1. Compute NDVI from the raster bands

    • Use Band 4 (NIR) and Band 3 (Red).

    • Formula:

      NDVI = (NIR − Red) / (NIR + Red)
  2. Add NDVI as a feature

    • Flatten NDVI to match the shape of your raster pixels.

    • Combine NDVI with the original bands to create a new feature array.

  3. Compute NDVI for training samples

    • Use the same formula for pixels inside your training polygons.

    • Combine with the original training bands to create a training feature array.

  4. Retrain your RandomForest

    • Use the new feature array (original bands + NDVI) and the training labels.

  5. Predict the raster

    • Use tiling and chunked prediction as before.

    • Include NDVI as a feature for each tile.

  6. Visualize the results

    • Use the same 7-class colormap as before.

    • Compare with the previous classification without NDVI.

  7. Reflect and Experiment

    • Which classes improved after adding NDVI?

    • Which land cover types are most affected by NDVI?

    • Optional: try adding other indices like NDWI (water) or NDBI (built-up) to further improve classification.


Tips:

  • Start with a downsampled raster to speed up the first run.

  • Check np.unique() of predicted classes to ensure the model predicts multiple classes.

Exercise 2: Improve Classification with NDVI and SVM

Goal: Explore how adding the NDVI index as a feature and switching the classifier to SVM affects land cover classification.


Instructions

  1. Compute NDVI from the raster bands

    • Use Band 4 (NIR) and Band 3 (Red).

    • Formula:

      NDVI = (NIR − Red) / (NIR + Red)
  2. Add NDVI as a feature

    • Flatten the NDVI array to match the shape of your raster pixels.

    • Combine with the original 4 bands to create a new feature array for classification.

  3. Compute NDVI for training samples

    • Use the same formula on pixels inside training polygons.

    • Combine with the original training bands to create the training feature array.

  4. Train an SVM classifier

    • Use sklearn.svm.SVC.

    • Use the new feature array (4 bands + NDVI) and the training labels.

    • Optional: experiment with kernel='linear' or kernel='rbf'.

  5. Predict the raster

    • Use the tiling + chunked prediction approach you implemented before.

    • Make sure NDVI is included as a feature for each tile.

  6. Visualize the results

    • Use the same 7-class colormap as before.

    • Compare with your previous RandomForest classification (NDVI only).

  7. Reflect and Experiment

    • Which classes improved after adding NDVI?

    • How does the SVM classifier perform compared to RandomForest?

    • Optional: try different kernels and note the differences in predicted maps.