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.

Generating patch-based embeddings with the Clay foundation model

You can now find a dataset in the registry. This page downloads and assembles a real one: Clay Foundation Model embeddings for the San Francisco Bay Area, the dataset the rest of this lesson’s hands-on pages build on.


1. Motivation

This is the page where the registry becomes actual data you can analyze. Clay’s embeddings, computed from NAIP aerial imagery across 20 tiles, come with labeled points for two land-use classes, which makes this dataset useful for every later page in this lesson, from unsupervised exploration through classification.


2. Core idea

Clay produces 768-dimensional patch embeddings from a range of satellite and aerial sources. This lesson’s dataset is distributed as GeoParquet files on Hugging Face Hub, one file per tile; the workflow is to download each tile, combine them into a single GeoDataFrame, and extract the embedding vectors into a NumPy matrix ready for analysis.


3. Workflow

A. List and download embedding tiles

repo_type="dataset" is important here; without it, HfApi looks for a model repository instead of a dataset repository, and the call will not find the files you expect. Each .gpq file is one GeoParquet tile of embeddings.

B. Combine tiles into a GeoDataFrame

Each downloaded tile is read directly with gpd.read_parquet(), since GeoParquet is a standard, directly readable geospatial format. pd.concat() stacks all 20 tiles’ rows into one table, and re-wrapping the result as a GeoDataFrame (with the first tile’s CRS) restores its spatial behavior, since pd.concat() alone returns a plain DataFrame.

C. Download the labeled points

This dataset also ships labeled points for two classes, baseball fields (class 0) and marinas (class 1), which you will use for the classification workflow two pages from now.

D. Extract the embedding matrix

Each row’s embeddings column holds a 768-element vector; np.stack() combines all of them into a single two-dimensional array, one row per patch, ready for the analysis functions used throughout the rest of this lesson. Extracting each patch’s centroid coordinates separately is what lets you plot embedding-space results back onto a real geographic map, a pattern you will use repeatedly starting on the next page.


4. Python reactivation

The list comprehension building embedding_files ([f.path for f in ... if f.path.endswith(".gpq")]) combines filtering and extraction in one line, the same pattern used for file-path lists throughout this course. np.stack() differs from a plain np.array() call on a column of arrays: it explicitly combines a sequence of equal-shaped arrays along a new axis, which is the reliable way to turn a pandas column of vectors into a proper two-dimensional matrix.


5. Common pitfalls


6. Mini task

embeddings.shape prints (36024, 768). Without looking at any other output, explain what each of these two numbers represents.

Sample solution

36024 is the number of patches (rows), one per image tile combined across all 20 downloaded GeoParquet files. 768 is the embedding dimension (columns), the length of each individual patch’s Clay embedding vector, consistent with the registry’s reported dimensionality for the Clay dataset from the previous page.


7. Key takeaways


Further reading