Update long-form proposal renderer for architecture diagram
Browse files
scripts/render_longform_proposal.py
CHANGED
|
@@ -97,6 +97,90 @@ def make_heavy_vs_student() -> None:
|
|
| 97 |
plt.close(fig)
|
| 98 |
|
| 99 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
def clean_inline(value: str) -> str:
|
| 101 |
value = re.sub(r"!\[[^]]*]\([^)]+\)", "", value)
|
| 102 |
value = re.sub(r"\[([^]]+)]\([^)]+\)", r"\1", value)
|
|
@@ -316,6 +400,7 @@ def main() -> None:
|
|
| 316 |
ASSETS.mkdir(parents=True, exist_ok=True)
|
| 317 |
make_model_evolution()
|
| 318 |
make_heavy_vs_student()
|
|
|
|
| 319 |
render_markdown()
|
| 320 |
print(f"Rendered {OUTPUT}")
|
| 321 |
|
|
|
|
| 97 |
plt.close(fig)
|
| 98 |
|
| 99 |
|
| 100 |
+
def make_final_student_architecture() -> None:
|
| 101 |
+
"""Draw the exact deployed tensor path, including recurrent state and inactive heads."""
|
| 102 |
+
fig, ax = plt.subplots(figsize=(15.5, 8.6))
|
| 103 |
+
fig.patch.set_facecolor("white")
|
| 104 |
+
ax.set_xlim(0, 15.5)
|
| 105 |
+
ax.set_ylim(0, 8.6)
|
| 106 |
+
ax.axis("off")
|
| 107 |
+
|
| 108 |
+
def box(x, y, w, h, title, body, color=BLUE, dashed=False):
|
| 109 |
+
patch = plt.Rectangle(
|
| 110 |
+
(x, y), w, h, facecolor="white", edgecolor=color, linewidth=1.8,
|
| 111 |
+
linestyle="--" if dashed else "-", joinstyle="round"
|
| 112 |
+
)
|
| 113 |
+
ax.add_patch(patch)
|
| 114 |
+
ax.text(x + 0.12, y + h - 0.18, title, va="top", fontsize=10,
|
| 115 |
+
fontweight="bold", color=color)
|
| 116 |
+
ax.text(x + 0.12, y + h - 0.55, body, va="top", fontsize=8.1,
|
| 117 |
+
color=NAVY, linespacing=1.28)
|
| 118 |
+
|
| 119 |
+
def arrow(x1, y1, x2, y2, color=NAVY, style="-"):
|
| 120 |
+
ax.annotate("", xy=(x2, y2), xytext=(x1, y1),
|
| 121 |
+
arrowprops=dict(arrowstyle="->", color=color, lw=1.4,
|
| 122 |
+
linestyle=style, shrinkA=2, shrinkB=2))
|
| 123 |
+
|
| 124 |
+
ax.text(0.35, 8.25, "Final OrbitSight CPU student — exact deployed architecture",
|
| 125 |
+
fontsize=17, fontweight="bold", color=NAVY)
|
| 126 |
+
ax.text(0.35, 7.88, "Solid boxes execute at inference; dashed boxes are stored/training-only.",
|
| 127 |
+
fontsize=9, color=GREY)
|
| 128 |
+
|
| 129 |
+
box(0.35, 5.25, 1.65, 1.35, "40 ms input", "3×640×640\npositive count\nnegative count\nrecency", CYAN)
|
| 130 |
+
box(2.35, 5.25, 1.65, 1.35, "Stem · 120 p", "3×3 Conv 3→4\nBatchNorm + SiLU\n4×640×640")
|
| 131 |
+
arrow(2.0, 5.93, 2.35, 5.93)
|
| 132 |
+
|
| 133 |
+
stages = [
|
| 134 |
+
(4.35, "Stage 1", "down 4→4 · s2\nConvLSTM d1\n4×320×320\n1,324 p"),
|
| 135 |
+
(6.35, "Stage 2", "down 4→8 · s2\nConvLSTM d2\n8×160×160\n4,952 p"),
|
| 136 |
+
(8.35, "Stage 3", "down 8→16 · s2\nConvLSTM d4\n16×80×80\n19,696 p"),
|
| 137 |
+
(10.35, "Stage 4", "down 16→32 · s2\nConvLSTM d8\n32×40×40\n78,560 p"),
|
| 138 |
+
]
|
| 139 |
+
for x, title, body in stages:
|
| 140 |
+
box(x, 5.05, 1.65, 1.75, title, body)
|
| 141 |
+
for start in [4.0, 6.0, 8.0, 10.0]:
|
| 142 |
+
arrow(start, 5.93, start + 0.35, 5.93)
|
| 143 |
+
|
| 144 |
+
for x, label in [(5.0, "H,C\nstate"), (7.0, "H,C\nstate"),
|
| 145 |
+
(9.0, "H,C\nstate"), (11.0, "H,C\nstate")]:
|
| 146 |
+
ax.annotate(label, xy=(x + 0.17, 6.75), xytext=(x + 0.17, 7.52),
|
| 147 |
+
ha="center", va="center", fontsize=7.5, color=RED,
|
| 148 |
+
arrowprops=dict(arrowstyle="<->", color=RED, lw=1.1))
|
| 149 |
+
|
| 150 |
+
heads = [
|
| 151 |
+
(6.25, 2.55, "Stride-4 head", "8→16→16\nreg 4×160²\nobj 1×160²\n3,573 active p"),
|
| 152 |
+
(8.25, 2.55, "Stride-8 head", "16→16→16\nreg 4×80²\nobj 1×80²\n4,725 active p"),
|
| 153 |
+
(10.25, 2.55, "Stride-16 head", "32→16→16\nreg 4×40²\nobj 1×40²\n7,029 active p"),
|
| 154 |
+
]
|
| 155 |
+
for x, y, title, body in heads:
|
| 156 |
+
box(x, y, 1.75, 1.65, title, body, CYAN)
|
| 157 |
+
arrow(7.15, 5.05, 7.15, 4.2)
|
| 158 |
+
arrow(9.15, 5.05, 9.15, 4.2)
|
| 159 |
+
arrow(11.15, 5.05, 11.15, 4.2)
|
| 160 |
+
|
| 161 |
+
box(12.45, 2.55, 2.45, 1.65, "Exact top-one decoder",
|
| 162 |
+
"33,600 scores → stable argmax\nthreshold 0.10\ndecode only winning cell\nno production NMS", RED)
|
| 163 |
+
for x in [8.0, 10.0, 12.0]:
|
| 164 |
+
arrow(x, 3.37, 12.45, 3.37)
|
| 165 |
+
|
| 166 |
+
box(12.45, 5.05, 2.45, 1.75, "Native output path",
|
| 167 |
+
"inverse area mapping\nDVX size ×0.98\nKalman/coast tracker\nsensor gate → integer row", BLUE)
|
| 168 |
+
arrow(13.68, 4.2, 13.68, 5.05)
|
| 169 |
+
|
| 170 |
+
box(0.35, 0.55, 3.45, 1.25, "Selective training objective",
|
| 171 |
+
"human focal + pixel-inclusive CIoU + aux BCE\n+ matched-teacher confidence/box + empty-window negatives", GREY, dashed=True)
|
| 172 |
+
box(4.15, 0.55, 3.45, 1.25, "Auxiliary segmentation · 9 p",
|
| 173 |
+
"1×1 Conv on stride-4 feature → 1×160×160\nexecuted only while model.training", GREY, dashed=True)
|
| 174 |
+
box(7.95, 0.55, 3.45, 1.25, "Compatibility classification · 15,123 p",
|
| 175 |
+
"three stored cls towers/predictors\ncompute_cls=False; never scored", GREY, dashed=True)
|
| 176 |
+
box(11.75, 0.55, 3.15, 1.25, "Checkpoint contract",
|
| 177 |
+
"135,111 stored parameters\nquality head: off · sensor FiLM: off", GREY, dashed=True)
|
| 178 |
+
|
| 179 |
+
fig.subplots_adjust(left=0.015, right=0.985, top=0.98, bottom=0.03)
|
| 180 |
+
fig.savefig(ASSETS / "final_student_architecture.png", dpi=180, bbox_inches="tight")
|
| 181 |
+
plt.close(fig)
|
| 182 |
+
|
| 183 |
+
|
| 184 |
def clean_inline(value: str) -> str:
|
| 185 |
value = re.sub(r"!\[[^]]*]\([^)]+\)", "", value)
|
| 186 |
value = re.sub(r"\[([^]]+)]\([^)]+\)", r"\1", value)
|
|
|
|
| 400 |
ASSETS.mkdir(parents=True, exist_ok=True)
|
| 401 |
make_model_evolution()
|
| 402 |
make_heavy_vs_student()
|
| 403 |
+
make_final_student_architecture()
|
| 404 |
render_markdown()
|
| 405 |
print(f"Rendered {OUTPUT}")
|
| 406 |
|