Collection of Common PyTorch Code Snippets

Click the above Beginner’s Guide to Vision“, select to add “Star” or “Pin

Heavyweight content delivered first-handCollection of Common PyTorch Code Snippets

Zhang Hao: Master’s student at the School of Computer Science, Nanjing University, focusing on computer vision and machine learning, particularly visual recognition and deep learning. Personal homepage:

http://lamda.nju.edu.cn/zhangh/

Original Zhihu link:

https://zhuanlan.zhihu.com/p/59205847?

This code is based on PyTorch version 1.0 and requires the following packages:

import collections
import os
import shutil
import tqdm

import numpy as np
import PIL.Image
import torch
import torchvision

Basic Configuration

Check PyTorch Version

torch.__version__               # PyTorch version
torch.version.cuda              # Corresponding CUDA version
torch.backends.cudnn.version()  # Corresponding cuDNN version
torch.cuda.get_device_name(0)   # GPU type

Update PyTorch

PyTorch will be installed in the anaconda3/lib/python3.7/site-packages/torch/ directory.

conda update pytorch torchvision -c pytorch

Set Random Seed

torch.manual_seed(0)
torch.cuda.manual_seed_all(0)

Specify Program to Run on Specific GPU Card

Specify environment variable in the command line:

CUDA_VISIBLE_DEVICES=0,1 python train.py

Or specify in the code:

os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'

Check if CUDA is available:

torch.cuda.is_available()

Set cuDNN Benchmark Mode

Benchmark mode will improve computation speed, but due to randomness in computation, the results of each network feedforward may vary slightly.

torch.backends.cudnn.benchmark = True

If you want to avoid such result fluctuations, set:

torch.backends.cudnn.deterministic = True

Clear GPU Memory

Sometimes after terminating the run with Control-C, GPU memory is not released promptly and needs to be cleared manually. In PyTorch, you can:

torch.cuda.empty_cache()

Or in the command line, first use ps to find the PID of the program, and then use kill to terminate that process:

ps aux | grep python
kill -9 [pid]

Or directly reset the GPU that has not been cleared:

nvidia-smi --gpu-reset -i [gpu_id]

Tensor Processing

Basic Information of Tensor

tensor.type()   # Data type
tensor.size()   # Shape of the tensor. It is a subclass of Python tuple
tensor.dim()    # Number of dimensions.

Data Type Conversion

# Set default tensor type. Float in PyTorch is much faster than double.
torch.set_default_tensor_type(torch.FloatTensor)

# Type conversions.
tensor = tensor.cuda()
tensor = tensor.cpu()
tensor = tensor.float()
tensor = tensor.long()

torch.Tensor and np.ndarray Conversion

# torch.Tensor -> np.ndarray.
ndarray = tensor.cpu().numpy()

# np.ndarray -> torch.Tensor.
tensor = torch.from_numpy(ndarray).float()
tensor = torch.from_numpy(ndarray.copy()).float()  # If ndarray has negative stride

torch.Tensor and PIL.Image Conversion

In PyTorch, tensors default to N×D×H×W order and the data range is [0, 1], requiring transpose and normalization.

# torch.Tensor -> PIL.Image.
image = PIL.Image.fromarray(torch.clamp(tensor * 255, min=0, max=255
    ).byte().permute(1, 2, 0).cpu().numpy())
image = torchvision.transforms.functional.to_pil_image(tensor)  # Equivalent way

# PIL.Image -> torch.Tensor.
tensor = torch.from_numpy(np.asarray(PIL.Image.open(path))
    ).permute(2, 0, 1).float() / 255
tensor = torchvision.transforms.functional.to_tensor(PIL.Image.open(path))  # Equivalent way

np.ndarray and PIL.Image Conversion

# np.ndarray -> PIL.Image.
image = PIL.Image.fromarray(ndarray.astype(np.uint8))

