EmoteVision / src /evaluator.py
gabriellidenor's picture
Upload folder using huggingface_hub
ce254e2 verified
Raw History Blame Contribute Delete
3.54 kB
import torch
import yaml
import json
from typing import Protocol, Any
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, classification_report, confusion_matrix
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
class DataProvider(Protocol):
def get_test_loader(self) -> Any:
...
class Evaluator:
def __init__(self, model: torch.nn.Module,data_provider: DataProvider):
self.model = model
self.data_provider = data_provider
self._y_true = None
self._y_pred = None
@torch.no_grad()
def _evaluate(self):
if self._y_true is not None and self._y_pred is not None:
return # prevents redundant interferance runs
self.model.eval()
loader = self.data_provider.get_test_loader()
device = next(self.model.parameters()).device
y_true_list = []
y_pred_list = []
for x, y in loader:
x = x.to(device)
outputs = self.model(x)
predictions = torch.argmax(outputs, dim = 1)
y_true_list.extend(y.cpu().numpy())
y_pred_list.extend(predictions.cpu().numpy())
self._y_true = np.array(y_true_list)
self._y_pred = np.array(y_pred_list)
def extract_y_true(self):
loader = self.data_provider.get_test_loader()
y_true = []
for _, y in loader:
y_true.extend(y.numpy() if hasattr(y, 'numpy') else y)
return y_true
def accuracy(self) -> float:
self._evaluate()
return float(accuracy_score(self._y_true, self._y_pred))
def precision(self, average: str = 'macro') -> float:
self._evaluate()
return float(precision_score(self._y_true, self._y_pred, average = average))
def recall(self, average: str = 'macro') -> float:
self._evaluate()
return float(recall_score(self._y_true, self._y_pred, average=average))
def f1_score(self, average: str = 'macro') -> float:
self._evaluate()
return float(f1_score(self._y_true, self._y_pred, average=average))
def plot_confusion_matrix(self, save_path: str = None):
self._evaluate()
cm = confusion_matrix(self._y_true, self._y_pred)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix')
if save_path:
plt.savefig(save_path)
plt.close()
else:
plt.show()
def get_classification_report(self) -> str:
self._evaluate()
return classification_report(self._y_true, self._y_pred)
def export_metrics(self, filepath: str, format: str = 'json'):
metrics = {
"accuracy": self.accuracy(),
"precision_macro": self.precision(average='macro'),
"precision_weighted": self.precision(average='weighted'),
"recall_macro": self.recall(average='macro'),
"recall_weighted": self.recall(average='weighted'),
"f1_macro": self.f1_score(average='macro'),
"f1_weighted": self.f1_score(average='weighted'),
}
with open(filepath, 'w') as f:
if format.lower() == 'json':
json.dump(metrics, f, indent=4)
elif format.lower() in ['yaml', 'yml']:
yaml.dump(metrics, f)
else:
raise ValueError("Unsupported format. Choose 'json' or 'yaml'.")