hoàn thành chức năng tính ndvi analysys 2 màn hình

This commit is contained in:
Victor Phan
2025-12-24 13:57:08 +07:00
parent 389c7c141f
commit e86709df85
25 changed files with 4755 additions and 460 deletions
+240 -52
View File
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"id": "912ed572-1658-406b-976c-cd6de2d4e89e",
"metadata": {
"tags": []
@@ -734,7 +734,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": null,
"id": "2e955884-d4af-422d-a8e6-d436199540e0",
"metadata": {
"tags": []
@@ -756,75 +756,144 @@
],
"source": [
"%%time\n",
"# 🤖 RANDOM FOREST MODEL TRAINING\n",
"# 🤖 LAND USE CLASSIFICATION MODEL TRAINING (MỤC TIÊU CHÍNH)\n",
"print(\"=\"*70)\n",
"print(\"MODEL TRAINING\")\n",
"print(\"LAND USE CLASSIFICATION TRAINING\")\n",
"print(\"=\"*70)\n",
"print(\"\\n🎯 Mục tiêu: Dự đoán phân loại sử dụng đất (8 lớp)\")\n",
"print(\" - NDVI/NDWI/NDBI/EVI là INPUT FEATURES\")\n",
"print(\" - Sau khi predict xong → có thể hiển thị NDVI map như chỉ số phụ\")\n",
"print(\"=\"*70)\n",
"\n",
"if train is not None and ndvi is not None:\n",
" print(\"\\n[1] Extracting features from NDVI...\")\n",
"if train is not None and data is not None:\n",
" print(\"\\n[1] Extracting MULTIPLE features from satellite data...\")\n",
" print(\" (Sử dụng nhiều spectral indices để cải thiện accuracy)\")\n",
" \n",
" try:\n",
" # Extract NDVI values at training point locations\n",
" # Extract features at training point locations\n",
" X = []\n",
" y = []\n",
" \n",
" for idx, point in train.iterrows():\n",
" try:\n",
" # Get NDVI value at point location (nearest neighbor)\n",
" ndvi_val = float(ndvi.sel(x=point.geometry.x, y=point.geometry.y, method='nearest').values)\n",
" label = label_mapping[point.Hientrang]\n",
" \n",
" X.append([ndvi_val])\n",
" y.append(int(label))\n",
" except Exception as e:\n",
" print(f\" ⚠️ Point {idx}: {e}\")\n",
" # Available features from data\n",
" available_features = ['ndvi_mean', 'ndvi_min', 'ndvi_max', 'ndvi_std', 'ndvi_range',\n",
" 'ndwi_mean', 'ndbi_mean', 'evi_mean']\n",
" \n",
" if len(X) > 0:\n",
" X = np.array(X)\n",
" y = np.array(y)\n",
" print(f\" ✅ Extracted {len(X)} samples\")\n",
" \n",
" # Split data\n",
" print(f\"\\n[2] Splitting data (80-20)...\")\n",
" from sklearn.model_selection import train_test_split\n",
" X_train, X_test, y_train, y_test = train_test_split(\n",
" X, y, test_size=0.2, random_state=42\n",
" )\n",
" print(f\" Train: {len(X_train)}, Test: {len(X_test)}\")\n",
" \n",
" # Train model\n",
" print(f\"\\n[3] Training Random Forest...\")\n",
" from sklearn.ensemble import RandomForestClassifier\n",
" from sklearn.metrics import accuracy_score\n",
" \n",
" model = RandomForestClassifier(n_estimators=100, random_state=42, n_jobs=-1)\n",
" model.fit(X_train, y_train)\n",
" \n",
" # Evaluate\n",
" y_pred = model.predict(X_test)\n",
" accuracy = accuracy_score(y_test, y_pred)\n",
" print(f\" ✅ Model trained!\")\n",
" print(f\" Accuracy: {accuracy*100:.2f}%\")\n",
" \n",
" else:\n",
" print(f\" ❌ No samples extracted\")\n",
" # Check which features are actually available\n",
" features_to_use = [f for f in available_features if f in data.data_vars]\n",
" \n",
" if not features_to_use:\n",
" print(\" ❌ No spectral features found in dataset!\")\n",
" print(\" Available variables:\", list(data.data_vars))\n",
" model = None\n",
" else:\n",
" print(f\" Using {len(features_to_use)} features: {features_to_use}\")\n",
" \n",
" for idx, point in train.iterrows():\n",
" try:\n",
" # Extract all available features at this point\n",
" feature_vec = []\n",
" for feat_name in features_to_use:\n",
" feat_val = float(data[feat_name].sel(\n",
" x=point.geometry.x, \n",
" y=point.geometry.y, \n",
" method='nearest'\n",
" ).values)\n",
" feature_vec.append(feat_val)\n",
" \n",
" # Get label\n",
" label = label_mapping[point.Hientrang]\n",
" \n",
" # Only add if no NaN values\n",
" if not np.isnan(feature_vec).any():\n",
" X.append(feature_vec)\n",
" y.append(int(label))\n",
" except Exception as e:\n",
" # Skip points with errors\n",
" continue\n",
" \n",
" if len(X) > 0:\n",
" X = np.array(X)\n",
" y = np.array(y)\n",
" print(f\" ✅ Extracted {len(X)} samples with {X.shape[1]} features each\")\n",
" \n",
" # Show feature statistics\n",
" print(f\"\\n Feature statistics:\")\n",
" for i, feat_name in enumerate(features_to_use):\n",
" print(f\" {feat_name:15s}: mean={X[:,i].mean():.3f}, std={X[:,i].std():.3f}\")\n",
" \n",
" # Split data\n",
" print(f\"\\n[2] Splitting data (80-20)...\")\n",
" from sklearn.model_selection import train_test_split\n",
" X_train, X_test, y_train, y_test = train_test_split(\n",
" X, y, test_size=0.2, random_state=42, stratify=y\n",
" )\n",
" print(f\" Train: {len(X_train)}, Test: {len(X_test)}\")\n",
" \n",
" # Show class distribution\n",
" unique, counts = np.unique(y_train, return_counts=True)\n",
" print(f\"\\n Class distribution in training set:\")\n",
" for cls, count in zip(unique, counts):\n",
" cls_name = [k for k, v in label_mapping.items() if v == str(cls)][0]\n",
" print(f\" {cls}: {cls_name:15s} - {count:4d} samples ({count/len(y_train)*100:.1f}%)\")\n",
" \n",
" # Train model\n",
" print(f\"\\n[3] Training Random Forest for LAND USE CLASSIFICATION...\")\n",
" from sklearn.ensemble import RandomForestClassifier\n",
" from sklearn.metrics import accuracy_score, classification_report\n",
" \n",
" model = RandomForestClassifier(\n",
" n_estimators=200, # More trees for better accuracy\n",
" max_depth=30,\n",
" min_samples_split=5,\n",
" random_state=42,\n",
" n_jobs=-1,\n",
" verbose=1\n",
" )\n",
" model.fit(X_train, y_train)\n",
" \n",
" # Evaluate\n",
" y_pred = model.predict(X_test)\n",
" accuracy = accuracy_score(y_test, y_pred)\n",
" \n",
" print(f\"\\n ✅ Model trained!\")\n",
" print(f\" Training accuracy: {model.score(X_train, y_train)*100:.2f}%\")\n",
" print(f\" Testing accuracy: {accuracy*100:.2f}%\")\n",
" \n",
" # Show feature importance\n",
" print(f\"\\n Feature importance:\")\n",
" importances = model.feature_importances_\n",
" indices = np.argsort(importances)[::-1]\n",
" for i, idx in enumerate(indices):\n",
" print(f\" {i+1}. {features_to_use[idx]:15s}: {importances[idx]:.4f}\")\n",
" \n",
" # Classification report\n",
" print(f\"\\n[4] Classification Report:\")\n",
" class_names = [k for k, v in sorted(label_mapping.items(), key=lambda x: x[1])]\n",
" print(classification_report(y_test, y_pred, target_names=class_names, zero_division=0))\n",
" \n",
" else:\n",
" print(f\" ❌ No samples extracted\")\n",
" model = None\n",
" \n",
" except Exception as e:\n",
" print(f\" ❌ Error: {e}\")\n",
" import traceback\n",
" traceback.print_exc()\n",
" model = None\n",
"else:\n",
" print(\"❌ Missing training data or NDVI\")\n",
" print(\"❌ Missing training data or satellite data\")\n",
" model = None\n",
"\n",
"print(\"\\n\" + \"=\"*70)\n",
"print(\"📝 NOTE: Model này dự đoán PHÂN LOẠI SỬ DỤNG ĐẤT (8 lớp)\")\n",
"print(\" NDVI là một trong các features đầu vào, không phải mục tiêu dự đoán\")\n",
"print(\" Sau khi predict → có thể hiển thị NDVI map như chỉ số phụ\")\n",
"print(\"=\"*70)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": null,
"id": "f1a14379-ed6e-4897-9ca4-2669743fab40",
"metadata": {
"tags": []
@@ -843,24 +912,143 @@
}
],
"source": [
"# 💾 SAVE MODEL\n",
"# 💾 SAVE MODEL WITH METADATA\n",
"print(\"=\"*70)\n",
"print(\"MODEL SAVING\")\n",
"print(\"=\"*70)\n",
"\n",
"if model is not None:\n",
" print(\"\\n🔄 Saving trained model...\")\n",
" print(\"\\n🔄 Saving trained LAND USE CLASSIFICATION model with metadata...\")\n",
" try:\n",
" save_model(\"model_rasterio.joblib\", model)\n",
" print(\"✅ Model saved to model_train/model_rasterio.joblib\")\n",
" from datetime import datetime\n",
" \n",
" # Prepare metadata for ModelManager\n",
" metadata = {\n",
" \"timestamp\": datetime.now().isoformat(),\n",
" \"data_source\": \"Local S3 ODC (Open Data Cube)\",\n",
" \"collections\": [\"sentinel-2-l2a\"],\n",
" \"features\": features_to_use, # All features used\n",
" \"feature_mode\": \"extended\", # Using extended aggregate features\n",
" \"training_samples\": len(X_train),\n",
" \"testing_samples\": len(X_test),\n",
" \"test_size\": 0.2,\n",
" \"train_accuracy\": float(model.score(X_train, y_train)),\n",
" \"test_accuracy\": float(accuracy),\n",
" \"model_type\": \"random_forest\",\n",
" \"device\": \"cpu\",\n",
" \"n_estimators\": 200,\n",
" \"max_depth\": 30,\n",
" \"learning_rate\": None,\n",
" \"cnn_epochs\": None,\n",
" \"n_features\": X_train.shape[1],\n",
" \"n_classes\": len(np.unique(y)),\n",
" \"class_names\": list(label_mapping.keys()),\n",
" \"classification_report\": classification_report(y_test, y_pred, \n",
" target_names=class_names, \n",
" output_dict=True,\n",
" zero_division=0),\n",
" \"bbox\": None,\n",
" \"time_range\": f\"{date_range[0]}/{date_range[1]}\",\n",
" \"resolution\": 10,\n",
" \"notes\": \"LAND USE CLASSIFICATION model trained from 01.train_ODC.ipynb. Predicts 8 land use classes using multiple spectral indices. NDVI is one of the input features, not the prediction target.\"\n",
" }\n",
" \n",
" # Save model with metadata using updated save_model function\n",
" save_model(\"model_land_use_odc.joblib\", model, metadata=metadata, label_encoder=None)\n",
" \n",
" print(\"✅ Model saved to model_train/model_land_use_odc.joblib\")\n",
" print(f\" - Purpose: Land Use Classification (8 classes)\")\n",
" print(f\" - Features: {len(features_to_use)} ({', '.join(features_to_use[:3])}...)\")\n",
" print(f\" - Train Accuracy: {metadata['train_accuracy']*100:.2f}%\")\n",
" print(f\" - Test Accuracy: {metadata['test_accuracy']*100:.2f}%\")\n",
" print(f\" - Classes: {metadata['n_classes']}\")\n",
" print(f\"\\n📝 NDVI là một trong các features, không phải prediction target\")\n",
" print(f\" Sau khi predict → có thể tính NDVI map riêng để hiển thị\")\n",
" except Exception as e:\n",
" print(f\"❌ Error saving model: {e}\")\n",
" import traceback\n",
" traceback.print_exc()\n",
"else:\n",
" print(\"❌ No model to save\")\n",
"\n",
"print(\"=\"*70)"
]
},
{
"cell_type": "markdown",
"id": "4a8579f4",
"metadata": {},
"source": [
"# 📖 Hướng dẫn sử dụng Model\n",
"\n",
"## Mục đích của Model\n",
"\n",
"Model này được train để **DỰ ĐOÁN PHÂN LOẠI SỬ DỤNG ĐẤT** với 8 lớp:\n",
"\n",
"1. **Lua tom** (0) - Lúa tôm\n",
"2. **Lua** (1) - Lúa\n",
"3. **CHN** (2) - Cây hàng năm\n",
"4. **CLN** (3) - Cây lâu năm \n",
"5. **TS** (4) - Thủy sản\n",
"6. **Song** (5) - Sông\n",
"7. **Dat xay dung** (6) - Đất xây dựng\n",
"8. **Rung** (7) - Rừng\n",
"\n",
"## Features đầu vào\n",
"\n",
"Model sử dụng **nhiều spectral indices** làm features:\n",
"- NDVI (mean, min, max, std, range)\n",
"- NDWI (mean)\n",
"- NDBI (mean)\n",
"- EVI (mean)\n",
"\n",
"## NDVI là gì trong hệ thống này?\n",
"\n",
"⚠️ **QUAN TRỌNG**: NDVI **KHÔNG PHẢI** là mục tiêu dự đoán!\n",
"\n",
"- **NDVI là INPUT FEATURE**: Một trong các chỉ số dùng để train model\n",
"- **Mục tiêu dự đoán**: Phân loại sử dụng đất (8 lớp)\n",
"- **NDVI map**: Có thể hiển thị NDVI map như chỉ số phụ sau khi predict xong\n",
"\n",
"## Workflow Prediction\n",
"\n",
"```python\n",
"# 1. Load model\n",
"model, label_encoder, metadata = model_manager.load_model(\"model_land_use_odc.joblib\")\n",
"\n",
"# 2. Extract features từ satellite data\n",
"features = extract_features(satellite_data) # NDVI, NDWI, NDBI, EVI\n",
"\n",
"# 3. Predict land use classification\n",
"land_use_prediction = model.predict(features)\n",
"# → Kết quả: Mảng với giá trị 0-7 (8 lớp sử dụng đất)\n",
"\n",
"# 4. (Optional) Tính NDVI map riêng để hiển thị\n",
"ndvi_map = (NIR - Red) / (NIR + Red)\n",
"# → NDVI map chỉ để visualize, không phải prediction target\n",
"```\n",
"\n",
"## So sánh với approach cũ\n",
"\n",
"| Approach | Features | Target | NDVI Role |\n",
"|----------|----------|--------|-----------|\n",
"| ❌ Cũ (sai) | Chỉ NDVI | 8 lớp đất | Input duy nhất |\n",
"| ✅ Mới (đúng) | NDVI + NDWI + NDBI + EVI | 8 lớp đất | Một trong nhiều features |\n",
"\n",
"## Test Model\n",
"\n",
"```python\n",
"# Test với website\n",
"# 1. Upload model_land_use_odc.joblib lên server\n",
"# 2. Chọn model trong prediction interface\n",
"# 3. Chọn vùng và thời gian\n",
"# 4. System sẽ tự động:\n",
"# - Extract features (NDVI, NDWI, NDBI, EVI)\n",
"# - Predict land use classification\n",
"# - (Optional) Generate NDVI visualization map\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,