chạy được local và GPU và server API

This commit is contained in:
Victor Phan
2025-12-12 20:09:48 +07:00
parent d96c0c9d69
commit c60dea728f
5 changed files with 266 additions and 4 deletions
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:549bf41a29b39a583c9ac1a2f08283b7494bcd521f8b6b5aff1fa7f5f0ca1cab
size 919988
oid sha256:dd3fecbef4c80ff1bd20922e6b2250d94ac05e55c3a2efbff4da20fcea3d739f
size 39812
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:89c347e98288e77ddb7579d4cfa2b49924a993f7173a2d12155ef7a1893082b1
size 163627
+256
View File
@@ -0,0 +1,256 @@
"""
API Server for Land Classification Model Training
Cho phép chọn dữ liệu và cấu hình training qua giao diện web
"""
from fastapi import FastAPI, BackgroundTasks, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse, FileResponse
from pydantic import BaseModel
from typing import Optional, List
import uvicorn
import joblib
import json
from datetime import datetime
from pathlib import Path
import sys
app = FastAPI(title="Land Classification Training API", version="1.0.0")
# Enable CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Global training status
training_status = {
"is_training": False,
"progress": "",
"error": None,
"result": None,
"start_time": None,
"end_time": None
}
class TrainingConfig(BaseModel):
"""Cấu hình training"""
# Khu vực (bbox)
min_lon: float = 105.6
min_lat: float = 9.3
max_lon: float = 106.2
max_lat: float = 9.8
# Thời gian
start_date: str = "2023-03-01"
end_date: str = "2023-05-31"
# Dữ liệu
max_scenes: int = 12
cloud_cover: int = 30
resolution: int = 20 # 10m hoặc 20m
# Model parameters
n_estimators: int = 100
max_depth: int = 20
learning_rate: float = 0.1
use_gpu: bool = True
# Training data
training_shapefile: str = "train/ST_training data_updated_1130points_new.shp"
class TrainingStatus(BaseModel):
"""Trạng thái training"""
is_training: bool
progress: str
error: Optional[str]
result: Optional[dict]
start_time: Optional[str]
end_time: Optional[str]
@app.get("/", response_class=HTMLResponse)
async def root():
"""Serve giao diện web"""
html_file = Path(__file__).parent / "training_interface.html"
if html_file.exists():
return FileResponse(html_file)
else:
return HTMLResponse("""
<html>
<head><title>Training Interface</title></head>
<body>
<h1>Land Classification Training API</h1>
<p>API Documentation: <a href="/docs">/docs</a></p>
<p>Training Interface: Tạo file training_interface.html</p>
</body>
</html>
""")
@app.get("/api/config/presets")
async def get_presets():
"""Lấy các preset cấu hình sẵn"""
return {
"presets": [
{
"name": "PC - Nhỏ (3 tháng, 20m, 12 scenes)",
"config": {
"min_lon": 105.6, "min_lat": 9.3, "max_lon": 106.2, "max_lat": 9.8,
"start_date": "2023-03-01", "end_date": "2023-05-31",
"max_scenes": 12, "cloud_cover": 30, "resolution": 20
}
},
{
"name": "Server - Trung bình (6 tháng, 10m, 30 scenes)",
"config": {
"min_lon": 105.5, "min_lat": 9.2, "max_lon": 106.4, "max_lat": 10.0,
"start_date": "2023-01-01", "end_date": "2023-06-30",
"max_scenes": 30, "cloud_cover": 30, "resolution": 10
}
},
{
"name": "Full - Lớn (1 năm, 10m, 60 scenes)",
"config": {
"min_lon": 105.5, "min_lat": 9.2, "max_lon": 106.4, "max_lat": 10.0,
"start_date": "2022-09-01", "end_date": "2023-10-01",
"max_scenes": 60, "cloud_cover": 50, "resolution": 10
}
}
]
}
@app.get("/api/training/status", response_model=TrainingStatus)
async def get_training_status():
"""Kiểm tra trạng thái training"""
return training_status
@app.post("/api/training/start")
async def start_training(config: TrainingConfig, background_tasks: BackgroundTasks):
"""Bắt đầu training với config đã chọn"""
global training_status
if training_status["is_training"]:
raise HTTPException(status_code=400, detail="Training đang chạy, vui lòng đợi")
# Reset status
training_status = {
"is_training": True,
"progress": "Đang khởi tạo...",
"error": None,
"result": None,
"start_time": datetime.now().isoformat(),
"end_time": None
}
# Run training in background
background_tasks.add_task(run_training, config)
return {"message": "Training đã bắt đầu", "status": training_status}
@app.post("/api/training/stop")
async def stop_training():
"""Dừng training (nếu đang chạy)"""
global training_status
training_status["is_training"] = False
training_status["error"] = "Đã dừng bởi người dùng"
training_status["end_time"] = datetime.now().isoformat()
return {"message": "Training đã dừng"}
@app.get("/api/models/list")
async def list_models():
"""Liệt kê các model đã train"""
model_dir = Path("model_train")
if not model_dir.exists():
return {"models": []}
models = []
for model_file in model_dir.glob("*.joblib"):
info_file = model_file.with_suffix('.json')
info = {}
if info_file.exists():
with open(info_file) as f:
info = json.load(f)
models.append({
"filename": model_file.name,
"created": datetime.fromtimestamp(model_file.stat().st_mtime).isoformat(),
"size_mb": round(model_file.stat().st_size / 1024 / 1024, 2),
"info": info
})
# Sort by creation time (newest first)
models.sort(key=lambda x: x["created"], reverse=True)
return {"models": models}
async def run_training(config: TrainingConfig):
"""Chạy training process"""
global training_status
try:
training_status["progress"] = "Đang import thư viện..."
# Import training module
from train_module import train_model
training_status["progress"] = "Đang load dữ liệu Sentinel-2..."
# Run training
result = train_model(
bbox=[config.min_lon, config.min_lat, config.max_lon, config.max_lat],
time_range=f"{config.start_date}/{config.end_date}",
max_scenes=config.max_scenes,
cloud_cover=config.cloud_cover,
resolution=config.resolution,
training_shapefile=config.training_shapefile,
n_estimators=config.n_estimators,
max_depth=config.max_depth,
learning_rate=config.learning_rate,
use_gpu=config.use_gpu,
status_callback=lambda msg: update_progress(msg)
)
training_status["is_training"] = False
training_status["progress"] = "Hoàn thành!"
training_status["result"] = result
training_status["end_time"] = datetime.now().isoformat()
except Exception as e:
training_status["is_training"] = False
training_status["error"] = str(e)
training_status["progress"] = f"Lỗi: {str(e)}"
training_status["end_time"] = datetime.now().isoformat()
import traceback
print(traceback.format_exc())
def update_progress(message: str):
"""Cập nhật progress message"""
global training_status
training_status["progress"] = message
print(f"[PROGRESS] {message}")
if __name__ == "__main__":
print("=" * 70)
print("🚀 LAND CLASSIFICATION TRAINING API SERVER")
print("=" * 70)
print("\n📍 Endpoints:")
print(" - Web Interface: http://localhost:8000")
print(" - API Docs: http://localhost:8000/docs")
print(" - Start Training: POST http://localhost:8000/api/training/start")
print(" - Check Status: GET http://localhost:8000/api/training/status")
print("\n" + "=" * 70)
uvicorn.run(app, host="0.0.0.0", port=8000, log_level="info")
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3c05fa531f6c5e9a79b645bacea70e88e4edce5d1a80f09559e8ee1baec93082
size 208484
oid sha256:eb89e36fa4f4c740d5a079baf53b02bec2ef1120ac770bed6b6be4aa9fc99a1b
size 208470
+3
View File
@@ -0,0 +1,3 @@
fastapi
uvicorn
pydantic