Model Analysis API

This module provides comprehensive model analysis capabilities for PyTorch models.

Core Functions

Classes

Function Details

analyze_model

analyze_model(model, input_shape=None, detailed=True)

Analyze a PyTorch model and return detailed statistics.

Parameters:

  • model (torch.nn.Module): PyTorch model to analyze

  • input_shape (tuple, optional): Input tensor shape

  • detailed (bool, optional): Whether to include detailed layer analysis (default: True)

Returns: dict - Dictionary containing model analysis with keys:

  • basic_info (dict): Basic model information * total_parameters (int): Total number of parameters * trainable_parameters (int): Number of trainable parameters * total_layers (int): Total number of layers * device (str): Device the model is on * model_mode (str): Model mode (training/evaluation)

  • memory (dict): Memory usage information * parameters_mb (float): Parameter memory in MB * activations_mb (float): Activation memory in MB * input_mb (float): Input memory in MB * total_memory_mb (float): Total memory in MB

  • architecture (dict): Architecture analysis * depth (int): Network depth * conv_layers (int): Number of convolutional layers * linear_layers (int): Number of linear layers * norm_layers (int): Number of normalization layers * patterns (list): Detected architectural patterns

Raises:

  • ImportError: If PyTorch is not available

Example:

import torch.nn as nn
from pytorch-graph import analyze_model

model = nn.Sequential(
    nn.Linear(784, 128),
    nn.ReLU(),
    nn.Linear(128, 10)
)

# Analyze model structure
analysis = analyze_model(model, input_shape=(1, 784))
print(f"Total parameters: {analysis['basic_info']['total_parameters']:,}")
print(f"Model size: {analysis['memory']['total_memory_mb']:.2f} MB")

profile_model

profile_model(model, input_shape, device='cpu')

Profile a PyTorch model for performance analysis.

Parameters:

  • model (torch.nn.Module): PyTorch model to profile

  • input_shape (tuple): Input tensor shape

  • device (str, optional): Device to run profiling on (‘cpu’ or ‘cuda’, default: ‘cpu’)

Returns: dict - Profiling results dictionary with keys:

  • mean_time_ms (float): Mean inference time in milliseconds

  • std_time_ms (float): Standard deviation of inference time

  • min_time_ms (float): Minimum inference time in milliseconds

  • max_time_ms (float): Maximum inference time in milliseconds

  • fps (float): Frames per second (throughput)

  • memory_usage (dict): Memory usage statistics

  • execution_times (list): List of individual execution times

Raises:

  • ImportError: If PyTorch is not available

Example:

from pytorch-graph import profile_model

profiling_results = profile_model(
    model=model,
    input_shape=(1, 784),
    device='cpu'
)

print(f"Average inference time: {profiling_results['mean_time_ms']:.2f} ms")
print(f"Throughput: {profiling_results['fps']:.1f} FPS")

extract_activations

extract_activations(model, input_tensor, layer_names=None)

Extract intermediate activations from a PyTorch model.

Parameters:

  • model (torch.nn.Module): PyTorch model to extract activations from

  • input_tensor (torch.Tensor): Input tensor for forward pass

  • layer_names (list, optional): Specific layer names to extract (if None, extracts all)

Returns: dict - Dictionary of layer names to activation tensors

Raises:

  • ImportError: If PyTorch is not available

Example:

import torch
from pytorch-graph import extract_activations

input_tensor = torch.randn(1, 784)
activations = extract_activations(
    model=model,
    input_tensor=input_tensor,
    layer_names=['0', '2']  # Extract from specific layers
)

for layer_name, activation in activations.items():
    print(f"{layer_name}: {activation.shape}")

ModelAnalyzer Class

class ModelAnalyzer

Comprehensive model analysis and profiling class.

Methods:

analyze(model, input_shape=None, detailed=True, device='auto')

Perform comprehensive analysis of the PyTorch model.

