| """Plot 4-grid normalized confusion matrices for QnA evaluation.""" |
| import numpy as np |
| import matplotlib.pyplot as plt |
| import matplotlib.gridspec as gridspec |
| from pathlib import Path |
|
|
| |
| |
| SYSTEMS = { |
| "Ours": dict(FP=5, FN=8), |
| "Claude": dict(FP=7, FN=10), |
| "GPT": dict(FP=9, FN=8), |
| "Grok": dict(FP=8, FN=7), |
| } |
| N_POS = N_NEG = 50 |
|
|
|
|
| def _make_cm(fp, fn): |
| tp = N_POS - fn |
| tn = N_NEG - fp |
| |
| |
| |
| raw = np.array([[tp, fn], [fp, tn]], dtype=float) |
| |
| norm = raw / raw.sum(axis=1, keepdims=True) |
| return norm, raw.astype(int) |
|
|
|
|
| CMAP = "Blues" |
| LABELS = ["Positive", "Negative"] |
|
|
| fig, axes = plt.subplots(2, 2, figsize=(9, 7.5)) |
| axes = axes.flatten() |
|
|
| for ax, (name, vals) in zip(axes, SYSTEMS.items()): |
| cm_norm, cm_raw = _make_cm(vals["FP"], vals["FN"]) |
|
|
| im = ax.imshow(cm_norm, cmap=CMAP, vmin=0.0, vmax=1.0, aspect="auto") |
|
|
| ax.set_xticks([0, 1]) |
| ax.set_xticklabels(LABELS, fontsize=10) |
| ax.set_yticks([0, 1]) |
| ax.set_yticklabels(LABELS, fontsize=10, rotation=90, va="center") |
| ax.set_xlabel("Predicted", fontsize=10) |
| ax.set_ylabel("Actual", fontsize=10) |
| ax.set_title(name, fontsize=13, fontweight="bold", pad=8) |
|
|
| row_labels = [["TP", "FN"], ["FP", "TN"]] |
| for i in range(2): |
| for j in range(2): |
| v_norm = cm_norm[i, j] |
| v_raw = cm_raw[i, j] |
| txt_color = "white" if v_norm > 0.55 else "black" |
| ax.text( |
| j, i, |
| f"{row_labels[i][j]}\n{v_norm:.2f}\n({v_raw})", |
| ha="center", va="center", |
| color=txt_color, |
| fontsize=11, fontweight="bold", |
| linespacing=1.4, |
| ) |
|
|
| |
| fig.subplots_adjust(right=0.88, hspace=0.38, wspace=0.36) |
| cbar_ax = fig.add_axes([0.91, 0.12, 0.025, 0.75]) |
| fig.colorbar(im, cax=cbar_ax, label="Normalised rate") |
|
|
| fig.suptitle("Normalised Confusion Matrices — QnA Evaluation", |
| fontsize=14, fontweight="bold", y=1.01) |
|
|
| out = Path(__file__).resolve().parents[1] / "artifacts" / "results" / "confusion_matrices.png" |
| out.parent.mkdir(parents=True, exist_ok=True) |
| plt.savefig(out, dpi=150, bbox_inches="tight") |
| print(f"Saved: {out}") |
| plt.show() |
|
|