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.

Using embeddings for lightweight classification and change analysis

You explored the embedding space without any labels on the previous page. This page adds a small number of labels back in, training a lightweight classifier on top of the same embeddings, then uses embedding comparison as a lightweight route to change detection.


1. Motivation

This page demonstrates the core economic advantage of embeddings directly: because Clay already extracted rich features during pre-training, a simple classifier trained on fewer than a hundred labeled points can achieve reasonable accuracy, without training anything resembling the segmentation or detection models from earlier lessons.


2. Core idea

The workflow is “embed first, classify later”: match your labeled points to their corresponding embedding patches with a spatial join, train a lightweight classifier directly on the matched embeddings, and separately, compare embeddings across locations or time as a lightweight signal for change detection.


3. Workflow

A. Labels to embedding patches

Checking and matching CRS before the join is not optional; a mismatch here would silently produce wrong or empty matches rather than a clear error. predicate="within" matches each labeled point to whichever embedding patch’s geometry contains it; the matched count can be slightly larger than the original label count if a point happens to fall inside more than one overlapping patch.

B. Extract labeled embeddings

stratify=class_labels preserves the original class balance in both the training and validation splits, important here since the two classes (baseball fields and marinas) are not evenly represented to begin with.

C. Train and compare classifiers

method="knn" trains a k-nearest neighbors classifier, which predicts a new point’s class based on the majority class among its n_neighbors closest embeddings. Comparing this against two alternatives is straightforward, since only the method argument changes:

Random Forest builds many decision trees and combines their votes; logistic regression fits a linear decision boundary in embedding space. None of these three methods needs more than a few seconds to train, precisely because the heavy feature-extraction work already happened during Clay’s pre-training, not here.

D. Visualize class separation

If the two classes form visually distinct groups in this PCA projection, that is a strong sign the foundation model’s embeddings already encode the distinction your classifier is learning to draw, which is exactly why so few labels are enough here.

E. Embeddings for change detection

compare_embeddings() computes similarity between two matched sets of embeddings; in a genuine temporal comparison (the same locations at two different dates, unlike this demonstration comparing different spatial patches), low-similarity outliers would flag locations that likely changed between the two dates, a lightweight alternative to ChangeStar’s per-pixel change map from L10 when a coarser, patch-level change signal is enough.


4. Python reactivation

stratify=class_labels is a keyword argument to train_test_split() that ensures each split’s class proportions match the original data’s, rather than potentially skewing by chance, especially important with the kind of small, imbalanced label set used here. The list-of-dictionaries-to-DataFrame pattern in step C (results_summary.append({...}), then pd.DataFrame(results_summary)) is a common way to collect results from a loop into a clean, displayable table.


5. Common pitfalls


6. Mini task

Your k-NN classifier achieves 75% validation accuracy on 32 held-out points, 24 baseball fields and 8 marinas. A classmate says this is clearly a strong result. What would you check before agreeing?

Sample solution

With classes this imbalanced (24 versus 8), a baseline that always predicts “Baseball Field” would already achieve 75% accuracy without learning anything about marinas at all, so overall accuracy alone does not confirm the classifier is doing well on both classes. The next step would be checking per-class metrics (precision and recall for each class specifically), which would reveal whether the classifier is actually distinguishing marinas or simply defaulting to the majority class most of the time.


7. Key takeaways