{"slug":"geo-deep-learning","title":"geo-deep-learning","summary":"Invoke before recommending, training, or auditing a neural method for geospatial imagery, including vision transformers, U-Net/DeepLab/SegFormer, object detection, pixel classification, building/road extraction, and EO foundation-model fine-tuning. Also invoke for neural chip-spl","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-18T14:08:02.24886Z","repo":{"url":"https://github.com/muend/geoai-skills","stars":27,"forks":3,"license":"MIT","updatedAt":"2026-09-03T23:49:19Z"},"bodyHtml":"<hr>\n<h2>name: geo-deep-learning\ndescription: &gt;-\nInvoke before recommending, training, or auditing a neural method for\ngeospatial imagery, including vision transformers, U-Net/DeepLab/SegFormer,\nobject detection, pixel classification, building/road extraction, and EO\nfoundation-model fine-tuning. Also invoke for neural chip-split validity,\nIoU/accuracy claims, augmentation, imbalanced losses, spatial validation,\nor sliding-window inference. Use remote-sensing-analysis for non-neural\nmethods and change-detection when temporal change is the deliverable.\nlicense: MIT\nmetadata:\nauthor: Muhammed Enes Duran</h2>\n<h1>Geospatial Deep Learning</h1>\n<p>Purpose: deep learning on Earth observation with the two failure modes that\ndominate this field designed out from the start: <strong>spatial leakage</strong>\n(inflated metrics from nearby train/test pixels) and <strong>georeferencing loss</strong>\n(predictions that no longer align with the map).</p>\n<h2>Characterise the label set before naming an architecture</h2>\n<p>Architecture advice given without knowing the label set is guesswork. Before\nrecommending U-Net versus a foundation model versus a non-deep baseline, state\nor ask for:</p>\n<ul>\n<li><strong>Label count and labelled area</strong> — polygons alone say nothing; 40 polygons\ncovering 2 ha and 40 covering 2 000 km² are different problems.</li>\n<li><strong>Geographic spread</strong> — are the labels clustered in one scene, one season and\none sensor, or distributed across the deployment domain? Clustered labels cap\nwhat any model can generalise to, and they decide whether a geographically\nindependent validation split is even constructible.</li>\n<li><strong>Class balance and minority-class pixel fraction</strong>, so loss and sampling\nchoices are grounded rather than assumed.</li>\n<li><strong>Deployment geography</strong> — where predictions will be made, relative to where\nthe labels are.</li>\n</ul>\n<p>Do not answer \"fine-tune a large model or use a simpler approach\" before these\nare known. When the user has not supplied them, ask and give the provisional\nrecommendation <em>conditioned on</em> the answers (\"if the 40 polygons sit in one\nscene, then …; if they span the region, then …\"), never a single unconditional\nrecommendation.</p>\n<h2>Problem framing first</h2>\n<table>\n<thead>\n<tr>\n<th>Task</th>\n<th>Head/architecture default</th>\n<th>Metric</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Pixel-wise classes (land cover)</td>\n<td>U-Net / DeepLabv3+ (pretrained encoder)</td>\n<td>mIoU, per-class IoU</td>\n</tr>\n<tr>\n<td>Binary extraction (buildings, water, roads)</td>\n<td>U-Net + Dice/CE hybrid</td>\n<td>IoU, F1; boundary F1 for roads</td>\n</tr>\n<tr>\n<td>Object detection (vehicles, ships, trees)</td>\n<td>YOLO-family / Faster R-CNN, rotated boxes if oriented</td>\n<td>mAP@50</td>\n</tr>\n<tr>\n<td>Scene classification</td>\n<td>Fine-tuned CNN/ViT</td>\n<td>F1 (macro)</td>\n</tr>\n<tr>\n<td>Regression (height, biomass, density)</td>\n<td>U-Net with regression head</td>\n<td>RMSE/MAE + spatial residual map</td>\n</tr>\n</tbody>\n</table>\n<p>Before any deep model: run a cheap baseline (random forest on bands+indices,\nor thresholded index). If the DL model can't beat it clearly, the problem is\ndata, not architecture. <code>segmentation-models-pytorch</code> and <code>torchgeo</code> cover\nmost needs — don't hand-build architectures without a reason.</p>\n<h2>Chipping (dataset construction)</h2>\n<ul>\n<li>Chip size: 256–512 px; stride &lt; chip size only for training (overlap\naugments), never let overlapping chips straddle the train/val boundary.</li>\n<li><strong>Preserve georeferencing</strong>: store each chip's transform/bounds (torchgeo\ndatasets or a sidecar index in GeoParquet). A prediction you can't put\nback on the map is worthless.</li>\n<li>Keep chips in the native data range; normalize with <strong>dataset-computed</strong>\nper-band statistics (ImageNet stats only for 3-band RGB with a pretrained\nencoder, and say so).</li>\n<li>Class imbalance is the norm (buildings ≈ 2-5% of pixels). Log per-chip\nclass fractions; oversample positive-containing chips rather than\ndistorting the loss beyond recognition.</li>\n</ul>\n<h2>Split policy — the non-negotiable</h2>\n<p>Split by <strong>geographic block or scene</strong>, never by random chip. Adjacent\nchips are near-duplicates; random splits produce beautiful, fake validation\ncurves. Follow the canonical protocol:\n<code>ml-experiment-standards</code> → <code>references/spatial-cv-protocol.md</code>.\nFor generalization claims across regions, hold out an entire region.</p>\n<h2>Training defaults</h2>\n<ul>\n<li>Loss: Dice + CE (segmentation, imbalanced); plain CE when balanced; Focal\nonly after comparing — it's not a free win.</li>\n<li>Augmentation: flips/rot90 are safe for nadir imagery; be careful with\ncolor jitter on multispectral (it breaks radiometric meaning — prefer\nband dropout or slight scaling); never augment in ways that violate the\nphysics.</li>\n<li>Encoder pretrained; multispectral input → inflate/replace first conv, or\nuse an EO foundation model checkpoint (Prithvi, SatMAE, Clay) when bands\nmatch.</li>\n<li>Early stopping on val mIoU (patience 10-15); cosine or plateau LR\nschedule; AMP on by default.</li>\n<li>Log config + metrics + git hash per run — see <code>ml-experiment-standards</code>.</li>\n</ul>\n<h2>Inference on large scenes</h2>\n<p>Sliding window with overlap (25-50%) and blending (feather/gaussian or\ncenter-crop stitching) to kill tile-edge artifacts. Then:</p>\n<pre><code>import rasterio\n\nwith rasterio.open(scene_path) as src:\n    profile = src.profile\nprofile.update(count=1, dtype=\"uint8\", nodata=255, compress=\"deflate\")\nwith rasterio.open(out_path, \"w\", **profile) as dst:\n    dst.write(mask.astype(\"uint8\"), 1)  # same transform/CRS as the scene\n</code></pre>\n<p>Post-process: sieve tiny blobs (min mapping unit), optionally regularize\nbuilding polygons, and vectorize (<code>rasterio.features.shapes</code>) for GIS\ndelivery. Report metrics AFTER post-processing too — that's what the user\nships.</p>\n<h2>Verification protocol</h2>\n<ol>\n<li>Metrics table: per-class IoU/F1 with CI across seeds or folds.</li>\n<li><strong>Error map</strong>: prediction vs reference overlaid on imagery for 3+\nrepresentative areas including a known-hard one.</li>\n<li>Sanity inference on an out-of-distribution patch (different season/\nregion) with an honest note on degradation.</li>\n<li>Alignment check: overlay predictions on the source scene in a GIS at\ntwo zoom levels — catches transform bugs instantly.</li>\n</ol>\n<h2>Pitfalls checklist</h2>\n<ul>\n<li>Random chip split → leaked, unreproducible \"SOTA\".</li>\n<li>Normalizing test data with train-time stats not saved → skewed inference.</li>\n<li>Losing the geotransform in NumPy-land; writing predictions with default\nnorth-up transform.</li>\n<li>Tile-edge seams from no-overlap inference.</li>\n<li>uint16 imagery fed to a float pipeline without scaling → dead gradients.</li>\n<li>Accuracy reported on chip level while the product is a stitched map.</li>\n</ul>\n<h2>Execution contract</h2>\n<ul>\n<li><strong>Workflow:</strong> frame target and unit of prediction; build chips and labels; create spatial splits; train against a baseline; run overlap-aware inference; validate the stitched product.</li>\n<li><strong>Decision rules:</strong> use deep learning only when label volume, spatial texture, compute, and expected uplift justify it; otherwise prefer a simpler remote-sensing or ML workflow.</li>\n<li><strong>Verification protocol:</strong> report spatial holdout metrics across seeds or folds, inspect error maps and hard areas, test geographic transfer, and check output georeferencing.</li>\n<li><strong>Failure modes:</strong> invalidate results for leaked chips, label misalignment, train/inference normalization drift, tile seams, or metrics computed at the wrong product unit.</li>\n<li><strong>Deliverables:</strong> model and configuration, split manifest, preprocessing contract, metrics with uncertainty, georeferenced predictions, error maps, and model card limitations.</li>\n<li><strong>Source freshness:</strong> consult <a href=\"references/authoritative-sources.md\">the authoritative source registry</a> before selecting framework APIs, datasets, or weights and record the checked date.</li>\n</ul>\n","files":[{"path":"agents/openai.yaml","sizeBytes":224,"isText":true},{"path":"references/authoritative-sources.md","sizeBytes":792,"isText":true},{"path":"SKILL.md","sizeBytes":7507,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-18T14:08:27.277337Z","sha256":"47417FA0709FFD14D26CA4594B4801C86EAA3514FFBB5F216DC9564EEE6BCB41","sizeBytes":4672},"review":null,"source":{"repositoryUrl":"https://github.com/muend/geoai-skills","path":"skills/geo-deep-learning","license":"MIT","commit":"096e5d4e6825a128e376b017783ee4c8c7323f9b","subtreeSha":"380C8D913BC346EEB80606E925A552163873BF9015289F6F24BC9908EF9D7E79","lastSyncedAt":"2026-09-27T19:46:46.325636Z"},"reviewedAt":"2026-09-18T14:09:30.119933Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/muend/geoai-skills/tree/main/skills/geo-deep-learning"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install muend-geoai-skills@llmmart"},{"target":"git","command":"git clone https://github.com/muend/geoai-skills.git"}]}