File size: 2,110 Bytes
f28d994
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
"""Fig 2: two-stage stacking framework (schematic). Pure matplotlib patches."""
from pathlib import Path
import sys

import matplotlib.pyplot as plt
from matplotlib.patches import FancyBboxPatch, FancyArrowPatch

sys.path.insert(0, str(Path(__file__).resolve().parent))
from plot_style import apply, save, PALETTE_DEEP as C  # noqa: E402

apply()
ROOT = Path(__file__).resolve().parents[2]
FIG = ROOT / "reports" / "figures"

fig, ax = plt.subplots(figsize=(13, 5))
ax.set_xlim(0, 13)
ax.set_ylim(0, 5)
ax.axis("off")


def box(x, y, w, h, text, color, fc_alpha=0.18, fs=10):
    p = FancyBboxPatch((x, y), w, h, boxstyle="round,pad=0.08,rounding_size=0.15",
                       fc=color, ec=color, alpha=fc_alpha, lw=2)
    ax.add_patch(p)
    ax.text(x + w / 2, y + h / 2, text, ha="center", va="center", fontsize=fs, fontweight="bold")


def arrow(x1, y1, x2, y2):
    ax.add_patch(FancyArrowPatch((x1, y1), (x2, y2), arrowstyle="-|>", mutation_scale=18, lw=2, color="black"))


# Stage 1: score producers
ax.text(1.25, 4.7, "Stage 1: Score producers", ha="center", fontsize=11, fontweight="bold")
for i, (t, col) in enumerate([("LightGCN", C[0]), ("BPR-MF", C[1]), ("DeepWalk", C[2]), ("Node2Vec", C[3])]):
    box(0.2, 3.4 - i * 0.8, 2.1, 0.6, t, col, fs=9.5)

# Feature engineering
ax.text(5.9, 4.7, "Feature engineering (259-d)", ha="center", fontsize=11, fontweight="bold")
for i, (t, col) in enumerate([("higher-order prop. (69)", C[3]), ("random-walk blocks (88)", C[2]),
                              ("explicit graph / meta-path (18)", C[0]), ("content-rich + BPR + ranks (84)", C[1])]):
    box(4.6, 3.4 - i * 0.8, 2.6, 0.6, t, col, fs=8.6)

# Stage 2
ax.text(9.9, 4.7, "Stage 2 / Decision", ha="center", fontsize=11, fontweight="bold")
box(8.3, 3.0, 3.2, 1.0, "LightGBM\nmeta-learner", C[4], fs=10)
box(8.3, 1.4, 3.2, 1.0, "rank-cutoff decision\n(top-50% + known pos.)", C[5], fs=9)

# arrows
arrow(2.3, 3.1, 4.6, 3.1)
arrow(7.2, 3.5, 8.3, 3.5)
arrow(9.9, 3.0, 9.9, 2.4)

ax.set_title("Two-stage stacking framework", fontsize=13)
save(fig, "fig2_framework", FIG)
print("saved fig2_framework")