### Install pytorch-custom-utils Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt Install the library using pip. ```bash pip install pytorch-custom-utils ``` -------------------------------- ### Install Pytorch Custom Utils Source: https://github.com/lucidrains/pytorch-custom-utils/blob/main/README.md Install the package via pip. ```bash $ pip install pytorch-custom-utils ``` -------------------------------- ### Integrate W&B Tracking via Context Manager Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt Inject a Weights & Biases tracking context manager into a training class to simplify experiment logging. ```python import torch from torch import nn from accelerate import Accelerator from pytorch_custom_utils import add_wandb_tracker_contextmanager @add_wandb_tracker_contextmanager( accelerator_instance_name='accelerator', tracker_hps_instance_name='hparams' ) class Trainer: def __init__(self, model, lr=1e-4, batch_size=32): self.accelerator = Accelerator(log_with='wandb') self.model = model self.hparams = {'lr': lr, 'batch_size': batch_size} def train(self): # Training logic here for step in range(100): loss = torch.tensor(1.0 / (step + 1)) self.accelerator.log({'loss': loss.item()}, step=step) trainer = Trainer(nn.Linear(10, 10)) # Use the injected context manager with trainer.wandb_tracking(project='my-project', run='experiment-1'): trainer.train() ``` -------------------------------- ### Combine Optimizer with Warmup and Scheduler Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt Wrap an optimizer to handle learning rate scheduling, warmup, and gradient clipping within an Accelerate training loop. ```python import torch from torch import nn from torch.optim import AdamW from torch.optim.lr_scheduler import CosineAnnealingLR from accelerate import Accelerator from pytorch_custom_utils import OptimizerWithWarmupSchedule accelerator = Accelerator() model = nn.Linear(512, 512) base_optimizer = AdamW(model.parameters(), lr=1e-4) # Create optimizer with warmup and cosine scheduling optimizer = OptimizerWithWarmupSchedule( accelerator=accelerator, optimizer=base_optimizer, scheduler=CosineAnnealingLR, scheduler_kwargs={'T_max': 10000}, warmup_steps=1000, max_grad_norm=1.0 ) # Training loop for batch in dataloader: optimizer.zero_grad() loss = model(batch).mean() accelerator.backward(loss) optimizer.step() # Handles gradient clipping, warmup, and scheduling # Save and load optimizer state state = optimizer.state_dict() optimizer.load_state_dict(state) ``` -------------------------------- ### Configure Adam Optimizer with Weight Decay Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt Create Adam or AdamW optimizers with built-in support for excluding biases and layer norms from weight decay. ```python import torch from torch import nn from pytorch_custom_utils import get_adam_optimizer class Model(nn.Module): def __init__(self, dim): super().__init__() self.linear = nn.Linear(dim, dim) self.norm = nn.LayerNorm(dim) def forward(self, x): return self.norm(self.linear(x)) model = Model(dim=512) # Standard AdamW with weight decay (excludes biases/gammas from WD) optimizer = get_adam_optimizer( model.parameters(), lr=1e-4, wd=0.01, betas=(0.9, 0.99), eps=1e-8, filter_by_requires_grad=True, omit_gammas_and_betas_from_wd=True ) # Without weight decay (returns Adam instead of AdamW) optimizer_no_wd = get_adam_optimizer( model.parameters(), lr=3e-4, wd=0.0 ) # Apply weight decay to all parameters optimizer_full_wd = get_adam_optimizer( model.parameters(), lr=1e-4, wd=0.01, omit_gammas_and_betas_from_wd=False ) ``` -------------------------------- ### Gradient Accumulation Helper Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt Use this context manager for efficient gradient accumulation with Accelerate. It automatically handles `no_sync` for distributed training, ensuring gradients are only synchronized on the last accumulation step. ```python import torch from torch import nn from accelerate import Accelerator from pytorch_custom_utils.accelerate_utils import model_forward_contexts accelerator = Accelerator() model = nn.Linear(512, 512) model = accelerator.prepare(model) optimizer = torch.optim.Adam(model.parameters()) grad_accum_steps = 4 batches = [torch.randn(8, 512) for _ in range(grad_accum_steps)] # Efficient gradient accumulation with automatic no_sync for context, batch in zip( model_forward_contexts(accelerator, model, grad_accum_steps), batches ): with context(): # Handles autocast and no_sync automatically loss = model(batch).mean() / grad_accum_steps accelerator.backward(loss) optimizer.step() optimizer.zero_grad() ``` -------------------------------- ### Tensor Padding and Slicing Utilities Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt These functions allow for flexible padding and slicing of tensors along specified dimensions. `pad_at_dim` adds values, `slice_at_dim` extracts a portion, and `pad_or_slice_to` adjusts the tensor to an exact length. ```python import torch from pytorch_custom_utils.utils import pad_at_dim, slice_at_dim, pad_or_slice_to # Pad tensor at specific dimension tensor = torch.randn(2, 10, 64) # Pad sequence dimension to length 15 (add 5 zeros at the end) padded = pad_at_dim(tensor, pad=(0, 5), dim=1, value=0.) print(padded.shape) # torch.Size([2, 15, 64]) # Slice to get first 8 elements at dimension 1 sliced = slice_at_dim(tensor, slice(0, 8), dim=1) print(sliced.shape) # torch.Size([2, 8, 64]) # Pad or slice to exact length exact_12 = pad_or_slice_to(tensor, length=12, dim=1, pad_value=0.) print(exact_12.shape) # torch.Size([2, 12, 64]) exact_5 = pad_or_slice_to(tensor, length=5, dim=1) print(exact_5.shape) # torch.Size([2, 5, 64]) ``` -------------------------------- ### Track Device on Pytorch Modules Source: https://github.com/lucidrains/pytorch-custom-utils/blob/main/README.md Use the module_device decorator to add a convenient .device property to a nn.Module. ```python import torch from torch import nn from pytorch_custom_utils import module_device # decorate the class with `module_device` class decorator @module_device() class MLP(nn.Module): def __init__(self, dim): super().__init__() self.net = nn.Linear(dim, dim) def forward(self, x): return self.net(x) # instantiated mlp mlp = MLP(dim = 512) mlp.to(torch.device('mps')) # now you have a convenient .device mlp.device # mps:0 ``` -------------------------------- ### Add Save and Load Methods to Modules Source: https://github.com/lucidrains/pytorch-custom-utils/blob/main/README.md Use the save_load decorator to add persistence methods to a nn.Module class. ```python import torch from torch import nn from pytorch_custom_utils import save_load # decorate the entire class with `save_load` class decorator @save_load() class MLP(nn.Module): def __init__(self, dim): super().__init__() self.net = nn.Sequential(nn.Linear(dim, dim), nn.SiLU(), nn.Linear(dim, dim)) def forward(self, x): return self.net(x) # instantiated mlp mlp = MLP(dim = 512) # now you have a save and load method mlp.save('./mlp.pt') mlp.load('./mlp.pt') # you can also directly initialize from the checkpoint, without having to save the corresponding hyperparameters (in this case, dim = 512) mlp = MLP.init_and_load('./mlp.pt') ``` -------------------------------- ### Count Trainable Parameters with Decorator Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt Use the total_parameters decorator to automatically track and expose the count of trainable parameters in a module. ```python @total_parameters(count_only_requires_grad=True, total_parameters_property_name='trainable_params') class FrozenEncoder(nn.Module): def __init__(self, dim): super().__init__() self.frozen = nn.Linear(dim, dim) self.frozen.requires_grad_(False) self.trainable = nn.Linear(dim, dim) def forward(self, x): return self.trainable(self.frozen(x)) encoder = FrozenEncoder(256) print(f"Trainable: {encoder.trainable_params:,}") # Only counts trainable layer ``` -------------------------------- ### Automatic Input Device Casting with autocast_device Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt The autocast_device decorator automatically moves tensor inputs to the model's device before the forward pass, preventing device mismatch errors. Ensure the module also has device tracking enabled via module_device. ```python import torch from torch import nn from pytorch_custom_utils import module_device from pytorch_custom_utils.module_device import autocast_device @module_device() @autocast_device(methods=['forward', 'encode']) class Encoder(nn.Module): def __init__(self, dim): super().__init__() self.linear = nn.Linear(dim, dim) def forward(self, x): return self.linear(x) def encode(self, x): return self.forward(x) encoder = Encoder(dim=128).cuda() # Input on CPU automatically moved to CUDA cpu_tensor = torch.randn(4, 128) # on CPU output = encoder(cpu_tensor) # works without manual .cuda() print(output.device) # cuda:0 ``` -------------------------------- ### Track Module Device with module_device Decorator Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt The module_device decorator adds a .device property to nn.Module subclasses, simplifying device tracking. It automatically returns the current device of the model's parameters, eliminating manual device placement checks. ```python import torch from torch import nn from pytorch_custom_utils import module_device @module_device(device_property_name='device') class MLP(nn.Module): def __init__(self, dim): super().__init__() self.net = nn.Sequential( nn.Linear(dim, dim * 4), nn.GELU(), nn.Linear(dim * 4, dim) ) def forward(self, x): return self.net(x) mlp = MLP(dim=256) print(mlp.device) # cpu mlp.to('cuda') print(mlp.device) # cuda:0 mlp.to('mps') print(mlp.device) # mps:0 ``` -------------------------------- ### Save and Load PyTorch Models with save_load Decorator Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt The save_load decorator adds save(), load(), and init_and_load() methods to nn.Module subclasses. It automatically captures constructor arguments for easy model serialization and loading without manual hyperparameter specification. ```python import torch from torch import nn from pytorch_custom_utils import save_load @save_load(version='1.0.0') class Transformer(nn.Module): def __init__(self, dim, depth, heads): super().__init__() self.dim = dim self.layers = nn.ModuleList([ nn.TransformerEncoderLayer(d_model=dim, nhead=heads) for _ in range(depth) ]) def forward(self, x): for layer in self.layers: x = layer(x) return x # Create and train model model = Transformer(dim=512, depth=6, heads=8) # Save model with all config model.save('./transformer.pt') # Load weights into existing model model.load('./transformer.pt', strict=True) # Initialize and load from checkpoint (no need to know original hyperparameters) restored_model = Transformer.init_and_load('./transformer.pt') print(restored_model.dim) # 512 ``` -------------------------------- ### Unwrap DDP Models Automatically Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt Use the auto_unwrap_model decorator to access model attributes directly even when the model is wrapped by Accelerate's DDP. ```python import torch from torch import nn from accelerate import Accelerator from pytorch_custom_utils import auto_unwrap_model @auto_unwrap_model( accelerator_instance_name='accelerator', model_instance_name='model' ) class Trainer: def __init__(self, dim): self.accelerator = Accelerator() self.model = nn.Linear(dim, dim) self.model = self.accelerator.prepare(self.model) # model is now wrapped, but custom_attr is accessible def get_weight_shape(self): # Accesses unwrapped model automatically return self.model.weight.shape trainer = Trainer(dim=512) print(trainer.get_weight_shape()) # torch.Size([512, 512]) ``` -------------------------------- ### Count Model Parameters with total_parameters Decorator Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt The total_parameters decorator adds a property to count all parameters in an nn.Module subclass. It can optionally filter to count only trainable parameters by setting count_only_requires_grad=True. ```python import torch from torch import nn from pytorch_custom_utils import total_parameters @total_parameters(count_only_requires_grad=False) class ResNet(nn.Module): def __init__(self, dim, num_blocks): super().__init__() self.blocks = nn.ModuleList([ nn.Sequential( nn.Linear(dim, dim), nn.ReLU(), nn.Linear(dim, dim) ) for _ in range(num_blocks) ]) def forward(self, x): for block in self.blocks: x = x + block(x) return x model = ResNet(dim=512, num_blocks=4) print(f"Total parameters: {model.total_parameters:,}") # Total parameters: 4,198,400 ``` -------------------------------- ### Masked Mean and Mask Combination Source: https://context7.com/lucidrains/pytorch-custom-utils/llms.txt Compute the mean of tensor elements only where a mask is true. `maybe_and_mask` safely combines multiple boolean masks, returning `None` if all inputs are `None`. ```python import torch from pytorch_custom_utils.utils import masked_mean, maybe_and_mask # Masked mean calculation values = torch.tensor([[1., 2., 3., 4.], [5., 6., 7., 8.]]) mask = torch.tensor([[True, True, False, False], [True, True, True, False]]) # Mean only over masked positions result = masked_mean(values, mask, dim=-1) print(result) # tensor([1.5000, 6.0000]) # Combine multiple masks (handles None safely) mask1 = torch.tensor([True, True, False, True]) mask2 = torch.tensor([True, False, False, True]) combined = maybe_and_mask(mask1, mask2) print(combined) # tensor([True, False, False, True]) # Returns None if all inputs are None result = maybe_and_mask(None, None) print(result) # None ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.