# PIL.Image -> np.ndarray.
darray = np.asarray(PIL.Image.open(path))

Extract Value from a Tensor Containing Only One Element

This is particularly useful for tracking the change of loss during training. Otherwise, this will accumulate the computation graph, causing GPU memory usage to increase.

value = tensor.item()

Tensor Reshaping

Tensor reshaping is often needed to input features from convolutional layers into fully connected layers. Compared to torch.view, torch.reshape can automatically handle cases where the input tensor is non-contiguous.

tensor = torch.reshape(tensor, shape)

Shuffle Order

tensor = tensor[torch.randperm(tensor.size(0))]  # Shuffle the first dimension

Horizontal Flip

PyTorch does not support tensor[::-1] style negative stride operations; horizontal flipping can be achieved with tensor indexing.

# Assume tensor has shape N*D*H*W.
tensor = tensor[:, :, :, torch.arange(tensor.size(3) - 1, -1, -1).long()]

Copy Tensor

There are three ways to copy, corresponding to different needs.

# Operation                 |  New/Shared memory | Still in computation graph |
tensor.clone()            # |        New         |          Yes               |
tensor.detach()           # |      Shared        |          No                |
tensor.detach().clone()()  # |        New         |          No                |

Concatenate Tensors

Note that the difference between torch.cat and torch.stack is that torch.cat concatenates along the given dimension, while torch.stack adds a dimension. For example, when the parameters are three 10×5 tensors, the result of torch.cat is a 30×5 tensor, while the result of torch.stack is a 3×10×5 tensor.

tensor = torch.cat(list_of_tensors, dim=0)
tensor = torch.stack(list_of_tensors, dim=0)

Convert Integer Labels to One-Hot Encoding

Labels in PyTorch default to starting from 0.

N = tensor.size(0)
one_hot = torch.zeros(N, num_classes).long()
one_hot.scatter_(dim=1, index=torch.unsqueeze(tensor, dim=1), src=torch.ones(N, num_classes).long())

Get Non-Zero/Zero Elements

torch.nonzero(tensor)               # Index of non-zero elements
torch.nonzero(tensor == 0)          # Index of zero elements
torch.nonzero(tensor).size(0)       # Number of non-zero elements
torch.nonzero(tensor == 0).size(0)  # Number of zero elements

Tensor Expansion

# Expand tensor of shape 64*512 to shape 64*512*7*7.
torch.reshape(tensor, (64, 512, 1, 1)).expand(64, 512, 7, 7)

Matrix Multiplication

# Matrix multiplication: (m*n) * (n*p) -> (m*p).
result = torch.mm(tensor1, tensor2)

# Batch matrix multiplication: (b*m*n) * (b*n*p) -> (b*m*p).
result = torch.bmm(tensor1, tensor2)

# Element-wise multiplication.
result = tensor1 * tensor2

Calculate Pairwise Euclidean Distance Between Two Sets of Data

# X1 is of shape m*d.
X1 = torch.unsqueeze(X1, dim=1).expand(m, n, d)
# X2 is of shape n*d.
X2 = torch.unsqueeze(X2, dim=0).expand(m, n, d)
# dist is of shape m*n, where dist[i][j] = sqrt(|X1[i, :] - X[j, :]|^2)
dist = torch.sqrt(torch.sum((X1 - X2) ** 2, dim=2))

Model Definition

Convolutional Layer

The most commonly used convolutional layer configurations are:

conv = torch.nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=True)
conv = torch.nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1, padding=0, bias=True)

If the convolutional layer configuration is complex and inconvenient to calculate the output size, you can use the following visualization tool for assistance:

Link: https://ezyang.github.io/convolution-visualizer/index.html

Global Average Pooling (GAP) Layer

gap = torch.nn.AdaptiveAvgPool2d(output_size=1)

Bilinear Pooling

