Introduction to pytorch Image classification based on PyTorch

Introduction to pytorch (1) Introduction to pytorch

Fish Cat Classifier

task

Design a classifier to distinguish fish from cats.

🐟🐱

data

ImageNet: A standard collection of images used to train neural networks that contains more than 14 million images and 2000 image categories.
github has the download code, but I'm always not running right, so I've just downloaded the pictures from other sources. Extraction Code: pypt)

dataset and data loader

pytorch uses dataset and data loader to establish a connection between data and a neural network.
Datasets that conform to the following classes can be trained by feeding neural networks.

class Dataset(object):
    def __getitem__(self, index):
        raise NotImplementedError
    def __len__(self):
        raise NotImplementedError

len: Returns the length of the data.
getitem: Returns the corresponding tensor and label for each batch_size.

Establishing training datasets

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data
import torch.nn.functional as F
import torchvision
from torchvision import transforms
from PIL import Image


train_data_path = "./train/"

transforms = transforms.Compose([
    transforms.Resize(64),  # Convert to 64*64
    transforms.ToTensor(),  # Convert image to tensor
    transforms.Normalize(mean=[0.485, 0.456, 0.406],  # normalize
                         std=[0.229, 0.224, 0.225])
])
train_data = torchvision.datasets.ImageFolder(root=train_data_path, transform=transforms)

Establish validation and test datasets

val_data_path = "./val/"
val_data = torchvision.datasets.ImageFolder(root=val_data_path,
                                            transform=transforms)
test_data_path = "./test/"
test_data = torchvision.datasets.ImageFolder(root=test_data_path,
                                             transform=transforms)

Create dataloder

batch_size = 64

train_data_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size)
val_data_loader = torch.utils.data.DataLoader(val_data, batch_size=batch_size)
test_data_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size)

batch_size

Understand the number of data fed to the network each time. A larger batch_size allows the program to learn global information better, but takes up more memory space. The pytorch default batch_size is 1.

Setting up a neural network

It contains:

  1. One input layer: processes the input tensor
  2. Output layer: used to determine type
  3. Hidden Layer
# Define Neural Network
class net(nn.Module):
    def __init__(self):
        super(net, self).__init__()
        self.fc1 = nn.Linear(12288, 84)  # 64*64*3
        self.fc2 = nn.Linear(84, 20)
        self.fc3 = nn.Linear(20, 2)
    def forward(self, x):
        x = nn.ReLU(self.fc1(x))
        x = nn.ReLU(self.fc2(x))
        x = nn.Softmax(self.fc3(x))
        return x
  • init() is used to set up network layers
  • forward() is used to describe the flow of data in training or prediction

lossfunction

pytorch sets loss function to determine how to update the network to achieve the desired results.
pytorch contains the vast majority of loss function functions and can also use custom functions.
CrossEntropyLoss is chosen as the loss function. It combines nn.LogSoftmax() and nn.NLLLoss() functions.
softmax: S i = e i ∑ i e i S_i=\frac{e^i}{\sum_{i}e^i}\quad Si​=∑i​eiei​
Cross-Entropy:
∑ i p i l o g ( p i ) \sum_{i}p_ilog(p_i) i∑​pi​log(pi​)
So modify forward.

def forward(self):
    # Convert to 1D vector
    x = x.view(-1, 12288)
    x = F.relu(self.fc1(x))
    x = F.relu(self.fc2(x))
    x = self.fc3(x)
    return x

optimizing

Use the optimizer to keep up with each training of the neural network.
The models included SGD (Random Gradient Decrease), AdaGrad (Learning Rate is different for each parameter), RMSProp (Setting Decay Factor), and Adam (Self-designed Learning Rate).

net = net()
optimizer = optim.Adam(net.parameters(), lr=0.001)

train

def train(model, loss_fn, device, optimizer, epochs=20):
    train_loss = 0.0
    val_loss = 0.0
    model.train()  # Training mode
    for epoch in range(epochs):
        for batch in train_data_loader:
            optimizer.zero_grad()  # Empty last calculated gradient
            inputs, traget = batch
            inputs, traget = inputs.to(device), traget.to(device)  # Put the tensor on the gpu, if possible
            output = model.forward(inputs)
            loss = loss_fn(output, traget)  # Calculating loss
            loss.backward()  # Reverse Propagation
            optimizer.step()  # Update Weights
            train_loss += loss.data.item()
        train_loss /= len(train_data)

        model.eval()  # Test mode
        num_correct = 0
        num_examples = 0
        for batch in val_data_loader:
            inputs, traget = batch
            inputs, traget = inputs.to(device), traget.to(device)
            output = model.forward(inputs)
            loss = loss_fn(output, traget)
            val_loss += loss.data.item()
            correct = torch.eq(torch.max(F.softmax(output, dim=1), dim=1)[1], traget).view(-1)
            num_correct += sum(correct).item()
            num_examples += correct.shape[0]
        val_loss /= len(val_data)
        print(
            'epoch[{}|{}],train_loss:{:.4f},val_loss:{:.4f},accuary:{:.4f}'
                .format(epoch + 1, epochs, train_loss, val_loss,
                        num_correct / num_examples))

