thêm chức năng train trên odc predict trên planetary

This commit is contained in:
Victor Phan
2026-03-04 23:14:48 +07:00
parent 8a1e7bb22e
commit add7d16ecf
2 changed files with 353 additions and 178 deletions
+127
View File
@@ -9,10 +9,12 @@ Usage:
import xarray as xr
import numpy as np
import pandas as pd
import geopandas as gpd
from pystac_client import Client
import planetary_computer
import odc.stac
from datetime import datetime
from sklearn.model_selection import train_test_split
def load_sentinel2_stac(
@@ -292,6 +294,127 @@ def load_and_process_s1(bbox, date_range):
return data_monthly
# ══════════════════════════════════════════════════════════════════════════════
# TRAINING DATA FUNCTIONS
# ══════════════════════════════════════════════════════════════════════════════
def load_train_data(train_path, label_mapping=None):
"""
Load training data from shapefile or GeoJSON
Args:
train_path: Path to training data file (.shp, .geojson, etc.)
label_mapping: Optional dict to map labels to numeric IDs
Returns:
GeoDataFrame with training points
"""
print(f"📂 Loading training data from: {train_path}")
try:
train = gpd.read_file(train_path)
print(f"✅ Loaded {len(train)} training points")
print(f" Columns: {list(train.columns)}")
if label_mapping is not None and 'label' in train.columns:
train['label_id'] = train['label'].map(label_mapping).astype(int)
print(f" Labels mapped: {sorted(train['label_id'].unique())}")
return train
except Exception as e:
print(f"❌ Error loading training data: {e}")
return None
def extract_features_at_points(train_data, data_s2, data_s1):
"""
Extract Sentinel-1 and Sentinel-2 features at training point locations
Args:
train_data: GeoDataFrame with training points
data_s2: xarray Dataset with Sentinel-2 data
data_s1: xarray Dataset with Sentinel-1 data
Returns:
X (features), y (labels)
"""
print(f"🔧 Extracting features from satellite data at {len(train_data)} points...")
X_list = []
y_list = []
for idx, point in train_data.iterrows():
try:
lon, lat = point.geometry.x, point.geometry.y
# Extract S2 data at point location
s2_point = data_s2.sel(x=lon, y=lat, method='nearest')
s2_values = s2_point.to_array().values.flatten()
# Extract S1 data at point location
s1_point = data_s1.sel(x=lon, y=lat, method='nearest')
s1_values = s1_point.to_array().values.flatten()
# Combine features
features = np.concatenate([s2_values, s1_values])
# Skip if contains NaN
if not np.isnan(features).any():
X_list.append(features)
y_list.append(point['label_id'])
else:
print(f" ⚠ Skip point {idx}: contains NaN")
except Exception as e:
print(f" ⚠ Skip point {idx}: {e}")
continue
X = np.array(X_list)
y = np.array(y_list)
print(f"✅ Extracted features from {len(X)} points")
print(f" Feature dimension: {X.shape[1]}")
print(f" Classes: {sorted(set(y.tolist()))}")
return X, y
def split_train_data(X, y, test_size=0.2, val_size=0.1, random_state=42):
"""
Split data into train/val/test sets
Args:
X: Features array
y: Labels array
test_size: Proportion for test set
val_size: Proportion for validation set (from train+val)
random_state: Random seed
Returns:
X_train, X_val, X_test, y_train, y_val, y_test
"""
print(f"📊 Splitting data...")
# First split: train+val vs test
X_temp, X_test, y_temp, y_test = train_test_split(
X, y, test_size=test_size, random_state=random_state, stratify=y
)
# Second split: train vs val
val_ratio = val_size / (1 - test_size)
X_train, X_val, y_train, y_val = train_test_split(
X_temp, y_temp, test_size=val_ratio, random_state=random_state, stratify=y_temp
)
print(f"✅ Data split complete:")
print(f" Train: {len(X_train)} samples ({len(X_train)/len(X)*100:.1f}%)")
print(f" Val: {len(X_val)} samples ({len(X_val)/len(X)*100:.1f}%)")
print(f" Test: {len(X_test)} samples ({len(X_test)/len(X)*100:.1f}%)")
return X_train, X_val, X_test, y_train, y_val, y_test
# Print module info
print("=" * 70)
print("📦 Data Loading Module (No ODC Database Required)")
@@ -302,5 +425,9 @@ print("\n bbox = (lon_min, lat_min, lon_max, lat_max)")
print(" date_range = ('2022-09-01', '2023-10-01')")
print("\n data_s2 = load_and_process_s2(bbox, date_range)")
print(" data_s1 = load_and_process_s1(bbox, date_range)")
print("\n # Load training data")
print(" train = load_train_data('train/data.shp', label_mapping)")
print(" X, y = extract_features_at_points(train, data_s2, data_s1)")
print(" X_train, X_val, X_test, y_train, y_val, y_test = split_train_data(X, y)")
print("=" * 70)
print()