thêm chức năng train trên odc predict trên planetary
This commit is contained in:
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user