NLP-beginner's picture
CS3319 Project 2 final deliverable (public F1 = 0.96626)
f28d994
Raw
History Blame Contribute Delete
4.54 kB
"""Figure 3 — Performance evolution roadmap (hero figure).
Two tracks — validation F1 (solid, filled) and public-leaderboard F1 (dashed, hollow)
— over the method stages, with the three conceptual leaps shaded and annotated.
"""
from pathlib import Path
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import FancyArrowPatch
from style import apply, save, PALETTE as C, COL2 # noqa: E402
KEY = "fig3_roadmap"
TITLE = "Figure 3. Performance evolution roadmap"
# (stage label, module added, val F1, public F1 or None)
STAGES = [
("GNN\nbaseline", "BPR-MF backbone", 0.8850, None),
("LightGCN\nensemble", "collaborative signal", 0.9386, 0.93044),
("+ graph/meta-path\nstacking", "LightGBM stacker", 0.9560, 0.95760),
("+ content\n+ BPR-MF", "semantic content", 0.9593, 0.95996),
("+ DeepWalk\n/ Node2Vec", "random-walk embed.", 0.9621, 0.96252),
("+ 7-block RW\nensemble", "diverse RW blocks", 0.9649, None),
("+ high-order\npropagation","directed citation propagation", 0.9669, 0.96626),
]
def make(root, out):
apply()
labels = [s[0] for s in STAGES]
modules = [s[1] for s in STAGES]
val = np.array([s[2] for s in STAGES])
pub = np.array([s[3] for s in STAGES])
x = np.arange(len(STAGES))
fig, ax = plt.subplots(figsize=(COL2, 4.1))
# three conceptual phases as shaded bands
for (x0, x1, c, t) in [(0, 1.5, C[7], "I · CF signal"),
(1.5, 4.5, C[1], "II · structural stacking"),
(4.5, 6.5, C[2], "III · high-order semantics")]:
ax.axvspan(x0, x1, color=c, alpha=0.06)
ax.text((x0 + x1) / 2, 0.984, t, ha="center", fontsize=7.5, color=c, fontweight="bold")
ax.plot(x, val, "-o", color=C[0], lw=1.9, ms=7, label="validation F1 (seed=202)", zorder=5)
xp = x[pub != None]
ax.plot(xp, pub[pub != None], "--s", color=C[3], lw=1.7, ms=6, mfc="white",
label="public-leaderboard F1", zorder=5)
# module labels above each point
for xi, vi, m in zip(x, val, modules):
ax.annotate(m, (xi, vi), textcoords="offset points", xytext=(0, 12),
ha="center", fontsize=6.8, color="dimgray", rotation=0)
# headline leap brackets (val gains from the LightGCN base)
leaps = [(1, 2, "+0.0174\nstacking"), (4, 5, "+0.0028\nRW blocks"), (5, 6, "+0.0020\nhigh-order")]
for a, b, txt in leaps:
y = val[a] - 0.012
ax.add_patch(FancyArrowPatch((x[a], y), (x[b], y), arrowstyle="<->", color=C[2], lw=1.1))
ax.text((x[a] + x[b]) / 2, y - 0.006, txt, ha="center", fontsize=6.8, color=C[2])
# crown the final
ax.plot(x[-1], val[-1], marker="*", ms=18, color="gold", mec=C[0], mew=0.8, zorder=6)
ax.annotate(f"final\n0.9669 val\n0.9663 public", (x[-1], val[-1]),
xytext=(-8, -34), textcoords="offset points", fontsize=7.2, ha="center",
fontweight="bold", color=C[0],
arrowprops=dict(arrowstyle="->", color=C[0], lw=0.9))
ax.set_xticks(x); ax.set_xticklabels(labels, fontsize=7)
ax.set_ylabel("F1-score"); ax.set_ylim(0.875, 0.990)
ax.legend(loc="lower right", fontsize=7.5)
ax.set_title("Performance evolution: three leaps toward public F1 = 0.9663", fontsize=10)
save(fig, KEY, out)
return dict(key=KEY, title=TITLE, status="ok",
files=[f"{KEY}.pdf", f"{KEY}.png", f"{KEY}.svg"],
sources=["validation_runs/dynamic_summary.csv", "post95/extra/content/node2vec/high_order ablations",
"README public-leaderboard stage table"],
caption=(
"Performance evolution roadmap. Validation F1 (blue) and public-leaderboard F1 (green, "
"dashed) across the method stages. Three conceptual leaps are shaded: (I) LightGCN "
"captures the collaborative-filtering main signal; (II) explicit graph / meta-path features "
"with a LightGBM stacker fill the local-structure blind spot (+0.0174 val); (III) random-walk "
"embeddings and directed high-order citation propagation inject high-order structural "
"semantics. The final model — rich content + 7 random-walk blocks + directed high-order "
"propagation + LightGBM — reaches public F1 = 0.9663."))
if __name__ == "__main__":
from style import ensure_dirs
r = make(Path("."), ensure_dirs(Path(".")))
print(r["key"], r["status"])