parameter

simnet = net()
device = 'cuda' if torch.cuda.is_available() else 'cpu'
simnet.to(device)
optimizer = optim.Adam(simnet.parameters(), lr=0.001)
train(model=simnet, optimizer=optimizer, loss_fn=torch.nn.CrossEntropyLoss(),
      device=device)

Forecast

# test
labels = ['cat', 'fish']
 img = Image.open('train/cat/19.jpg')
 img = img_transforms(img)
 img = img.unsqueeze(0)
 pre = simnet(img.to(device))
 pre = pre.argmax()
 print(labels[pre])

Model Save

# save
torch.save(simnet, "/cat_fish_classification")
 # load
 simnet = torch.load('cat_fish_classification')
 # save model parameter
 torch.save(simnet.state_dict(), 'cat_fish_classification')
 # load
 simnet = net()
 simnet_state_dict = torch.load('cat_fish_classification')
 simnet.load_state_dict(simnet_state_dict)

torch.save() made a mistake. The exact reason is not clear. Leave a hole first.

All Code

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data
import torch.nn.functional as F
import torchvision
from torchvision import transforms
from PIL import Image


def check_image(path):
    try:
        im = Image.open(path)
        return True
    except:
        return False


img_transforms = transforms.Compose([
    transforms.Resize((64, 64)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406],
                         std=[0.229, 0.224, 0.225])
])

train_data_path = "./train/"
train_data = torchvision.datasets.ImageFolder(root=train_data_path, transform=img_transforms, is_valid_file=check_image)
val_data_path = "./val/"
val_data = torchvision.datasets.ImageFolder(root=val_data_path, transform=img_transforms, is_valid_file=check_image)
test_data_path = "./test"
test_data = torchvision.datasets.ImageFolder(root=test_data_path, transform=img_transforms, is_valid_file=check_image)

batch_size = 64

train_data_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size)
val_data_loader = torch.utils.data.DataLoader(val_data, batch_size=batch_size)
test_data_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size)


# Define Neural Network
class net(nn.Module):
    def __init__(self):
        super(net, self).__init__()
        self.fc1 = nn.Linear(12288, 84)  # 64*64*3
        self.fc2 = nn.Linear(84, 20)
        self.fc3 = nn.Linear(20, 2)

    def forward(self, x):
        x = x.view(-1, 12288)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


# model = net()

def train(model, loss_fn, device, optimizer, epochs=20):
    train_loss = 0.0
    val_loss = 0.0
    model.train()  # Training mode
    for epoch in range(epochs):
        for batch in train_data_loader:
            optimizer.zero_grad()  # Empty last calculated gradient
            inputs, traget = batch
            inputs, traget = inputs.to(device), traget.to(device)  # Put the tensor on the gpu, if possible
            output = model.forward(inputs)
            loss = loss_fn(output, traget)  # Calculating loss
            loss.backward()  # Reverse Propagation
            optimizer.step()  # Update Weights
            train_loss += loss.data.item()
        train_loss /= len(train_data)

        model.eval()  # Test mode
        num_correct = 0
        num_examples = 0
        for batch in val_data_loader:
            inputs, traget = batch
            inputs, traget = inputs.to(device), traget.to(device)
            output = model.forward(inputs)
            loss = loss_fn(output, traget)
            val_loss += loss.data.item()
            correct = torch.eq(torch.max(F.softmax(output, dim=1), dim=1)[1], traget).view(-1)
            num_correct += sum(correct).item()
            num_examples += correct.shape[0]
        val_loss /= len(val_data)
        print(
            'epoch[{}|{}],train_loss:{:.4f},val_loss:{:.4f},accuary:{:.4f}'
                .format(epoch + 1, epochs, train_loss, val_loss,
                        num_correct / num_examples))




if __name__ == '__main__':
    simnet = net()
    device = 'cuda' if torch.cuda.is_available() else 'cpu'
    simnet.to(device)
    optimizer = optim.Adam(simnet.parameters(), lr=0.001)
    train(model=simnet, optimizer=optimizer, loss_fn=torch.nn.CrossEntropyLoss(),
          device=device)
    # test
    labels = ['cat', 'fish']
    img = Image.open('train/cat/19.jpg')
    img = img_transforms(img)
    img = img.unsqueeze(0)
    pre = simnet(img.to(device))
    pre = pre.argmax()
    print(labels[pre])

    # save
    torch.save(simnet, "/cat_fish_classification")
    # load
    simnet = torch.load('cat_fish_classification')
    # save model parameter
    torch.save(simnet.state_dict(), 'cat_fish_classification')
    # load
    simnet = net()
    simnet_state_dict = torch.load('cat_fish_classification')
    simnet.load_state_dict(simnet_state_dict)

Tags: Pytorch Deep Learning

Posted on Fri, 05 Nov 2021 16:58:19 -0400 by Axariel