diff --git a/src/training/plot_metrics.py b/src/training/plot_metrics.py index df97c62..c8db1aa 100644 --- a/src/training/plot_metrics.py +++ b/src/training/plot_metrics.py @@ -25,26 +25,54 @@ sns.set_theme(style="whitegrid", palette="deep", font_scale=1.1) def plot_train_metrics(train_df: pd.DataFrame, out_dir: Path) -> None: - """Plot training metrics: loss, temperature, gates, lr.""" - fig, axes = plt.subplots(2, 2, figsize=(14, 10)) + """Plot training metrics: loss, recall, AP, temperature, gates, lr.""" + fig, axes = plt.subplots(2, 3, figsize=(20, 10)) fig.suptitle("Training Metrics", fontsize=16, fontweight="bold") # 1. Loss. ax = axes[0, 0] - sns.lineplot(data=train_df, x="epoch", y="total", ax=ax, marker="o", linewidth=2) - ax.set_title("Loss") + col = "train_loss" if "train_loss" in train_df.columns else "total" + if col in train_df.columns: + sns.lineplot(data=train_df, x="epoch", y=col, ax=ax, marker="o", linewidth=2) + ax.set_title("Train Loss") ax.set_xlabel("Epoch") ax.set_ylabel("InfoNCE Loss") - # 2. Temperature (tau). + # 2. Recall@K (train). ax = axes[0, 1] - sns.lineplot(data=train_df, x="epoch", y="temperature", ax=ax, marker="s", linewidth=2, color="orange") + for k in [1, 5, 10]: + col = f"r@{k}_q2g" + if col in train_df.columns: + df_valid = train_df.dropna(subset=[col]) + if not df_valid.empty: + sns.lineplot(data=df_valid, x="epoch", y=col, ax=ax, marker="o", linewidth=2, label=f"R@{k}") + ax.set_title("Train Recall@K (drone → sat)") + ax.set_xlabel("Epoch") + ax.set_ylabel("Recall") + ax.set_ylim(0, 1) + ax.legend() + + # 3. Average Precision (train). + ax = axes[0, 2] + if "ap_q2g" in train_df.columns: + df_valid = train_df.dropna(subset=["ap_q2g"]) + if not df_valid.empty: + sns.lineplot(data=df_valid, x="epoch", y="ap_q2g", ax=ax, marker="s", linewidth=2, color="purple") + ax.set_title("Train AP (drone → sat)") + ax.set_xlabel("Epoch") + ax.set_ylabel("AP") + ax.set_ylim(0, 1) + + # 4. Temperature (tau). + ax = axes[1, 0] + if "temperature" in train_df.columns: + sns.lineplot(data=train_df, x="epoch", y="temperature", ax=ax, marker="s", linewidth=2, color="orange") ax.set_title("Temperature (τ)") ax.set_xlabel("Epoch") ax.set_ylabel("τ") - # 3. Gate values. - ax = axes[1, 0] + # 5. Gate values. + ax = axes[1, 1] if "gate_q" in train_df.columns and "gate_g" in train_df.columns: sns.lineplot(data=train_df, x="epoch", y="gate_q", ax=ax, marker="o", linewidth=2, label="gate_q (drone)") sns.lineplot(data=train_df, x="epoch", y="gate_g", ax=ax, marker="s", linewidth=2, label="gate_g (sat)") @@ -54,9 +82,10 @@ def plot_train_metrics(train_df: pd.DataFrame, out_dir: Path) -> None: ax.set_ylabel("Image weight") ax.set_ylim(0, 1) - # 4. Learning rate. - ax = axes[1, 1] - sns.lineplot(data=train_df, x="epoch", y="lr", ax=ax, marker="^", linewidth=2, color="green") + # 6. Learning rate. + ax = axes[1, 2] + if "lr" in train_df.columns: + sns.lineplot(data=train_df, x="epoch", y="lr", ax=ax, marker="^", linewidth=2, color="green") ax.set_title("Learning Rate") ax.set_xlabel("Epoch") ax.set_ylabel("LR")