Parameters:

  • model (torch.nn.Module): PyTorch model to analyze

  • input_shape (tuple, optional): Input tensor shape

  • detailed (bool, optional): Whether to include detailed analysis (default: True)

  • device (str, optional): Device for analysis (‘auto’, ‘cpu’, ‘cuda’, default: ‘auto’)

Returns: dict - Dictionary containing comprehensive analysis

profile_model(model, input_shape, device='cpu', num_runs=100)

Profile PyTorch model performance.

Parameters:

  • model (torch.nn.Module): PyTorch model to profile

  • input_shape (tuple): Input tensor shape

  • device (str, optional): Device for profiling (default: ‘cpu’)

  • num_runs (int, optional): Number of timing runs (default: 100)

Returns: dict - Dictionary with profiling results

get_layer_info(model, input_shape=None)

Get detailed information about each layer in the model.

Parameters:

  • model (torch.nn.Module): PyTorch model

  • input_shape (tuple, optional): Input tensor shape

Returns: list - List of layer information dictionaries

calculate_memory_usage(model, input_shape)

Calculate memory usage for the model.

Parameters:

  • model (torch.nn.Module): PyTorch model

  • input_shape (tuple): Input tensor shape

Returns: dict - Memory usage information

detect_architecture_patterns(model)

Detect common architectural patterns in the model.

Parameters:

  • model (torch.nn.Module): PyTorch model

Returns: list - List of detected patterns

Examples

Basic Model Analysis

import torch.nn as nn
from pytorch-graph import analyze_model

model = nn.Sequential(
    nn.Linear(784, 128),
    nn.ReLU(),
    nn.Dropout(0.2),
    nn.Linear(128, 64),
    nn.ReLU(),
    nn.Linear(64, 10)
)

# Analyze model structure
analysis = analyze_model(model, input_shape=(1, 784))

# Basic information
basic_info = analysis['basic_info']
print(f"Total parameters: {basic_info['total_parameters']:,}")
print(f"Trainable parameters: {basic_info['trainable_parameters']:,}")
print(f"Total layers: {basic_info['total_layers']}")

# Memory usage
memory_info = analysis['memory']
print(f"Model size: {memory_info['total_memory_mb']:.2f} MB")

# Architecture analysis
arch_info = analysis['architecture']
print(f"Network depth: {arch_info['depth']}")
print(f"Linear layers: {arch_info['linear_layers']}")

Performance Profiling

from pytorch-graph import profile_model

# Profile model performance
profiling_results = profile_model(
    model=model,
    input_shape=(1, 784),
    device='cpu'
)

print(f"Average inference time: {profiling_results['mean_time_ms']:.2f} ms")
print(f"Standard deviation: {profiling_results['std_time_ms']:.2f} ms")
print(f"Min time: {profiling_results['min_time_ms']:.2f} ms")
print(f"Max time: {profiling_results['max_time_ms']:.2f} ms")
print(f"Throughput: {profiling_results['fps']:.1f} FPS")

Activation Extraction

import torch
from pytorch-graph import extract_activations

input_tensor = torch.randn(1, 784)

# Extract activations from all layers
all_activations = extract_activations(model, input_tensor)

for layer_name, activation in all_activations.items():
    print(f"Layer {layer_name}: {activation.shape}")

# Extract from specific layers
specific_activations = extract_activations(
    model=model,
    input_tensor=input_tensor,
    layer_names=['0', '3', '5']  # First, fourth, and sixth layers
)

Advanced Usage with ModelAnalyzer

from pytorch-graph import ModelAnalyzer

# Create analyzer
analyzer = ModelAnalyzer()

# Comprehensive analysis
analysis = analyzer.analyze(
    model=model,
    input_shape=(1, 784),
    detailed=True,
    device='auto'
)

# Get layer information
layer_info = analyzer.get_layer_info(model, input_shape=(1, 784))
for layer in layer_info:
    print(f"Layer: {layer['name']}, Type: {layer['type']}, Parameters: {layer['parameters']}")

