garmentiq.classification.test_pytorch_nn
Evaluating a classification model on a held-out dataset.
1"""Evaluating a classification model on a held-out dataset.""" 2import torch 3import torch.nn as nn 4from torch.utils.data import DataLoader, TensorDataset 5from typing import Callable, Type 6from tqdm.auto import tqdm 7from sklearn.metrics import f1_score, accuracy_score, classification_report 8from garmentiq.utils.device import empty_cache 9from garmentiq.classification.utils import ( 10 CachedDataset, 11 seed_worker, 12 train_epoch, 13 validate_epoch, 14 save_best_model, 15 validate_train_param, 16 validate_test_param, 17) 18 19 20def test_pytorch_nn( 21 model_path: str, 22 model_class: Type[torch.nn.Module], 23 model_args: dict, 24 dataset_class: Callable, 25 dataset_args: dict, 26 param: dict, 27): 28 """ 29 Evaluates a trained PyTorch model on a test dataset. 30 31 Loads the model from disk, prepares the test dataset, and computes loss, accuracy, 32 F1 score, and prints a full classification report. 33 34 Args: 35 model_path (str): Path to the saved model checkpoint file. 36 model_class (Type[torch.nn.Module]): The class of the PyTorch model to instantiate. 37 Must inherit from `torch.nn.Module`. 38 model_args (dict): Dictionary of arguments used to initialize the model. 39 dataset_class (Callable): A callable class or function that returns a `torch.utils.data.Dataset`-compatible dataset. 40 (Note: Not directly used, but included for consistency with training pipeline.) 41 dataset_args (dict): Dictionary with dataset components: 42 - `cached_images` (torch.Tensor): Preprocessed test image tensors. 43 - `cached_labels` (torch.Tensor): Corresponding test labels. 44 - `raw_labels` (pandas.Series or array-like): Original labels for report generation. 45 param (dict): Dictionary of optional configuration parameters. 46 Optional Keys: 47 - `device` (Union[str, torch.device]): Device for computation, e.g. `"cpu"`, 48 `"cuda"`, `"cuda:0"`, or `"mps"`. Hardware acceleration is opt-in; 49 pass it explicitly to use a GPU or Apple Silicon. Default is `"cpu"`. 50 - `batch_size` (int): Batch size used for testing. Default is 64. 51 52 Raises: 53 FileNotFoundError: If the model checkpoint cannot be loaded. 54 ValueError: If the requested `device` is invalid or unavailable on this machine. 55 TypeError: If any parameter is of an incorrect type. 56 57 Returns: 58 None — prints test loss, accuracy, F1 score, and a classification report. 59 """ 60 validate_test_param(param) 61 model = model_class(**model_args).to(param["device"]) 62 state_dict = torch.load(model_path, map_location=param["device"], weights_only=True) 63 new_state_dict = {k.replace("module.", ""): v for k, v in state_dict.items()} 64 model.load_state_dict(new_state_dict, strict=False) 65 model.eval() 66 67 test_dataset = TensorDataset( 68 dataset_args["cached_images"], dataset_args["cached_labels"] 69 ) 70 test_loader = DataLoader( 71 test_dataset, batch_size=param["batch_size"], shuffle=False 72 ) 73 74 # Evaluation 75 all_preds = [] 76 all_labels = [] 77 total_loss = 0.0 78 79 with torch.no_grad(): 80 for images, labels in tqdm(test_loader, desc="Evaluating"): 81 images = images.to(param["device"]) 82 labels = labels.to(param["device"]) 83 84 outputs = model(images) 85 criterion = nn.CrossEntropyLoss() 86 loss = criterion(outputs, labels) 87 88 total_loss += loss.item() * images.size(0) 89 _, preds = torch.max(outputs, 1) 90 91 all_preds.extend(preds.cpu().numpy()) 92 all_labels.extend(labels.cpu().numpy()) 93 94 # Calculate metrics 95 test_loss = total_loss / len(test_loader.dataset) 96 test_acc = accuracy_score(all_labels, all_preds) 97 test_f1 = f1_score(all_labels, all_preds, average="weighted") 98 99 del model 100 empty_cache(param["device"]) 101 102 print(f"Test Loss: {test_loss:.4f}") 103 print(f"Test Accuracy: {test_acc:.4f}") 104 print(f"Test F1 Score: {test_f1:.4f}") 105 print("\nClassification Report:") 106 print( 107 classification_report( 108 all_labels, 109 all_preds, 110 target_names=sorted(dataset_args["raw_labels"].unique()), 111 ) 112 )
def
test_pytorch_nn( model_path: str, model_class: Type[torch.nn.modules.module.Module], model_args: dict, dataset_class: Callable, dataset_args: dict, param: dict):
21def test_pytorch_nn( 22 model_path: str, 23 model_class: Type[torch.nn.Module], 24 model_args: dict, 25 dataset_class: Callable, 26 dataset_args: dict, 27 param: dict, 28): 29 """ 30 Evaluates a trained PyTorch model on a test dataset. 31 32 Loads the model from disk, prepares the test dataset, and computes loss, accuracy, 33 F1 score, and prints a full classification report. 34 35 Args: 36 model_path (str): Path to the saved model checkpoint file. 37 model_class (Type[torch.nn.Module]): The class of the PyTorch model to instantiate. 38 Must inherit from `torch.nn.Module`. 39 model_args (dict): Dictionary of arguments used to initialize the model. 40 dataset_class (Callable): A callable class or function that returns a `torch.utils.data.Dataset`-compatible dataset. 41 (Note: Not directly used, but included for consistency with training pipeline.) 42 dataset_args (dict): Dictionary with dataset components: 43 - `cached_images` (torch.Tensor): Preprocessed test image tensors. 44 - `cached_labels` (torch.Tensor): Corresponding test labels. 45 - `raw_labels` (pandas.Series or array-like): Original labels for report generation. 46 param (dict): Dictionary of optional configuration parameters. 47 Optional Keys: 48 - `device` (Union[str, torch.device]): Device for computation, e.g. `"cpu"`, 49 `"cuda"`, `"cuda:0"`, or `"mps"`. Hardware acceleration is opt-in; 50 pass it explicitly to use a GPU or Apple Silicon. Default is `"cpu"`. 51 - `batch_size` (int): Batch size used for testing. Default is 64. 52 53 Raises: 54 FileNotFoundError: If the model checkpoint cannot be loaded. 55 ValueError: If the requested `device` is invalid or unavailable on this machine. 56 TypeError: If any parameter is of an incorrect type. 57 58 Returns: 59 None — prints test loss, accuracy, F1 score, and a classification report. 60 """ 61 validate_test_param(param) 62 model = model_class(**model_args).to(param["device"]) 63 state_dict = torch.load(model_path, map_location=param["device"], weights_only=True) 64 new_state_dict = {k.replace("module.", ""): v for k, v in state_dict.items()} 65 model.load_state_dict(new_state_dict, strict=False) 66 model.eval() 67 68 test_dataset = TensorDataset( 69 dataset_args["cached_images"], dataset_args["cached_labels"] 70 ) 71 test_loader = DataLoader( 72 test_dataset, batch_size=param["batch_size"], shuffle=False 73 ) 74 75 # Evaluation 76 all_preds = [] 77 all_labels = [] 78 total_loss = 0.0 79 80 with torch.no_grad(): 81 for images, labels in tqdm(test_loader, desc="Evaluating"): 82 images = images.to(param["device"]) 83 labels = labels.to(param["device"]) 84 85 outputs = model(images) 86 criterion = nn.CrossEntropyLoss() 87 loss = criterion(outputs, labels) 88 89 total_loss += loss.item() * images.size(0) 90 _, preds = torch.max(outputs, 1) 91 92 all_preds.extend(preds.cpu().numpy()) 93 all_labels.extend(labels.cpu().numpy()) 94 95 # Calculate metrics 96 test_loss = total_loss / len(test_loader.dataset) 97 test_acc = accuracy_score(all_labels, all_preds) 98 test_f1 = f1_score(all_labels, all_preds, average="weighted") 99 100 del model 101 empty_cache(param["device"]) 102 103 print(f"Test Loss: {test_loss:.4f}") 104 print(f"Test Accuracy: {test_acc:.4f}") 105 print(f"Test F1 Score: {test_f1:.4f}") 106 print("\nClassification Report:") 107 print( 108 classification_report( 109 all_labels, 110 all_preds, 111 target_names=sorted(dataset_args["raw_labels"].unique()), 112 ) 113 )
Evaluates a trained PyTorch model on a test dataset.
Loads the model from disk, prepares the test dataset, and computes loss, accuracy, F1 score, and prints a full classification report.
Arguments:
- model_path (str): Path to the saved model checkpoint file.
- model_class (Type[torch.nn.Module]): The class of the PyTorch model to instantiate.
Must inherit from
torch.nn.Module. - model_args (dict): Dictionary of arguments used to initialize the model.
- dataset_class (Callable): A callable class or function that returns a
torch.utils.data.Dataset-compatible dataset. (Note: Not directly used, but included for consistency with training pipeline.) - dataset_args (dict): Dictionary with dataset components:
cached_images(torch.Tensor): Preprocessed test image tensors.cached_labels(torch.Tensor): Corresponding test labels.raw_labels(pandas.Series or array-like): Original labels for report generation.
- param (dict): Dictionary of optional configuration parameters.
Optional Keys:
-
device(Union[str, torch.device]): Device for computation, e.g."cpu","cuda","cuda:0", or"mps". Hardware acceleration is opt-in; pass it explicitly to use a GPU or Apple Silicon. Default is"cpu". -batch_size(int): Batch size used for testing. Default is 64.
Raises:
- FileNotFoundError: If the model checkpoint cannot be loaded.
- ValueError: If the requested
deviceis invalid or unavailable on this machine. - TypeError: If any parameter is of an incorrect type.
Returns:
None — prints test loss, accuracy, F1 score, and a classification report.