X = torch.reshape(N, D, H * W)                        # Assume X has shape N*D*H*W
X = torch.bmm(X, torch.transpose(X, 1, 2)) / (H * W)  # Bilinear pooling
assert X.size() == (N, D, D)
X = torch.reshape(X, (N, D * D))
X = torch.sign(X) * torch.sqrt(torch.abs(X) + 1e-5)   # Signed-sqrt normalization
X = torch.nn.functional.normalize(X)                  # L2 normalization

Multi-GPU Synchronized Batch Normalization

When using torch.nn.DataParallel to run the code on multiple GPU cards, the default operation of PyTorch’s BN layer is to compute the mean and standard deviation independently on each card. Synchronized BN uses data from all cards to compute the mean and standard deviation of the BN layer, mitigating the issue of inaccurate mean and standard deviation estimation when the batch size is small, making it an effective performance enhancement technique in tasks like object detection.

Link: https://github.com/vacancy/Synchronized-BatchNorm-PyTorch

Similar to BN Moving Average

To achieve operations similar to BN moving average, use in-place operations in the forward function to assign values to the moving average.

class BN(torch.nn.Module)
    def __init__(self):
        ...
        self.register_buffer('running_mean', torch.zeros(num_features))

    def forward(self, X):
        ...
        self.running_mean += momentum * (current - self.running_mean)

Calculate Total Number of Parameters in the Model

num_parameters = sum(torch.numel(parameter) for parameter in model.parameters())

Output Model Information Similar to Keras model.summary()

Link: https://github.com/sksq96/pytorch-summary

Model Weight Initialization

Note the difference between model.modules() and model.children(): model.modules() iterates through all sublayers of the model, while model.children() only iterates through one layer of the model.

# Common practice for initialization.
for layer in model.modules():
    if isinstance(layer, torch.nn.Conv2d):
        torch.nn.init.kaiming_normal_(layer.weight, mode='fan_out',
                                      nonlinearity='relu')
        if layer.bias is not None:
            torch.nn.init.constant_(layer.bias, val=0.0)
    elif isinstance(layer, torch.nn.BatchNorm2d):
        torch.nn.init.constant_(layer.weight, val=1.0)
        torch.nn.init.constant_(layer.bias, val=0.0)
    elif isinstance(layer, torch.nn.Linear):
        torch.nn.init.xavier_normal_(layer.weight)
        if layer.bias is not None:
            torch.nn.init.constant_(layer.bias, val=0.0)

# Initialization with given tensor.
layer.weight = torch.nn.Parameter(tensor)

Using Pre-trained Models for Certain Layers

Note that if the saved model is torch.nn.DataParallel, the current model also needs to be:

model.load_state_dict(torch.load('model,pth'), strict=False)

Loading a Model Saved on GPU to CPU

model.load_state_dict(torch.load('model,pth', map_location='cpu'))

Data Preparation, Feature Extraction, and Fine-tuning

Get Basic Information of Video Data

import cv2
video = cv2.VideoCapture(mp4_path)
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
num_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
fps = int(video.get(cv2.CAP_PROP_FPS))
video.release()

TSN Samples One Frame of Video per Segment

