SoFunction
Updated on 2024-11-15

python artificial intelligence using RepVgg to achieve image classification example details

summaries

RepVgg makes VGG great again by reparameterizing the structure. By "VGG-style" I mean:

  • There is no branching structure. This is commonly referred to as plain or feed-forward architecture.
  • Use only 3x3 convolution.
  • Use only ReLU as an activation function.

The deeper version of RepVGG reached 84.16% correct! Countering a number of TRANSFORMERS!

How did RepVgg get there? Simply put:

  • First, train a multibranch model.
  • Then, the multi-branch model is equivalently converted to a one-way model
  • Most in, at the time of deployment, the deployment of converted single path models

I this article mainly explains how to use RepVgg to complete the image classification task, next we complete the project together in practice.

You can learn through this article:

  • How do you use data augmentation, including augmentation of transforms, CutOut, MixUp, CutMix, and other augmentations?
  • How to implement RepVGG model to achieve training?
  • How to equivalently convert a multi-branch model to a single path model?
  • How to use pytorch comes with blending accuracy?
  • How can I use gradient cropping to prevent gradient explosion?
  • How to train with DP Multi Graphics?
  • How to plot loss and acc curves?
  • How to generate val's assessment report?
  • How to write a test script to test a test set?
  • How to adjust the learning rate using cosine annealing strategy?
  • How to use AverageMeter class to count custom variables like ACC and loss?
  • How to understand and count ACC1 and ACC5?
  • How to use EMA?

installer

Install timm

Just use pip, command:

pip install timm

Data Enhancement Cutout and Mixup

In order to improve my results I have added Cutout and Mixup enhancements to my code. To implement these two enhancements you need to install torchtoolbox. install command:

pip install torchtoolbox

Cutout implementation, in transforms.

