# Шаблоны визуализаций для CVGL ## 1. Pareto Front: Params vs R@1 ```python import matplotlib.pyplot as plt import numpy as np methods = { 'Sample4Geo': (88.5, 92.65), 'VimGeo': (50.87, 96.19), 'QDFL': (5.0, 95.00), 'MobileGeo': (28.57, 97.15), '(MGS)²': (100.0, 97.50), 'NADEZHDA': (8.5, None), # target } fig, ax = plt.subplots(figsize=(8, 5)) for name, (params, r1) in methods.items(): if r1 is None: ax.scatter(params, 90, marker='*', s=200, c='#ff7f0e', zorder=5) ax.annotate(f'{name}\n(target)', (params, 90), fontsize=9, ha='center', va='bottom') else: ax.scatter(params, r1, s=100, zorder=4) ax.annotate(name, (params, r1), fontsize=9, textcoords='offset points', xytext=(5, 5)) ax.set_xlabel('Parameters (M)') ax.set_ylabel('R@1 (%) on University-1652') ax.set_title('Accuracy vs Model Size: CVGL Methods') ax.axvspan(0, 10, alpha=0.1, color='green', label='Edge budget (≤10M)') ax.legend() plt.savefig('pareto_params_r1.png', dpi=300, bbox_inches='tight') plt.savefig('pareto_params_r1.pdf', bbox_inches='tight') ``` ## 2. Grouped Bar: R@1 Across Datasets ```python import matplotlib.pyplot as plt import numpy as np methods = ['Sample4Geo', 'VimGeo', 'GeoDTR+', 'CAMP', 'CGSI'] datasets = ['Univ-1652', 'CVUSA', 'CVACT-test'] data = np.array([ [92.65, 98.68, 75.0], # Sample4Geo [0, 96.19, 81.69], # VimGeo [94.67, 95.43, 0], # GeoDTR+ [94.46, 98.97, 0], # CAMP [95.45, 0, 0], # CGSI ]) x = np.arange(len(methods)) width = 0.25 fig, ax = plt.subplots(figsize=(10, 5)) for i, ds in enumerate(datasets): mask = data[:, i] > 0 bars = ax.bar(x[mask] + i * width, data[mask, i], width, label=ds) ax.set_ylabel('R@1 (%)') ax.set_xticks(x + width) ax.set_xticklabels(methods, rotation=15, ha='right') ax.legend() ax.set_ylim(70, 102) plt.savefig('r1_comparison.png', dpi=300, bbox_inches='tight') ``` ## 3. Training Curve with Loss Components ```python import matplotlib.pyplot as plt import numpy as np epochs = np.arange(60) # Simulated progressive staging l_task = 1.5 * np.exp(-0.03 * epochs) + 0.2 l_lupi = np.where(epochs < 10, 0, np.where(epochs < 20, 0.5 * (epochs - 10) / 10, 0.5)) * np.exp(-0.02 * (epochs - 10).clip(0)) l_feat = np.where(epochs < 10, 0, 0.3 * np.exp(-0.02 * (epochs - 10))) l_total = l_task + l_lupi + l_feat fig, ax = plt.subplots(figsize=(8, 4)) ax.plot(epochs, l_task, label='$L_{task}$ (InfoNCE)', linewidth=2) ax.plot(epochs, l_lupi, label='$L_{LUPI}$ (MSE)', linewidth=2, linestyle='--') ax.plot(epochs, l_feat, label='$L_{feat}$ (alignment)', linewidth=2, linestyle=':') ax.plot(epochs, l_total, label='$L_{total}$', linewidth=2.5, color='black', alpha=0.7) ax.axvspan(0, 10, alpha=0.08, color='blue', label='Warmup') ax.axvspan(10, 20, alpha=0.08, color='orange', label='Ramp-up') ax.axvspan(20, 60, alpha=0.05, color='green', label='Full') ax.set_xlabel('Epoch') ax.set_ylabel('Loss') ax.set_title('Progressive Loss Staging (NADEZHDA)') ax.legend(ncol=2, fontsize=9) plt.savefig('training_curve.png', dpi=300, bbox_inches='tight') ``` ## 4. Architecture Block Diagram (matplotlib patches) ```python import matplotlib.pyplot as plt import matplotlib.patches as mpatches fig, ax = plt.subplots(figsize=(14, 6)) ax.set_xlim(0, 14) ax.set_ylim(0, 6) ax.axis('off') def add_block(ax, xy, w, h, label, color, sublabel=''): box = mpatches.FancyBboxPatch(xy, w, h, boxstyle='round,pad=0.1', facecolor=color, edgecolor='black', linewidth=1.5, alpha=0.85) ax.add_patch(box) ax.text(xy[0] + w/2, xy[1] + h/2, label, ha='center', va='center', fontsize=10, fontweight='bold') if sublabel: ax.text(xy[0] + w/2, xy[1] + 0.15, sublabel, ha='center', va='bottom', fontsize=7, color='gray') def add_arrow(ax, start, end, label=''): ax.annotate('', xy=end, xytext=start, arrowprops=dict(arrowstyle='->', lw=1.5, color='#333')) if label: mid = ((start[0]+end[0])/2, (start[1]+end[1])/2 + 0.15) ax.text(*mid, label, fontsize=7, ha='center', color='#555') # Teacher side add_block(ax, (0.5, 4), 2, 1.2, 'DINOv2-L\n(frozen+LoRA)', '#1f77b4', '304M params') add_block(ax, (0.5, 2), 2, 1.2, 'Multi-FiLM\nFusion', '#9467bd', 'text→visual modulation') add_block(ax, (0.5, 0.3), 2, 1.2, 'Teacher\nDescriptor', '#1f77b4', '512-dim') # Student side add_block(ax, (5, 4), 2, 1.2, 'FastViT-T12\n(shared)', '#ff7f0e', '8.5M params') add_block(ax, (5, 0.3), 2, 1.2, 'Student\nDescriptor', '#ff7f0e', '512-dim') # Distillation arrows add_arrow(ax, (2.5, 0.9), (5, 0.9), '$L_{LUPI}$') add_arrow(ax, (2.5, 4.6), (5, 4.6), '$L_{feat}$') ax.set_title('NADEZHDA: Teacher-Student Architecture', fontsize=14, fontweight='bold') plt.savefig('nadezhda_architecture.png', dpi=300, bbox_inches='tight') ``` ## 5. Mermaid: LUPI Distillation Pipeline ````markdown ```mermaid graph LR subgraph Teacher ["Teacher (356M, cloud)"] S1[Satellite RGB] --> TE[DINOv2-L + LoRA] D1[Drone RGB] --> TE SV[Street-View] --> TE DP[Depth Map] --> TE TX[Text Desc.] --> FM[Multi-FiLM] FM --> TE TE --> TD[Teacher Descriptor 512-dim] end subgraph Student ["Student (8.5M, edge)"] S2[Satellite RGB] --> SE[FastViT-T12] D2[Drone RGB] --> SE SE --> SD[Student Descriptor 512-dim] end TD -->|L_LUPI: MSE| SD TE -->|L_feat: Conv1x1 proj| SE TD -->|L_RKD: relational| SD style Teacher fill:#e3f2fd,stroke:#1565c0 style Student fill:#fff3e0,stroke:#e65100 ``` ````