K = self._num_segments
if is_train:
    if num_frames > K:
        # Random index for each segment.
        frame_indices = torch.randint(
            high=num_frames // K, size=(K,), dtype=torch.long)
        frame_indices += num_frames // K * torch.arange(K)
    else:
        frame_indices = torch.randint(
            high=num_frames, size=(K - num_frames,), dtype=torch.long)
        frame_indices = torch.sort(torch.cat((
            torch.arange(num_frames), frame_indices)))[0]
else:
    if num_frames > K:
        # Middle index for each segment.
        frame_indices = num_frames / K // 2
        frame_indices += num_frames // K * torch.arange(K)
    else:
        frame_indices = torch.sort(torch.cat((                               
            torch.arange(num_frames), torch.arange(K - num_frames))))[0]
assert frame_indices.size() == (K,)
return [frame_indices[i] for i in range(K)]

Extract Convolution Features from a Certain Layer of ImageNet Pre-trained Model

# VGG-16 relu5-3 feature.
model = torchvision.models.vgg16(pretrained=True).features[:-1]
# VGG-16 pool5 feature.
model = torchvision.models.vgg16(pretrained=True).features
# VGG-16 fc7 feature.
model = torchvision.models.vgg16(pretrained=True)
model.classifier = torch.nn.Sequential(*list(model.classifier.children())[:-3])
# ResNet GAP feature.
model = torchvision.models.resnet18(pretrained=True)
model = torch.nn.Sequential(collections.OrderedDict(
    list(model.named_children())[:-1]))

with torch.no_grad():
    model.eval()
    conv_representation = model(image)

Extract Convolution Features from Multiple Layers of ImageNet Pre-trained Model

class FeatureExtractor(torch.nn.Module):
    """Helper class to extract several convolution features from the given
    pre-trained model.

    Attributes:
        _model, torch.nn.Module.
        _layers_to_extract, list<str> or set<str>

    Example:
        >>> model = torchvision.models.resnet152(pretrained=True)
        >>> model = torch.nn.Sequential(collections.OrderedDict(
                list(model.named_children())[:-1]))
        >>> conv_representation = FeatureExtractor(
                pretrained_model=model,
                layers_to_extract={'layer1', 'layer2', 'layer3', 'layer4'})(image)
    """
    def __init__(self, pretrained_model, layers_to_extract):
        torch.nn.Module.__init__(self)
        self._model = pretrained_model
        self._model.eval()
        self._layers_to_extract = set(layers_to_extract)

    def forward(self, x):
        with torch.no_grad():
            conv_representation = []
            for name, layer in self._model.named_children():
                x = layer(x)
                if name in self._layers_to_extract:
                    conv_representation.append(x)
            return conv_representation

Other Pre-trained Models

Link: https://github.com/Cadene/pretrained-models.pytorch

Fine-tune Fully Connected Layer

model = torchvision.models.resnet18(pretrained=True)
for param in model.parameters():
    param.requires_grad = False
model.fc = nn.Linear(512, 100)  # Replace the last fc layer
optimizer = torch.optim.SGD(model.fc.parameters(), lr=1e-2, momentum=0.9, weight_decay=1e-4)

Fine-tune Fully Connected Layer with Higher Learning Rate, Convolution Layer with Lower Learning Rate

model = torchvision.models.resnet18(pretrained=True)
finetuned_parameters = list(map(id, model.fc.parameters()))
conv_parameters = (p for p in model.parameters() if id(p) not in finetuned_parameters)
parameters = [{'params': conv_parameters, 'lr': 1e-3}, 
              {'params': model.fc.parameters()}]
optimizer = torch.optim.SGD(parameters, lr=1e-2, momentum=0.9, weight_decay=1e-4)

Model Training

Common Training and Validation Data Preprocessing

Among them, the ToTensor operation will convert PIL.Image or np.ndarray with shape H×W×D and data range [0, 255] into torch.Tensor with shape D×H×W and data range [0.0, 1.0].

train_transform = torchvision.transforms.Compose([
    torchvision.transforms.RandomResizedCrop(size=224,
                                             scale=(0.08, 1.0)),
    torchvision.transforms.RandomHorizontalFlip(),
    torchvision.transforms.ToTensor(),
    torchvision.transforms.Normalize(mean=(0.485, 0.456, 0.406),
                                     std=(0.229, 0.224, 0.225)),
 ])
 val_transform = torchvision.transforms.Compose([
    torchvision.transforms.Resize(224),
    torchvision.transforms.CenterCrop(224),
    torchvision.transforms.ToTensor(),
    torchvision.transforms.Normalize(mean=(0.485, 0.456, 0.406),
                                     std=(0.229, 0.224, 0.225)),
])

Basic Code Framework for Training

for t in epoch(80):
    for images, labels in tqdm.tqdm(train_loader, desc='Epoch %3d' % (t + 1)):
        images, labels = images.cuda(), labels.cuda()
        scores = model(images)
        loss = loss_function(scores, labels)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

Label Smoothing

for images, labels in train_loader:
    images, labels = images.cuda(), labels.cuda()
    N = labels.size(0)
    # C is the number of classes.
    smoothed_labels = torch.full(size=(N, C), fill_value=0.1 / (C - 1)).cuda()
    smoothed_labels.scatter_(dim=1, index=torch.unsqueeze(labels, dim=1), value=0.9)

    score = model(images)
    log_prob = torch.nn.functional.log_softmax(score, dim=1)
    loss = -torch.sum(log_prob * smoothed_labels) / N
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

Mixup

beta_distribution = torch.distributions.beta.Beta(alpha, alpha)
for images, labels in train_loader:
    images, labels = images.cuda(), labels.cuda()

    # Mixup images.
    lambda_ = beta_distribution.sample([]).item()
    index = torch.randperm(images.size(0)).cuda()
    mixed_images = lambda_ * images + (1 - lambda_) * images[index, :]

    # Mixup loss.    
    scores = model(mixed_images)
    loss = (lambda_ * loss_function(scores, labels) 
            + (1 - lambda_) * loss_function(scores, labels[index]))

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

L1 Regularization

l1_regularization = torch.nn.L1Loss(reduction='sum')
loss = ...  # Standard cross-entropy loss
for param in model.parameters():
    loss += torch.sum(torch.abs(param))
loss.backward()

Do Not Apply L2 Regularization/Weight Decay on Bias Terms

bias_list = (param for name, param in model.named_parameters() if name[-4:] == 'bias')
others_list = (param for name, param in model.named_parameters() if name[-4:] != 'bias')
parameters = [{'parameters': bias_list, 'weight_decay': 0},                
              {'parameters': others_list}]
optimizer = torch.optim.SGD(parameters, lr=1e-2, momentum=0.9, weight_decay=1e-4)

Gradient Clipping

torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=20)

