| 4 | import numpy as np |
| 5 | |
| 6 | class MetricsTracker: |
| 7 | def __init__(self): |
| 8 | self.metrics = [] |
| 9 | self.best_metrics = {} |
| 10 | |
| 11 | def update(self, metrics: Dict[str, Any]): |
| 12 | self.metrics.append(metrics.copy()) |
| 13 | |
| 14 | for key, value in metrics.items(): |
| 15 | if isinstance(value, (int, float)): |
| 16 | if key not in self.best_metrics: |
| 17 | self.best_metrics[key] = value |
| 18 | else: |
| 19 | if 'loss' in key.lower(): |
| 20 | self.best_metrics[key] = min(self.best_metrics[key], value) |
| 21 | else: |
| 22 | self.best_metrics[key] = max(self.best_metrics[key], value) |
| 23 | |
| 24 | def get_history(self, key: str) -> List[Any]: |
| 25 | return [m.get(key) for m in self.metrics if key in m] |
| 26 | |
| 27 | def get_latest(self, key: str) -> Any: |
| 28 | for m in reversed(self.metrics): |
| 29 | if key in m: |
| 30 | return m[key] |
| 31 | return None |
| 32 | |
| 33 | def get_best(self, key: str) -> Any: |
| 34 | return self.best_metrics.get(key) |
| 35 | |
| 36 | def get_average(self, key: str, last_n: int = None) -> float: |
| 37 | history = self.get_history(key) |
| 38 | if not history: |
| 39 | return 0.0 |
| 40 | |
| 41 | if last_n is not None: |
| 42 | history = history[-last_n:] |
| 43 | |
| 44 | return np.mean([v for v in history if v is not None]) |
| 45 | |
| 46 | def save(self, filepath: str): |
| 47 | os.makedirs(os.path.dirname(filepath), exist_ok=True) |
| 48 | |
| 49 | data = { |
| 50 | 'metrics': self.metrics, |
| 51 | 'best_metrics': self.best_metrics |
| 52 | } |
| 53 | |
| 54 | with open(filepath, 'w') as f: |
| 55 | json.dump(data, f, indent=2) |
| 56 | |
| 57 | def load(self, filepath: str): |
| 58 | with open(filepath, 'r') as f: |
| 59 | data = json.load(f) |
| 60 | |
| 61 | self.metrics = data.get('metrics', []) |
| 62 | self.best_metrics = data.get('best_metrics', {}) |
| 63 | |