| """Figure 4 — Final pipeline architecture. |
| |
| Five input streams converge into a LightGBM OOF stacker, a rank-cutoff top-50% decision, |
| and the submission. The high-order stream carries the two propagation formulae |
| H_k = R C^k and G_k = S R C^k rendered with mathtext. |
| """ |
| from pathlib import Path |
| import matplotlib.pyplot as plt |
| from matplotlib.patches import FancyBboxPatch, FancyArrowPatch |
| from style import apply, save, PALETTE as C, COL2 |
|
|
| KEY = "fig4_architecture" |
| TITLE = "Figure 4. Final pipeline architecture" |
|
|
|
|
| def _box(ax, x, y, w, h, text, color, fs=7.6, fc_alpha=0.16, weight="bold"): |
| ax.add_patch(FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.06,rounding_size=0.12", |
| fc=color, ec=color, alpha=fc_alpha, lw=1.5)) |
| ax.text(x + w / 2, y + h / 2, text, ha="center", va="center", fontsize=fs, |
| fontweight=weight, color="black") |
|
|
|
|
| def _arrow(ax, a, b, color="black", lw=1.3): |
| ax.add_patch(FancyArrowPatch(a, b, arrowstyle="-|>", mutation_scale=12, color=color, lw=lw)) |
|
|
|
|
| def make(root, out): |
| apply() |
| fig, ax = plt.subplots(figsize=(COL2, 4.3)) |
| ax.set_xlim(0, 13.6); ax.set_ylim(0, 6.2); ax.axis("off") |
|
|
| |
| _box(ax, 0.2, 2.7, 1.9, 0.9, "Official\nData", C[7], fs=8.5) |
|
|
| |
| streams = [ |
| (4.6, "Author–Paper graph", "LightGCN score / rank", C[0]), |
| (3.7, "Coauthor + citation graph", "explicit graph / meta-path feats", C[1]), |
| (2.8, "feature.pkl", "content sim. + rich profile", C[2]), |
| (1.9, "mixed graph", "DeepWalk / Node2Vec pair feats", C[3]), |
| (1.0, "$R\\,C^{k}$ and $S\\,R\\,C^{k}$", "high-order propagation feats", C[4]), |
| ] |
| for y, src, feat, col in streams: |
| _box(ax, 3.7, y - 0.30, 3.4, 0.62, f"{feat}", col, fs=7.2) |
| ax.text(3.7 + 3.4 + 0.08, y, src, ha="left", va="center", fontsize=6.6, color="dimgray") |
| _arrow(ax, (2.1, 3.15), (3.7, y)) |
|
|
| |
| ax.add_patch(FancyBboxPatch((8.45, 0.30), 3.15, 1.30, |
| boxstyle="round,pad=0.06,rounding_size=0.12", |
| fc=C[4], ec=C[4], alpha=0.10, lw=1.3)) |
| ax.text(8.55, 1.42, "high-order propagation", fontsize=7.2, color=C[4], fontweight="bold") |
| ax.text(10.0, 1.10, "$H_k = R\\,C^{\\,k}$", fontsize=11, color=C[4], ha="center") |
| ax.text(10.0, 0.72, "$G_k = S\\,R\\,C^{\\,k}$", fontsize=11, color=C[4], ha="center") |
| ax.text(10.0, 0.42, |
| "$R$: author–paper $C$: citation $S$: coauthor", |
| fontsize=6.2, color="dimgray", ha="center") |
| _arrow(ax, (7.1, 1.0), (8.45, 0.95), color=C[4], lw=1.2) |
|
|
| |
| _arrow(ax, (7.1, 2.8), (9.4, 4.3)) |
| _box(ax, 9.4, 3.85, 2.5, 0.95, "LightGBM\nOOF stacker\n(259-d)", C[5], fs=8) |
| _arrow(ax, (10.65, 3.85), (10.65, 3.05)) |
| _box(ax, 9.4, 2.15, 2.5, 0.85, "rank cutoff\ntop 50% + known pos.", C[6], fs=7.6) |
| _arrow(ax, (11.9, 2.55), (12.6, 2.55)) |
| _box(ax, 12.5, 2.10, 1.0, 0.9, "sub.", C[7], fs=8) |
|
|
| ax.set_title("Final two-stage stacking pipeline", 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=["schematic"], |
| caption=( |
| "Final pipeline. Five feature streams — LightGCN score/rank, explicit graph and meta-path " |
| "features, content similarity and rich author–content profiles, DeepWalk/Node2Vec pair " |
| "features, and high-order propagation features — are concatenated into a 259-d vector and " |
| "fed to a LightGBM out-of-fold stacker. A rank-cutoff decision (top 50% positive, known " |
| "positives forced to 1) produces the submission. High-order features are defined by " |
| "$H_k = R\\,C^{k}$ (author reaches papers $k$ citation hops away) and $G_k = S\\,R\\,C^{k}$ " |
| "(same, mediated by coauthorship), where $R$ is the author–paper matrix, $C$ the citation " |
| "matrix and $S$ the coauthorship matrix.")) |
|
|
|
|
| if __name__ == "__main__": |
| from style import ensure_dirs |
| r = make(Path("."), ensure_dirs(Path("."))) |
| print(r["key"], r["status"]) |
|
|