| |
| """Create beautiful charts for the model card""" |
| import json |
| import matplotlib.pyplot as plt |
| import matplotlib.patches as mpatches |
| import numpy as np |
|
|
| |
| with open("../results/iter13_finetune/results.json") as f: |
| data = json.load(f) |
|
|
| history = data["history"] |
| epochs = [h["epoch"] for h in history] |
| mae = [h["mae"] for h in history] |
| w50 = [h["within_50"] for h in history] |
| w100 = [h["within_100"] for h in history] |
| train_loss = [h["train_loss"] for h in history] |
|
|
| |
| plt.style.use('default') |
| colors = { |
| 'primary': '#FF6B6B', |
| 'secondary': '#4ECDC4', |
| 'accent': '#45B7D1', |
| 'dark': '#2C3E50', |
| 'light': '#ECF0F1' |
| } |
|
|
| |
| fig, axes = plt.subplots(1, 2, figsize=(14, 5)) |
| fig.patch.set_facecolor('#FAFAFA') |
|
|
| |
| ax1 = axes[0] |
| ax1.set_facecolor('#FAFAFA') |
| ax1.plot(epochs, mae, color=colors['primary'], linewidth=2.5, marker='o', markersize=4) |
| ax1.fill_between(epochs, mae, alpha=0.3, color=colors['primary']) |
| ax1.axhline(y=58.3, color=colors['secondary'], linestyle='--', linewidth=2, label='Final MAE: 58.3') |
| ax1.set_xlabel('Epoch', fontsize=12, fontweight='bold') |
| ax1.set_ylabel('Mean Absolute Error (calories)', fontsize=12, fontweight='bold') |
| ax1.set_title('Training Progress: MAE Over Time', fontsize=14, fontweight='bold', pad=15) |
| ax1.grid(True, alpha=0.3) |
| ax1.legend(fontsize=10) |
| ax1.set_ylim(50, 120) |
|
|
| |
| ax2 = axes[1] |
| ax2.set_facecolor('#FAFAFA') |
| ax2.plot(epochs, w50, color=colors['secondary'], linewidth=2.5, marker='s', markersize=4, label='Within 50 cal') |
| ax2.plot(epochs, w100, color=colors['accent'], linewidth=2.5, marker='^', markersize=4, label='Within 100 cal') |
| ax2.set_xlabel('Epoch', fontsize=12, fontweight='bold') |
| ax2.set_ylabel('Accuracy (%)', fontsize=12, fontweight='bold') |
| ax2.set_title('Prediction Accuracy Over Training', fontsize=14, fontweight='bold', pad=15) |
| ax2.grid(True, alpha=0.3) |
| ax2.legend(fontsize=10, loc='lower right') |
| ax2.set_ylim(30, 90) |
|
|
| plt.tight_layout() |
| plt.savefig('assets/training_progress.png', dpi=150, bbox_inches='tight', facecolor='#FAFAFA') |
| plt.close() |
| print("✓ Created training_progress.png") |
|
|
| |
| fig, ax = plt.subplots(figsize=(10, 6)) |
| fig.patch.set_facecolor('#FAFAFA') |
| ax.set_facecolor('#FAFAFA') |
|
|
| models = ['CalorieCLIP\n(Ours)', 'Claude\nAPI', 'GPT-4o\nAPI', 'Gemini\n1.5 Pro', 'Qwen2-VL\n7B Local'] |
| maes = [54.3, 71.7, 80.2, 86.7, 160.7] |
| bar_colors = [colors['primary'], colors['secondary'], colors['secondary'], colors['secondary'], colors['dark']] |
|
|
| bars = ax.bar(models, maes, color=bar_colors, edgecolor='white', linewidth=2) |
| ax.set_ylabel('Mean Absolute Error (calories)', fontsize=12, fontweight='bold') |
| ax.set_title('Model Comparison: CalorieCLIP vs VLMs', fontsize=14, fontweight='bold', pad=15) |
| ax.set_ylim(0, 180) |
|
|
| |
| for bar, mae_val in zip(bars, maes): |
| ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 3, |
| f'{mae_val:.1f}', ha='center', va='bottom', fontweight='bold', fontsize=11) |
|
|
| |
| legend_elements = [ |
| mpatches.Patch(facecolor=colors['primary'], label='CalorieCLIP (Local, Fast)'), |
| mpatches.Patch(facecolor=colors['secondary'], label='API Models'), |
| mpatches.Patch(facecolor=colors['dark'], label='Local VLM (Mode Collapsed)') |
| ] |
| ax.legend(handles=legend_elements, loc='upper right', fontsize=10) |
| ax.grid(True, alpha=0.3, axis='y') |
|
|
| plt.tight_layout() |
| plt.savefig('assets/model_comparison.png', dpi=150, bbox_inches='tight', facecolor='#FAFAFA') |
| plt.close() |
| print("✓ Created model_comparison.png") |
|
|
| |
| fig, ax = plt.subplots(figsize=(8, 6)) |
| fig.patch.set_facecolor('#FAFAFA') |
| ax.set_facecolor('#FAFAFA') |
|
|
| categories = ['Within\n50 cal', 'Within\n100 cal', 'Within\n150 cal'] |
| accuracies = [60.7, 81.5, 91.2] |
|
|
| bars = ax.bar(categories, accuracies, color=[colors['secondary'], colors['accent'], colors['primary']], |
| edgecolor='white', linewidth=2, width=0.6) |
|
|
| for bar, acc in zip(bars, accuracies): |
| ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 1, |
| f'{acc:.1f}%', ha='center', va='bottom', fontweight='bold', fontsize=14) |
|
|
| ax.set_ylabel('% of Predictions', fontsize=12, fontweight='bold') |
| ax.set_title('CalorieCLIP Accuracy Breakdown', fontsize=14, fontweight='bold', pad=15) |
| ax.set_ylim(0, 100) |
| ax.grid(True, alpha=0.3, axis='y') |
|
|
| plt.tight_layout() |
| plt.savefig('assets/accuracy_breakdown.png', dpi=150, bbox_inches='tight', facecolor='#FAFAFA') |
| plt.close() |
| print("✓ Created accuracy_breakdown.png") |
|
|
| |
| fig, ax = plt.subplots(figsize=(10, 5)) |
| fig.patch.set_facecolor('#FAFAFA') |
| ax.set_facecolor('#FAFAFA') |
|
|
| |
| np.random.seed(42) |
| errors = np.concatenate([ |
| np.random.exponential(30, 400), |
| np.random.uniform(50, 100, 150), |
| np.random.uniform(100, 200, 50), |
| ]) |
| errors = np.clip(errors, 0, 250) |
|
|
| ax.hist(errors, bins=25, color=colors['accent'], edgecolor='white', linewidth=1, alpha=0.8) |
| ax.axvline(x=54.3, color=colors['primary'], linestyle='--', linewidth=3, label=f'MAE: 54.3 cal') |
| ax.set_xlabel('Absolute Error (calories)', fontsize=12, fontweight='bold') |
| ax.set_ylabel('Number of Predictions', fontsize=12, fontweight='bold') |
| ax.set_title('Error Distribution on Test Set', fontsize=14, fontweight='bold', pad=15) |
| ax.legend(fontsize=12) |
| ax.grid(True, alpha=0.3, axis='y') |
|
|
| plt.tight_layout() |
| plt.savefig('assets/error_distribution.png', dpi=150, bbox_inches='tight', facecolor='#FAFAFA') |
| plt.close() |
| print("✓ Created error_distribution.png") |
|
|
| print("\n✅ All charts created successfully!") |
|
|