power-load-forecasting / code /generate_master_benchmark.py
neitpm's picture
Release: reproducible power load forecasting KAN artifacts and benchmark manifests
04cc18f verified
Raw History Blame Contribute Delete
8.4 kB
# -*- coding: utf-8 -*-
"""
=============================================================================
BẢNG TỔNG HỢP SO SÁNH TOÀN DIỆN CÁC MÔ HÌNH DỰ BÁO PHỤ TẢI ĐIỆN 30 PHÚT
(PHIÊN BẢN CHUẨN MỰC HỌC THUẬT CHO LUẬN VĂN THẠC SĨ)
=============================================================================
Đặc điểm hiệu chỉnh:
1. Đồng nhất mốc thời gian chính xác theo preprocessing_summary.json:
- Tập kiểm thử: 02/11/2024 15:30:00 -> 30/08/2025 23:30:00 (14,440 mẫu, lọc 14,385 mẫu hợp lệ).
2. Chuẩn hóa diễn đạt tính liên tục:
- "14.385 mẫu hợp lệ, được phân thành 16 đoạn thời gian liên tục; bootstrap không vượt qua các khoảng đứt gãy."
3. Minh bạch phương pháp Ensemble:
- Sử dụng Trung bình đều cố định (Uniform Simple Average, trọng số w_i = 1/5 cho cả 5 seeds),
hoàn toàn không dùng bất kỳ thông tin nào từ tập test để tối ưu trọng số (Zero Data Leakage).
4. Công thức cải thiện:
Improvement (%) = (Metric_Baseline - Metric_Model) / Metric_Baseline * 100%
=============================================================================
"""
import os
import sys
import json
from pathlib import Path
if sys.platform.startswith("win"):
try:
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
except Exception:
pass
import pandas as pd
import numpy as np
def generate_master_benchmark_table():
reports_dir = Path("output_preprocessing/reports")
# 1. Đọc kết quả baseline
df_base = pd.read_csv(reports_dir / "baseline_models_comparison.csv")
# 2. Đọc kết quả KAN 5 seed
with open(reports_dir / "kan_multi_seed_stability.json", "r", encoding="utf-8") as f:
kan_data = json.load(f)
stats = kan_data["summary_statistics"]
ens = kan_data["ensemble_5_seeds"]["metrics"]
master_rows = []
for _, row in df_base.iterrows():
master_rows.append({
"Phân nhóm": "Baseline / ML Truyền thống",
"Mô hình": row["model_name"],
"MAE (kW)": f"{row['MAE_kW']:.2f}",
"RMSE (kW)": f"{row['RMSE_kW']:.2f}",
"MAE (MW)": f"{row['MAE_MW']:.4f}",
"RMSE (MW)": f"{row['RMSE_MW']:.4f}",
"sMAPE (%)": f"{row['sMAPE_pct']:.2f}%",
"R2 Score": f"{row['R2_score']:.4f}",
"ΔMAE vs Persistence (%)": f"{((598.36 - row['MAE_kW']) / 598.36 * 100):+.2f}%" if "Persistence" not in row["model_name"] else "Baseline (0.00%)",
"ΔRMSE vs Persistence (%)": f"{((1160.44 - row['RMSE_kW']) / 1160.44 * 100):+.2f}%" if "Persistence" not in row["model_name"] else "Baseline (0.00%)",
})
# Dòng 8: Đánh giá độ ổn định của mô hình đơn KAN qua 5 seed (Mean ± Std)
master_rows.append({
"Phân nhóm": "Thống kê độ ổn định (5 Seed)",
"Mô hình": "8. Residual KAN đơn lẻ (Mean ± Std qua 5 Seed)*",
"MAE (kW)": f"{stats['MAE_kW_mean']:.2f} ± {stats['MAE_kW_std']:.2f}",
"RMSE (kW)": f"{stats['RMSE_kW_mean']:.2f} ± {stats['RMSE_kW_std']:.2f}",
"MAE (MW)": f"{stats['MAE_kW_mean']/1000:.4f}",
"RMSE (MW)": f"{stats['RMSE_kW_mean']/1000:.4f}",
"sMAPE (%)": f"{stats['sMAPE_pct_mean']:.2f}% ± {stats['sMAPE_pct_std']:.2f}%",
"R2 Score": f"{stats['R2_score_mean']:.4f} ± {stats['R2_score_std']:.4f}",
"ΔMAE vs Persistence (%)": f"+{stats['Improvement_MAE_pct_mean']:.2f}%",
"ΔRMSE vs Persistence (%)": f"+{stats['Improvement_RMSE_pct_mean']:.2f}%"
})
# Dòng 9: Mô hình kết hợp trung bình đều (Uniform Ensemble)
master_rows.append({
"Phân nhóm": "Mô hình đề xuất (Deep Learning)",
"Mô hình": "9. Residual KAN Ensemble (Trung bình đều 5 Seed)**",
"MAE (kW)": f"{ens['MAE_kW']:.2f}",
"RMSE (kW)": f"{ens['RMSE_kW']:.2f}",
"MAE (MW)": f"{ens['MAE_MW']:.4f}",
"RMSE (MW)": f"{ens['RMSE_MW']:.4f}",
"sMAPE (%)": f"{ens['sMAPE_pct']:.2f}%",
"R2 Score": f"{ens['R2_score']:.4f}",
"ΔMAE vs Persistence (%)": f"+{ens['Improvement_MAE_pct']:.2f}%",
"ΔRMSE vs Persistence (%)": f"+{ens['Improvement_RMSE_pct']:.2f}%"
})
df_master = pd.DataFrame(master_rows)
df_master.to_csv(reports_dir / "master_model_comparison_benchmark.csv", index=False, encoding="utf-8-sig")
headers = list(df_master.columns)
lines = [
"| " + " | ".join(headers) + " |",
"| " + " | ".join(["---"] * len(headers)) + " |"
]
for _, r in df_master.iterrows():
lines.append("| " + " | ".join([str(r[c]) for c in headers]) + " |")
md_table = "\n".join(lines)
notes = """
### Ghi chú phương pháp và phạm vi áp dụng (Dành cho Luận văn Thạc sĩ):
1. **Phạm vi dữ liệu thực nghiệm:**
- Tập kiểm thử gồm **14.385 mẫu hợp lệ**, được phân thành **16 phân đoạn thời gian liên tục**; quy trình bootstrap kiểm định không vượt qua các khoảng đứt gãy dữ liệu.
- Khoảng thời gian kiểm thử chính xác: **02/11/2024 15:30:00 đến 30/08/2025 23:30:00**.
- Đối tượng kiểm định: **Lộ 480 Trạm biến áp 224 Tân Hưng** (Công ty Điện lực Tây Ninh).
- *Lưu ý học thuật:* Kết quả phản ánh hiệu năng trên tập kiểm định cụ thể này; việc mở rộng sang các xuất tuyến khác (như trạm Suối Ngô hoặc các năm khác) cần có thực nghiệm tái thẩm định riêng biệt.
2. **Công thức tính tỷ lệ cải thiện:**
$$\\text{Improvement (\\%)} = \\frac{\\text{Metric}_{\\text{Persistence}} - \\text{Metric}_{\\text{Model}}}{\\text{Metric}_{\\text{Persistence}}} \\times 100\\%$$
- Giá trị **dương (+)**: Mô hình giảm sai số (tốt hơn Persistence).
- Giá trị **âm (-)**: Mô hình có sai số lớn hơn Persistence (kém hơn).
3. **Phân biệt hai dòng kết quả KAN:**
- `(*)` **Dòng 8 (Mean ± Std):** Thống kê độ ổn định của mô hình đơn qua 5 lần khởi tạo ngẫu nhiên khác nhau (`seeds = [42, 101, 2024, 7, 999]`), thể hiện tính hội tụ vững chắc của mạng.
- `(**)` **Dòng 9 (Ensemble):** Mô hình kết hợp bằng **trung bình đều cố định** $(\\hat{y}_{\\text{ens}} = \\frac{1}{5}\\sum_{i=1}^5 \\hat{y}_i)$, tuyệt đối không tối ưu hóa trọng số trên tập kiểm thử nhằm đảm bảo khách quan (Zero Data Leakage).
4. **Đánh giá toàn diện:**
- **Residual KAN** đạt ưu thế rõ rệt và vượt trội về **MAE, RMSE và R²**.
- **Persistence Naive** vẫn giữ vị trí dẫn đầu về **sMAPE (13.35%)** và là mốc baseline bắt buộc phải có để đối chiếu trong bài toán dự báo phụ tải ngắn hạn 30 phút.
5. **Kiểm soát rò rỉ dữ liệu (Data Leakage Control):**
- Bộ điền khuyết thiếu (`SimpleImputer`) và bộ chuẩn hóa (`StandardScaler`) được tính toán (`fit`) **nghiêm ngặt chỉ trên tập Train** (giai đoạn 03/2020 đến 01/2024), sau đó chỉ áp dụng phép chuyển đổi (`transform`) sang tập Validation và Test.
- Các siêu tham số dừng sớm (Early Stopping) được theo dõi độc lập trên tập Validation (01/2024 đến 11/2024). Tập Test tuyệt đối không tham gia vào bất kỳ khâu huấn luyện hay điều chỉnh ngưỡng nào.
"""
with open(reports_dir / "master_model_comparison_benchmark.md", "w", encoding="utf-8") as f:
f.write("# BẢNG TỔNG HỢP ĐỐI CHIẾU MÔ HÌNH DỰ BÁO PHỤ TẢI (TRẠM 224 TÂN HƯNG)\n\n")
f.write(md_table)
f.write("\n\n" + notes.strip() + "\n")
print("✅ Đã cập nhật bảng tổng hợp chuẩn mực học thuật hoàn thiện tại:")
print(f" - {reports_dir / 'master_model_comparison_benchmark.csv'}")
print(f" - {reports_dir / 'master_model_comparison_benchmark.md'}")
if __name__ == "__main__":
generate_master_benchmark_table()