|
|
|
|
| """
|
| Performance Trend Over Edit Cycles Visualization
|
| Tracks how the agent improves over time through RL retraining and heuristic updates
|
| """
|
| import matplotlib.pyplot as plt
|
| import numpy as np
|
| from typing import List, Dict
|
|
|
|
|
| def plot_performance_trend(edit_history: List[Dict],
|
| output_file: str = 'performance_trend.png'):
|
| """
|
| Create line plot showing performance improvement over edit cycles
|
|
|
| Args:
|
| edit_history: List of edit cycle results
|
| output_file: Output filename for the plot
|
| """
|
| cycles = list(range(1, len(edit_history) + 1))
|
| performance_deltas = [e['performance_delta'] for e in edit_history]
|
| rewards = [e.get('reward', 0.5 + e['performance_delta']) for e in edit_history]
|
|
|
| fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))
|
|
|
|
|
| ax1.plot(cycles, performance_deltas, 'o-', linewidth=2, markersize=6,
|
| color='#3498db', label='Performance Delta')
|
| ax1.axhline(y=0, color='gray', linestyle='--', alpha=0.5)
|
| ax1.fill_between(cycles, 0, performance_deltas, alpha=0.3, color='#3498db')
|
|
|
|
|
| window = 3
|
| if len(performance_deltas) >= window:
|
| moving_avg = np.convolve(performance_deltas, np.ones(window)/window, mode='valid')
|
| ax1.plot(range(window, len(cycles)+1), moving_avg, 'r--', linewidth=2,
|
| label=f'{window}-Cycle Moving Average')
|
|
|
| ax1.set_xlabel('Edit Cycle', fontsize=12, fontweight='bold')
|
| ax1.set_ylabel('Performance Delta', fontsize=12, fontweight='bold')
|
| ax1.set_title('Performance Delta Over Edit Cycles', fontsize=14, fontweight='bold')
|
| ax1.legend(fontsize=10)
|
| ax1.grid(True, alpha=0.3, linestyle='--')
|
|
|
|
|
| ax2.plot(cycles, rewards, 'o-', linewidth=2, markersize=6,
|
| color='#2ecc71', label='Reward')
|
| ax2.fill_between(cycles, min(rewards), rewards, alpha=0.3, color='#2ecc71')
|
|
|
|
|
| z = np.polyfit(cycles, rewards, 2)
|
| p = np.poly1d(z)
|
| ax2.plot(cycles, p(cycles), 'r--', linewidth=2, label='Trend')
|
|
|
| ax2.set_xlabel('Edit Cycle', fontsize=12, fontweight='bold')
|
| ax2.set_ylabel('Reward', fontsize=12, fontweight='bold')
|
| ax2.set_title('Reward Progression Over Edit Cycles', fontsize=14, fontweight='bold')
|
| ax2.legend(fontsize=10)
|
| ax2.grid(True, alpha=0.3, linestyle='--')
|
| ax2.set_ylim(0, 1.0)
|
|
|
| plt.tight_layout()
|
| plt.savefig(output_file, dpi=300, bbox_inches='tight')
|
| print(f"✓ Performance trend saved to {output_file}")
|
| plt.close()
|
|
|
|
|
| def plot_backend_usage_over_time(edit_history: List[Dict],
|
| output_file: str = 'backend_usage_trend.png'):
|
| """
|
| Create stacked area chart showing backend usage over time
|
|
|
| Args:
|
| edit_history: List of edit cycle results
|
| output_file: Output filename for the plot
|
| """
|
| cycles = list(range(1, len(edit_history) + 1))
|
| backends = list(set(e['backend'] for e in edit_history))
|
|
|
|
|
| window_size = 5
|
| backend_counts = {b: [] for b in backends}
|
|
|
| for i in range(len(edit_history)):
|
| start = max(0, i - window_size + 1)
|
| window = edit_history[start:i+1]
|
| total = len(window)
|
| for backend in backends:
|
| count = sum(1 for e in window if e['backend'] == backend)
|
| backend_counts[backend].append(count / total)
|
|
|
| fig, ax = plt.subplots(figsize=(12, 6))
|
|
|
| colors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12']
|
| ax.stackplot(cycles, *[backend_counts[b] for b in backends],
|
| labels=backends, colors=colors[:len(backends)], alpha=0.8)
|
|
|
| ax.set_xlabel('Edit Cycle', fontsize=12, fontweight='bold')
|
| ax.set_ylabel('Backend Usage Proportion', fontsize=12, fontweight='bold')
|
| ax.set_title(f'Backend Usage Over Time\n({window_size}-Cycle Rolling Window)',
|
| fontsize=14, fontweight='bold')
|
| ax.legend(loc='upper right', fontsize=10)
|
| ax.set_ylim(0, 1.0)
|
| ax.grid(True, alpha=0.3, linestyle='--')
|
|
|
| plt.tight_layout()
|
| plt.savefig(output_file, dpi=300, bbox_inches='tight')
|
| print(f"✓ Backend usage trend saved to {output_file}")
|
| plt.close()
|
|
|
|
|
| def plot_learning_curve_with_retraining(edit_history: List[Dict],
|
| retrain_intervals: List[int],
|
| output_file: str = 'learning_curve.png'):
|
| """
|
| Create learning curve with retraining markers
|
|
|
| Args:
|
| edit_history: List of edit cycle results
|
| retrain_intervals: List of cycle numbers where retraining occurred
|
| output_file: Output filename for the plot
|
| """
|
| cycles = list(range(1, len(edit_history) + 1))
|
| rewards = [e.get('reward', 0.5 + e['performance_delta']) for e in edit_history]
|
|
|
| fig, ax = plt.subplots(figsize=(14, 7))
|
|
|
|
|
| ax.plot(cycles, rewards, 'o-', linewidth=2, markersize=5,
|
| color='#3498db', alpha=0.7, label='Reward')
|
|
|
|
|
| for retrain_cycle in retrain_intervals:
|
| if retrain_cycle <= len(cycles):
|
| ax.axvline(x=retrain_cycle, color='red', linestyle='--',
|
| alpha=0.7, linewidth=2)
|
| ax.text(retrain_cycle, max(rewards) * 0.95, 'Retrain',
|
| rotation=90, va='top', ha='right', fontsize=9,
|
| color='red', fontweight='bold')
|
|
|
|
|
| window = 5
|
| if len(rewards) >= window:
|
| moving_avg = np.convolve(rewards, np.ones(window)/window, mode='valid')
|
| moving_std = [np.std(rewards[max(0, i-window):i+1])
|
| for i in range(window-1, len(rewards))]
|
| x_avg = range(window, len(cycles)+1)
|
| ax.plot(x_avg, moving_avg, 'g-', linewidth=3, label='Moving Average')
|
| ax.fill_between(x_avg,
|
| np.array(moving_avg) - np.array(moving_std),
|
| np.array(moving_avg) + np.array(moving_std),
|
| alpha=0.2, color='green', label='±1 Std Dev')
|
|
|
| ax.set_xlabel('Edit Cycle', fontsize=12, fontweight='bold')
|
| ax.set_ylabel('Reward', fontsize=12, fontweight='bold')
|
| ax.set_title('Learning Curve with RL Retraining Events',
|
| fontsize=14, fontweight='bold')
|
| ax.legend(fontsize=10, loc='lower right')
|
| ax.grid(True, alpha=0.3, linestyle='--')
|
| ax.set_ylim(0, 1.0)
|
|
|
| plt.tight_layout()
|
| plt.savefig(output_file, dpi=300, bbox_inches='tight')
|
| print(f"✓ Learning curve saved to {output_file}")
|
| plt.close()
|
|
|
|
|
| if __name__ == '__main__':
|
|
|
| np.random.seed(42)
|
|
|
|
|
| edit_history = []
|
| for i in range(30):
|
|
|
| base_reward = 0.65 + 0.01 * i + 0.05 * np.random.randn()
|
| performance_delta = base_reward - 0.5
|
| edit_history.append({
|
| 'edit_id': f'edit_{i}',
|
| 'backend': np.random.choice(['ibm', 'russian']),
|
| 'performance_delta': performance_delta,
|
| 'reward': base_reward
|
| })
|
|
|
|
|
| retrain_intervals = [10, 20, 30]
|
|
|
| plot_performance_trend(edit_history)
|
| plot_backend_usage_over_time(edit_history)
|
| plot_learning_curve_with_retraining(edit_history, retrain_intervals)
|
|
|