HishaamA commited on
Commit
a6f073a
·
verified ·
1 Parent(s): eb4bab6

Update long-form proposal renderer for architecture diagram

Browse files
Files changed (1) hide show
  1. scripts/render_longform_proposal.py +85 -0
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