Loading files
"""Common functions to marshal data to/from PyTorch
"""
import collections
import warnings
from typing import Tuple
import numpy as np
import torch
from torch import nn
def set_trainable(module: nn.Module, trainable=True, freeze_bn=True):
"""
Change 'requires_grad' value for module and it's child modules and
optionally freeze batchnorm modules.
:param module: Module to change
:param trainable: True to enable training
:param freeze_bn: True to freeze batch norm
:return: None
"""
trainable = bool(trainable)
freeze_bn = bool(freeze_bn)
for param in module.parameters():
param.requires_grad = trainable
# TODO: Add support for ABN, InplaceABN
bn_types = nn.BatchNorm1d, nn.BatchNorm2d, nn.BatchNorm3d, nn.SyncBatchNorm
if isinstance(module, bn_types):
module.track_running_stats = freeze_bn
for m in module.modules():
if isinstance(m, bn_types):
module.track_running_stats = freeze_bn
def freeze_bn(module: nn.Module):
"""Freezes BatchNorm
"""
warnings.warn("This method is deprecated. Please use `set_trainable`.")
set_trainable(module, True, False)
def logit(x: torch.Tensor, eps=1e-5):
x = torch.clamp(x.float(), eps, 1.0 - eps)
return torch.log(x / (1.0 - x))
def count_parameters(model: nn.Module) -> Tuple[int, int]:
"""
Count number of total and trainable parameters of a model
:param model: A model
:return: Tuple (total, trainable)
"""
total = sum(p.numel() for p in model.parameters())
trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total, trainable
def to_numpy(x) -> np.ndarray:
"""
Convert whatever to numpy array
:param x: List, tuple, PyTorch tensor or numpy array
:return: Numpy array
"""
if isinstance(x, np.ndarray):
return x
elif isinstance(x, torch.Tensor):
return x.detach().cpu().numpy()
elif isinstance(x, (list, tuple, int, float)):
return np.array(x)
else:
raise ValueError("Unsupported type")
def to_tensor(x, dtype=None) -> torch.Tensor:
if isinstance(x, torch.Tensor):
if dtype is not None:
x = x.type(dtype)
return x
if isinstance(x, np.ndarray):
x = torch.from_numpy(x)
if dtype is not None:
x = x.type(dtype)
return x
if isinstance(x, (list, tuple)):
x = np.ndarray(x)
x = torch.from_numpy(x)
if dtype is not None:
x = x.type(dtype)
return x
raise ValueError("Unsupported input type" + str(type(x)))
def tensor_from_rgb_image(image: np.ndarray) -> torch.Tensor:
image = np.moveaxis(image, -1, 0)
image = np.ascontiguousarray(image)
image = torch.from_numpy(image)
return image
def tensor_from_mask_image(mask: np.ndarray) -> torch.Tensor:
if len(mask.shape) == 2:
mask = np.expand_dims(mask, -1)
return tensor_from_rgb_image(mask)
def rgb_image_from_tensor(
image: torch.Tensor, mean, std, max_pixel_value=255.0, dtype=np.uint8
) -> np.ndarray:
image = np.moveaxis(to_numpy(image), 0, -1)
mean = to_numpy(mean)
std = to_numpy(std)
rgb_image = (max_pixel_value * (image * std + mean)).astype(dtype)
return rgb_image
def maybe_cuda(x):
if torch.cuda.is_available():
return x.cuda()
return x
def get_optimizable_parameters(model: nn.Module):
"""
Return list of optimizable parameters from the model
:param model:
:return:
"""
return filter(lambda x: x.requires_grad, model.parameters())
def transfer_weights(model: nn.Module, model_state_dict: collections.OrderedDict):
"""
Copy weights from state dict to model, skipping layers that are incompatible.
This method is helpful if you are doing some model surgery and want to load
part of the model weights into different model.
:param model: Model to load weights into
:param model_state_dict: Model state dict to load weights from
:return: None
"""
for name, value in model_state_dict.items():
try:
model.load_state_dict(
collections.OrderedDict([(name, value)]), strict=False
)
except Exception as e:
print(e)
b150d1354This file is pinned to the selected release. Download the original to open it in your design tool.