# Calculate memory usage
memory_usage = analyzer.calculate_memory_usage(model, input_shape=(1, 784))
print(f"Parameter memory: {memory_usage['parameters_mb']:.2f} MB")
print(f"Activation memory: {memory_usage['activations_mb']:.2f} MB")

# Detect patterns
patterns = analyzer.detect_architecture_patterns(model)
print(f"Detected patterns: {patterns}")

Model Comparison

def compare_models(models, input_shapes, names=None):
    """Compare multiple models."""
    if names is None:
        names = [f"Model_{i+1}" for i in range(len(models))]

    results = {}

    for name, (model, input_shape) in zip(names, zip(models, input_shapes)):
        # Analyze model
        analysis = analyze_model(model, input_shape=input_shape)

        # Profile performance
        profiling = profile_model(model, input_shape, device='cpu')

        results[name] = {
            'parameters': analysis['basic_info']['total_parameters'],
            'model_size': analysis['memory']['total_memory_mb'],
            'inference_time': profiling['mean_time_ms'],
            'throughput': profiling['fps']
        }

    # Print comparison
    print("Model Comparison:")
    print("-" * 50)
    for name, metrics in results.items():
        print(f"{name}:")
        print(f"  Parameters: {metrics['parameters']:,}")
        print(f"  Model Size: {metrics['model_size']:.2f} MB")
        print(f"  Inference Time: {metrics['inference_time']:.2f} ms")
        print(f"  Throughput: {metrics['throughput']:.1f} FPS")
        print()

    return results

# Example usage
models = [mlp_model, cnn_model, resnet_model]
input_shapes = [(1, 784), (1, 3, 32, 32), (1, 3, 224, 224)]
names = ["MLP", "CNN", "ResNet"]

comparison_results = compare_models(models, input_shapes, names)

Memory Analysis

def analyze_memory_usage(model, input_shape):
    """Analyze memory usage patterns."""
    analysis = analyze_model(model, input_shape=input_shape)
    memory_info = analysis['memory']

    print("Memory Analysis:")
    print(f"  Parameter memory: {memory_info['parameters_mb']:.2f} MB")
    print(f"  Activation memory: {memory_info['activations_mb']:.2f} MB")
    print(f"  Input memory: {memory_info['input_mb']:.2f} MB")
    print(f"  Total memory: {memory_info['total_memory_mb']:.2f} MB")

    # Memory efficiency
    param_ratio = memory_info['parameters_mb'] / memory_info['total_memory_mb']
    activation_ratio = memory_info['activations_mb'] / memory_info['total_memory_mb']

    print(f"  Parameter ratio: {param_ratio:.1%}")
    print(f"  Activation ratio: {activation_ratio:.1%}")

    return memory_info

# Analyze memory
memory_analysis = analyze_memory_usage(model, input_shape=(1, 784))

Layer-wise Analysis

def analyze_layers(model, input_shape):
    """Get detailed layer analysis."""
    analyzer = ModelAnalyzer()
    layer_info = analyzer.get_layer_info(model, input_shape)

    print("Layer-wise Analysis:")
    print("-" * 30)

    for layer in layer_info:
        print(f"\nLayer: {layer['name']}")
        print(f"  Type: {layer['type']}")
        print(f"  Parameters: {layer['parameters']:,}")
        print(f"  Input shape: {layer.get('input_shape', 'N/A')}")
        print(f"  Output shape: {layer.get('output_shape', 'N/A')}")
        if 'memory_usage' in layer:
            print(f"  Memory: {layer['memory_usage']:.2f} MB")

    return layer_info

# Analyze layers
layer_analysis = analyze_layers(model, input_shape=(1, 784))

Error Handling

The functions will raise appropriate exceptions for:

  • ImportError: If PyTorch is not available

  • RuntimeError: If model execution fails

  • ValueError: If invalid parameters are provided

  • TypeError: If model is not a PyTorch module

See Also

  • architecture_visualization - For architecture diagram generation

  • computational_graph_tracking - For computational graph analysis

  • Utilities API - For utility classes and functions