Calculate Accuracy of Softmax Output

score = model(images)
prediction = torch.argmax(score, dim=1)
num_correct = torch.sum(prediction == labels).item()
accuruacy = num_correct / labels.size(0)

Visualize the Computation Graph of Model Feedforward

Link: https://github.com/szagoruyko/pytorchviz

Visualize Learning Curves

There are two options: Facebook’s own Visdom and Tensorboard.

https://github.com/facebookresearch/visdom

https://github.com/lanpa/tensorboardX

# Example using Visdom.
vis = visdom.Visdom(env='Learning curve', use_incoming_socket=False)
assert self._visdom.check_connection()
self._visdom.close()
options = collections.namedtuple('Options', ['loss', 'acc', 'lr'])(
    loss={'xlabel': 'Epoch', 'ylabel': 'Loss', 'showlegend': True},
    acc={'xlabel': 'Epoch', 'ylabel': 'Accuracy', 'showlegend': True},
    lr={'xlabel': 'Epoch', 'ylabel': 'Learning rate', 'showlegend': True})

for t in epoch(80):
    tran(...)
    val(...)
    vis.line(X=torch.Tensor([t + 1]), Y=torch.Tensor([train_loss]),
             name='train', win='Loss', update='append', opts=options.loss)
    vis.line(X=torch.Tensor([t + 1]), Y=torch.Tensor([val_loss]),
             name='val', win='Loss', update='append', opts=options.loss)
    vis.line(X=torch.Tensor([t + 1]), Y=torch.Tensor([train_acc]),
             name='train', win='Accuracy', update='append', opts=options.acc)
    vis.line(X=torch.Tensor([t + 1]), Y=torch.Tensor([val_acc]),
             name='val', win='Accuracy', update='append', opts=options.acc)
    vis.line(X=torch.Tensor([t + 1]), Y=torch.Tensor([lr]),
             win='Learning rate', update='append', opts=options.lr)