from  import Cutout
# Data pre-processing
transform = ([
    ((224, 224)),
    Cutout(),
    (),
    ([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
])

The package needs to be imported: from import Mixup.

Defining Mixup, and SoftTargetCrossEntropy

  mixup_fn = Mixup(
    mixup_alpha=0.8, cutmix_alpha=1.0, cutmix_minmax=None,
    prob=0.1, switch_prob=0.5, mode='batch',
    label_smoothing=0.1, num_classes=12)
 criterion_train = SoftTargetCrossEntropy()

Parameter details:

mixup_alpha (float): mixup alpha value, if > 0 then mixup is active.

cutmix_alpha (float): cutmix alpha value, if > 0, cutmix is active.

cutmix_minmax (List[float]): cutmix min/max image ratio, cutmix is active, use this vs alpha if not None.

If cutmix_minmax is set, cutmix_alpha defaults to 1.0.

prob (float): the probability of applying mixup or cutmix to each batch or element.

switch_prob (float): probability of switching cutmix and mixup when both are active.

mode (str): how to apply mixup/cutmix arguments (each 'batch', 'pair' (element pair), 'elem' (element).

correct_lam (bool): applied when the cutmix bbox is cropped by the image border. lambda correction

label_smoothing (float): applies label smoothing to the mixing target tensor.

num_classes (int): number of classes of the target.

EMA

EMA (Exponential Moving Average) is Exponential Moving Average. The practice in deep learning is to save a copy of the parameters in history, and after a certain training phase, take the parameters in history to do a smoothing to the currently learned parameters. The specific implementation is as follows:

class EMA():
    def __init__(self, model, decay):
         = model
         = decay
         = {}
         = {}
    def register(self):
        for name, param in .named_parameters():
            if param.requires_grad:
                [name] = ()
    def update(self):
        for name, param in .named_parameters():
            if param.requires_grad:
                assert name in 
                new_average = (1.0 - ) *  +  * [name]
                [name] = new_average.clone()
    def apply_shadow(self):
        for name, param in .named_parameters():
            if param.requires_grad:
                assert name in 
                [name] = 
                 = [name]
    def restore(self):
        for name, param in .named_parameters():
            if param.requires_grad:
                assert name in 
                 = [name]
         = {}

added to the model.

# Initialization
ema = EMA(model, 0.999)
()
# Synchronize update shadow weights after updating parameters during training
def train():
    ()
    ()
# Before eval, apply shadow weights; after eval, restore original model parameters
def evaluate():
    ema.apply_shadow()
    # evaluate
    ()

This ema is best used when fine-tuning, otherwise the validation set won't score, or will score very slowly.

Project structure

RepVgg_demo
├─data1
│  ├─Black-grass
│  ├─Charlock
│  ├─Cleavers
│  ├─Common Chickweed
│  ├─Common wheat
│  ├─Fat Hen
│  ├─Loose Silky-bent
│  ├─Maize
│  ├─Scentless Mayweed
│  ├─Shepherds Purse
│  ├─Small-flowered Cranesbill
│  └─Sugar beet
├─models
│  ├─__init__.py
│  ├─
│  └─se_block.py
├─mean_std.py
├─
├─
├─
└─

mean_std.py: calculates the values of mean and std. : Generate the dataset. : EMA scripts in models folder and se_block.py: code from the official pytorch version. - : Network files. - se_block.py: SE attention mechanism.

In order to be able to use mixed precision in the DP approach, it is also necessary to add @autocast() in front of the model's forward function.

Calculate mean and std

In order to make the model converge more quickly, we need to calculate the values of mean and std. Create a new mean_std.py and insert the code:

from  import ImageFolder
import torch
from torchvision import transforms
def get_mean_and_std(train_data):
    train_loader = (
        train_data, batch_size=1, shuffle=False, num_workers=0,
        pin_memory=True)
    mean = (3)
    std = (3)
    for X, _ in train_loader:
        for d in range(3):
            mean[d] += X[:, d, :, :].mean()
            std[d] += X[:, d, :, :].std()
    mean.div_(len(train_data))
    std.div_(len(train_data))
    return list(()), list(())
if __name__ == '__main__':
    train_dataset = ImageFolder(root=r'data1', transform=())
    print(get_mean_and_std(train_dataset))

Data set structure:

Run results:

([0.3281186, 0.28937867, 0.20702125], [0.09407319, 0.09732835, 0.106712654])

Record this result and use it later!

Generating data sets

The structure of the dataset for image classification, which we have organized and returned, looks like this

data
├─Black-grass
├─Charlock
├─Cleavers
├─Common Chickweed
├─Common wheat
├─Fat Hen
├─Loose Silky-bent
├─Maize
├─Scentless Mayweed
├─Shepherds Purse
├─Small-flowered Cranesbill
└─Sugar beet

The default loading method for pytorch and keras is the ImageNet dataset format in the form of

├─data
│  ├─val
│  │   ├─Black-grass
│  │   ├─Charlock
│  │   ├─Cleavers
│  │   ├─Common Chickweed
│  │   ├─Common wheat
│  │   ├─Fat Hen
│  │   ├─Loose Silky-bent
│  │   ├─Maize
│  │   ├─Scentless Mayweed
│  │   ├─Shepherds Purse
│  │   ├─Small-flowered Cranesbill
│  │   └─Sugar beet
│  └─train
│      ├─Black-grass
│      ├─Charlock
│      ├─Cleavers
│      ├─Common Chickweed
│      ├─Common wheat
│      ├─Fat Hen
│      ├─Loose Silky-bent
│      ├─Maize
│      ├─Scentless Mayweed
│      ├─Shepherds Purse
│      ├─Small-flowered Cranesbill
│      └─Sugar beet

New format conversion script, insert code:

import glob
import os
import shutil
image_list=('data1/*/*.png')
print(image_list)
file_dir='data'
if (file_dir):
    print('true')
    #(file_dir)
    (file_dir)# Delete and recreate
    (file_dir)
else:
    (file_dir)
from sklearn.model_selection import train_test_split
trainval_files, val_files = train_test_split(image_list, test_size=0.3, random_state=42)
train_dir='train'
val_dir='val'
train_root=(file_dir,train_dir)
val_root=(file_dir,val_dir)
for file in trainval_files:
    file_class=("\\","/").split('/')[-2]
    file_name=("\\","/").split('/')[-1]
    file_class=(train_root,file_class)
    if not (file_class):
        (file_class)
    (file, file_class + '/' + file_name)
for file in val_files:
    file_class=("\\","/").split('/')[-2]
    file_name=("\\","/").split('/')[-1]
    file_class=(val_root,file_class)
    if not (file_class):
        (file_class)
    (file, file_class + '/' + file_name)

Completing the above opens up training and testing.

The above is python artificial intelligence using RepVgg to achieve image classification example details, more information about python artificial intelligence RepVgg image classification please pay attention to my other related articles!