實戰:最佳化求解 API
Vibe Prompt
「幫我用 FastAPI 建立一個通用最佳化 API:使用者輸入目標函數與範圍,後端用模擬退火求解。」
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import random, math
app = FastAPI(title="最佳化求解 API")
class OptimizeRequest(BaseModel):
objective: str # 數學表達式,如 "x**2 + y**2"
bounds: list[list[float]] # [[x_min,x_max], [y_min,y_max]]
algorithm: str = "simulated_annealing"
class OptimizeResponse(BaseModel):
best_solution: list[float]
best_value: float
algorithm: str
iterations: int
@app.post("/optimize", response_model=OptimizeResponse)
def optimize(req: OptimizeRequest):
dim = len(req.bounds)
def objective(x):
# 安全 eval
env = {"x": x} if dim == 1 else {f"x{i}": x[i] for i in range(dim)}
env.update({"sin": math.sin, "cos": math.cos, "sqrt": math.sqrt,
"abs": abs, "sum": sum, "pow": pow})
return eval(req.objective, {"__builtins__": {}}, env)
best = None
best_val = float('inf')
if req.algorithm == "simulated_annealing":
current = [random.uniform(b[0], b[1]) for b in req.bounds]
current_val = objective(current)
temp = 1000
iterations = 0
while temp > 0.01:
neighbor = [current[i] + random.uniform(-1, 1) for i in range(dim)]
neighbor = [max(req.bounds[i][0], min(req.bounds[i][1], neighbor[i]))
for i in range(dim)]
neighbor_val = objective(neighbor)
delta = neighbor_val - current_val
if delta < 0 or random.random() < math.exp(-delta/temp):
current = neighbor
current_val = neighbor_val
if current_val < best_val:
best = current[:]
best_val = current_val
temp *= 0.995
iterations += 1
return OptimizeResponse(
best_solution=best, best_value=round(best_val, 6),
algorithm=req.algorithm, iterations=iterations
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
本日總結
- ✅ 模擬退火
- ✅ 遺傳演算法
- ✅ PSO
- ✅ 超參數調優
- ✅ 最佳化 API
API 設計原則
端點設計
| 方法 | 端點 | 說明 |
|------|------|------|
| POST | /optimize | 執行最佳化任務 |
| GET | /optimize/{task_id} | 查詢任務狀態 |
| GET | /algorithms | 列出支援的演算法 |
| POST | /compare | 比較多種演算法 |
演算法選用策略
def select_algorithm(problem_type, dim, eval_budget):
"""根據問題特性自動推薦最佳化演算法"""
if dim <= 2 and eval_budget >= 10000:
return 'grid_search' # 低維度可窮舉
elif problem_type == 'discrete':
return 'simulated_annealing' # 離散問題
elif problem_type == 'continuous' and dim <= 20:
return 'differential_evolution' # 連續中等維度
elif problem_type == 'continuous':
return 'pso' # 連續高維度
elif eval_budget <= 500:
return 'genetic_algorithm' # 有限預算
else:
return 'simulated_annealing' # 通用預設
安全考量
- 沙箱執行:使用者提供的目標函數用
eval()執行,需限制命名空間 - 超時控制:每個最佳化任務設定時間上限
- 資源限制:限制最大迭代次數與記憶體使用
- 輸入驗證:確保 bounds 格式正確且合理
- 防止濫用:加入 API Rate Limiting
關鍵要點
- ✅ FastAPI 讓建立最佳化 API 只需 50 行核心程式碼
- ✅
eval()執行使用者函數時務必限制命名空間({"__builtins__": {}}) - ✅ 不同問題特性需要不同的演算法,沒有萬能解
- ✅ API 設計應考慮擴展性,方便加入新演算法
- ✅ 生產環境需要加入超時控制、日誌、錯誤處理
課程總結
你已經完成了元啟發式最佳化的五堂課程!
| 章節 | 核心技能 | |------|---------| | 1️⃣ 模擬退火 | 冶金退火啟發的機率性搜尋 | | 2️⃣ 遺傳演算法 | 選擇、交叉、突變的演化循環 | | 3️⃣ PSO & DE | 群體智慧與向量差分搜尋 | | 4️⃣ 超參數調優 | 用 SA/GA 自動搜尋 ML 最佳參數 | | 5️⃣ 最佳化 API | 將所有演算法包裝為通用服務 |
下一步
- 研究更先進的演算法:CMA-ES、NSGA-II(多目標)、Bayesian Optimization
- 應用層面:嘗試用元啟發式解決 ML 的 Feature Selection、Network Architecture Search
- 實戰:將你的最佳化 API 部署到雲端,串接前端提供可視化介面
把最佳化演算法包成 API 服務
前面的演算法都是在 Jupyter Notebook 中執行。但真實世界的應用需要讓其他系統可以呼叫——把最佳化演算法包裝成 REST API。
FastAPI 實作
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class OptimizeRequest(BaseModel):
algorithm: str # "GA", "PSO", "SA"
objective: str # JSON 格式的目標函數
bounds: dict # 參數範圍
max_iterations: int
@app.post("/optimize")
async def optimize(req: OptimizeRequest):
if req.algorithm == "GA":
result = run_genetic_algorithm(req.objective, req.bounds, req.max_iterations)
elif req.algorithm == "PSO":
result = run_pso(req.objective, req.bounds, req.max_iterations)
elif req.algorithm == "SA":
result = run_simulated_annealing(req.objective, req.bounds, req.max_iterations)
return {"best_params": result.best, "best_value": result.fitness}
課程總結
這堂元啟發式演算法課你學到了模擬退火、基因演算法、PSO、超參數最佳化到 API 部署——現在你可以用這些演算法解決傳統方法難以處理的最佳化問題。