Get Current Learning Rate

# If there is one global learning rate (which is the common case).
lr = next(iter(optimizer.param_groups))['lr']

# If there are multiple learning rates for different layers.
all_lr = []
for param_group in optimizer.param_groups:
    all_lr.append(param_group['lr'])

Learning Rate Decay

# Reduce learning rate when validation accuracy plateaus.
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='max', patience=5, verbose=True)
for t in range(0, 80):
    train(...); val(...)
    scheduler.step(val_acc)

# Cosine annealing learning rate.
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=80)
# Reduce learning rate by 10 at given epochs.
scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[50, 70], gamma=0.1)
for t in range(0, 80):
    scheduler.step()    
    train(...); val(...)

# Learning rate warmup by 10 epochs.
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lambda t: t / 10)
for t in range(0, 10):
    scheduler.step()
    train(...); val(...)

Save and Load Checkpoints

Note that to be able to resume training, we need to save both the model and optimizer states, as well as the current training epoch.

# Save checkpoint.
is_best = current_acc > best_acc
best_acc = max(best_acc, current_acc)
checkpoint = {
    'best_acc': best_acc,    
    'epoch': t + 1,
    'model': model.state_dict(),
    'optimizer': optimizer.state_dict(),
}
model_path = os.path.join('model', 'checkpoint.pth.tar')
torch.save(checkpoint, model_path)
if is_best:
    shutil.copy('checkpoint.pth.tar', model_path)

# Load checkpoint.
if resume:
    model_path = os.path.join('model', 'checkpoint.pth.tar')
    assert os.path.isfile(model_path)
    checkpoint = torch.load(model_path)
best_acc = checkpoint['best_acc']
start_epoch = checkpoint['epoch']
model.load_state_dict(checkpoint['model'])
optimizer.load_state_dict(checkpoint['optimizer'])
print('Load checkpoint at epoch %d.' % start_epoch)

Calculate Accuracy, Precision, and Recall

# data['label'] and data['prediction'] are groundtruth label and prediction 
# for each image, respectively.
accuracy = np.mean(data['label'] == data['prediction']) * 100

# Compute precision and recall for each class.
for c in range(len(num_classes)):
    tp = np.dot((data['label'] == c).astype(int),
                (data['prediction'] == c).astype(int))
    tp_fp = np.sum(data['prediction'] == c)
    tp_fn = np.sum(data['label'] == c)
    precision = tp / tp_fp * 100
    recall = tp / tp_fn * 100

Other PyTorch Considerations

Model Definition

  • It is recommended to use the torch.nn module to define layers with parameters and pooling layers, while activation functions should use torch.nn.functional directly. The difference between the torch.nn module and torch.nn.functional is that the torch.nn module calls torch.nn.functional at the bottom level during computation, but the torch.nn module includes the parameters of that layer and can handle both training and testing network states. When using torch.nn.functional, be aware of the network state, such as:

def forward(self, x):
    ...
    x = torch.nn.functional.dropout(x, p=0.5, training=self.training)
  • Switch network states with model.train() and model.eval() before model(x).

  • Code blocks that do not require gradient calculation should be enclosed in with torch.no_grad(). The difference between model.eval() and torch.no_grad() is that model.eval() switches the network to the testing state, for example, BN and dropout use different computation methods during training and testing. torch.no_grad() disables the automatic differentiation mechanism of PyTorch tensors to reduce memory usage and speed up computation, and the results cannot perform loss.backward().

  • The input to torch.nn.CrossEntropyLoss does not need to go through Softmax. torch.nn.CrossEntropyLoss is equivalent to torch.nn.functional.log_softmax + torch.nn.NLLLoss.

  • Use optimizer.zero_grad() before loss.backward() to clear accumulated gradients. optimizer.zero_grad() and model.zero_grad() have the same effect.

