bachelor-thesis/evaluation/06_sead_details.py

147 lines
4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
06_sead_details.py Tiefenanalyse der Ensemble-Entscheidungen
==============================================================
Visualisiert pro Lauf:
- Oben: Entwicklung der SEAD-Gewichte (w_i) pro Detektor
- Unten: Einzel-Anomalie-Scores (s_i) und aggregierter Gesamt-Score
- Hintergrund: Ground-Truth Injektionsfenster
"""
import sys
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
sys.path.insert(0, ".")
from config import *
DETECTORS = ["MAD", "RRCF-fast", "RRCF-mid", "RRCF-slow", "COPOD"]
def _to_utc(ts):
ts = pd.Timestamp(ts)
return ts.tz_localize("UTC") if ts.tzinfo is None else ts.tz_convert("UTC")
def plot_sead_internals(run_key: str, windows_df: pd.DataFrame):
print(f" Analysiere SEAD-Internals für {run_key}...")
try:
anom = load_anomalies(run_key)
except Exception as e:
print(f" Fehler: {e}")
return
if anom.empty:
return
anom["timestamp"] = anom["timestamp"].apply(_to_utc)
inj = windows_df[windows_df["run"] == run_key].copy()
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 10), sharex=True)
colors = plt.cm.tab10(np.linspace(0, 1, len(DETECTORS)))
det_color_map = {det: colors[i] for i, det in enumerate(DETECTORS)}
# --- Subplot 1: SEAD Gewichte ---
for det in DETECTORS:
col = f"{det}_weight"
if col in anom.columns:
ax1.plot(
anom["timestamp"],
anom[col],
label=f"w_{det}",
color=det_color_map[det],
lw=1.5,
)
ax1.axhline(
0.2, color="gray", linestyle=":", alpha=0.6, label="Gleichgewicht (0.2)"
)
ax1.set_ylabel("SEAD Gewicht $w_i$")
ax1.set_ylim(0, 0.7)
ax1.set_title(f"SEAD Ensemble Dynamik: {run_key}")
ax1.legend(loc="upper right", ncol=3, fontsize=9)
# --- Subplot 2: Anomalie Scores ---
for det in DETECTORS:
col = f"{det}_score"
if col in anom.columns:
ax2.plot(
anom["timestamp"],
anom[col],
color=det_color_map[det],
lw=0.8,
alpha=0.5,
linestyle="--",
)
ax2.plot(
anom["timestamp"],
anom["score"],
color="black",
lw=2.0,
label="Aggregierter Score (Pipeline)",
)
ax2.axhline(
0.5,
color="red",
linestyle="--",
lw=1.0,
alpha=0.7,
label="Alarm-Schwellenwert (0.5)",
)
ax2.set_ylabel("Anomalie Score $s_i$")
ax2.set_ylim(0, 1.1)
ax2.set_xlabel("Zeit [UTC]")
ax2.legend(loc="upper right", fontsize=9)
# --- Ground Truth Shading ---
for _, row in inj.iterrows():
t0, t1 = _to_utc(row["t_inj"]), _to_utc(row["t_stop"])
for ax in [ax1, ax2]:
ax.axvspan(t0, t1, color="red", alpha=0.08, zorder=0)
if ax == ax1:
ax.text(
t0,
ax.get_ylim()[1] * 0.95,
row["scenario"],
rotation=90,
color="darkred",
fontsize=7,
va="top",
alpha=0.6,
)
for ax in [ax1, ax2]:
ax.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M"))
ax.grid(True, alpha=0.2)
plt.tight_layout()
save_fig(f"06_sead_details_{run_key}")
def main():
print_section("06 SEAD Gewichte & Scores Analyse")
try:
windows_df = pd.read_csv(OUTPUT_DIR / "injection_windows.csv")
except:
print(" Fehler: injection_windows.csv nicht gefunden.")
return
sample_runs = ["full_cycle_run1", "high_bw_run1", "high_iops_run1"]
for rk in sample_runs:
if rk in RUNS:
plot_sead_internals(rk, windows_df)
print(
f"\n→ SEAD Detail-Plots unter {OUTPUT_DIR}/06_sead_details_*.png gespeichert."
)
if __name__ == "__main__":
main()