PyTorch Performance and Debugging

  • In torch.utils.data.DataLoader, try to set pin_memory=True. For particularly small datasets like MNIST, setting pin_memory=False may actually be faster. The setting of num_workers needs to be found through experimentation for the fastest value.

  • Use del to promptly delete unnecessary intermediate variables, saving GPU memory.

  • Using in-place operations can save GPU memory, such as:

x = torch.nn.functional.relu(x, inplace=True)
  • Reduce data transfer between CPU and GPU. For example, if you want to know the loss and accuracy for each mini-batch in an epoch, accumulating them in GPU and transferring them back to CPU at the end of the epoch is faster than transferring each mini-batch individually.

  • Using half-precision floating points with half() can lead to some speed improvements, but specific efficiency depends on the GPU model. Be cautious of stability issues due to low numerical precision.

  • Frequently use assert tensor.size() == (N, D, H, W) as a debugging method to ensure the tensor dimensions match your expectations.

  • Avoid using one-dimensional tensors except for labels y; use n*1 two-dimensional tensors instead to avoid unexpected results from one-dimensional tensor calculations.

  • Profile the time spent in different parts of the code:

with torch.autograd.profiler.profile(enabled=True, use_cuda=False) as profile:
    ...
print(profile)

Or run in the command line:

python -m torch.utils.bottleneck main.py

Acknowledgments

Thanks to @someflow and @El tnoto for their corrections. Due to the author’s limited knowledge and time constraints, errors in the code are inevitable. Readers are encouraged to provide criticism and corrections.

References

  • PyTorch official code: pytorch/examples (https://link.zhihu.com/?target=https%3A//github.com/pytorch/examples)

  • PyTorch forum: PyTorch Forums (https://link.zhihu.com/?target=https%3A//discuss.pytorch.org/latest%3Forder%3Dviews)

  • PyTorch documentation: http://pytorch.org/docs/stable/index.html (https://link.zhihu.com/?target=http%3A//pytorch.org/docs/stable/index.html)

  • Other public implementations based on PyTorch cannot be listed one by one.

Download 1: OpenCV-Contrib Extension Module Chinese Version Tutorial
Reply in the “Beginner’s Guide to Vision” WeChat public account:Extension Module Chinese Tutorial, to download the first OpenCV extension module tutorial in Chinese, covering installation of extension modules, SFM algorithms, stereo vision, object tracking, biological vision, super-resolution processing and more than twenty chapters.
Download 2: Python Vision Practical Projects 52 Lectures
Reply in the “Beginner’s Guide to Vision” WeChat public account:Python Vision Practical Projects, to download 31 vision practical projects including image segmentation, mask detection, lane line detection, vehicle counting, eyeliner addition, license plate recognition, character recognition, emotion detection, text content extraction, facial recognition, to help quickly learn computer vision.
Download 3: OpenCV Practical Projects 20 Lectures
Reply in the “Beginner’s Guide to Vision” WeChat public account:OpenCV Practical Projects 20 Lectures, to download 20 practical projects based on OpenCV to advance OpenCV learning.

Discussion Group

Welcome to join the reader group of the public account to communicate with peers. Currently, there are WeChat groups for SLAM, 3D vision, sensors, autonomous driving, computational photography, detection, segmentation, recognition, medical imaging, GAN, algorithm competitions and more (will gradually subdivide in the future).Please scan the WeChat ID below to join the group, and note: “nickname + school/company + research direction”, for example: “Zhang San + Shanghai Jiao Tong University + Vision SLAM”. Please follow the format for notes, otherwise you will not be approved. Successful additions will be invited to relevant WeChat groups based on research direction. Please do not send ads in the group, otherwise you will be removed from the group, thank you for your understanding~

Collection of Common PyTorch Code Snippets

Collection of Common PyTorch Code Snippets

Leave a Comment