Two classifications of cats and dogs and four classifications of weather

Tip: Articles for Learning Records

Article directory

  • foreword
  • 1. Classification of cat and dog images
    • 1.1 Data preprocessing
    • 1.2 Building a neural network
  • Two, four kinds of weather image data classification (pytorch)
  • Summarize

Foreword

The common classification network structure can be divided into two parts, one is the feature extraction part, and the other is the classification part; the feature extraction part is generally composed of various convolutions, and the convolution has powerful feature extraction capabilities; the classification part is generally composed of full connections, The features obtained in the feature extraction part are generally one-dimensional vectors, which can be directly classified into full connections; the VGG16 network consists of three different layers, namely convolutional layers, maximum pooling layers, and fully connected layers.

1. Cat and dog image classification

Source link

1.1 Data preprocessing

  1. Read the data set containing 5000 cat and dog images, the picture name contains the category name (cat and dog each have 2500 pictures), resize the image to 128*128 size.
  2. Label the picture according to the picture name, the label of the dog is marked as 1, and the label of the cat is marked as 0.
  3. Split data set: (train data, train label) is the training data, (test data, test label) is the test data, and the test data accounts for 25%.
  4. Check out the resized sample images of cats and dogs.
import os, shutil
# The path of the directory where the c data set is decompressed
original_dataset_dir = 'Cat & Dog'
# Create a directory to store smaller datasets
base_dir = 'find_cats_and_dogs'
os.mkdir(base_dir)

# train, validate and test splits
train_dir = os.path.join(base_dir, 'train')
os.mkdir(train_dir)
validation_dir = os.path.join(base_dir, 'validation')
os.mkdir(validation_dir)
test_dir = os.path.join(base_dir, 'test')
os.mkdir(test_dir)

# training cat pictures
train_cats_dir = os.path.join(train_dir, 'cats')
os.mkdir(train_cats_dir)

# training dog images
train_dogs_dir = os.path.join(train_dir, 'dogs')
os.mkdir(train_dogs_dir)

# Verify cat image
validation_cats_dir = os.path.join(validation_dir, 'cats')
os.mkdir(validation_cats_dir)

# verify dog image
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
os.mkdir(validation_dogs_dir)

# Test pictures of cats
test_cats_dir = os.path.join(test_dir, 'cats')
os.mkdir(test_cats_dir)

# Test pictures of cats
test_dogs_dir = os.path.join(test_dir, 'dogs')
os.mkdir(test_dogs_dir)

# Copy the first 1000 cat images to train the model
fnames = ['cat.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(train_cats_dir, fname)
    shutil. copyfile(src, dst)

# Copy 500 cat images to validation
fnames = ['cat.{}.jpg'.format(i) for i in range(1000, 1500)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(validation_cats_dir, fname)
    shutil. copyfile(src, dst)
    
# Copy 500 cat images to test
fnames = ['cat.{}.jpg'.format(i) for i in range(1500, 2000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(test_cats_dir, fname)
    shutil. copyfile(src, dst)
    
# Copy 1000 dog pictures to train the model
fnames = ['dog.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(train_dogs_dir, fname)
    shutil. copyfile(src, dst)
    
# Copy 500 dog pictures to verify
fnames = ['dog.{}.jpg'.format(i) for i in range(1000, 1500)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(validation_dogs_dir, fname)
    shutil. copyfile(src, dst)
    
# Copy 500 dog pictures to test
fnames = ['dog.{}.jpg'.format(i) for i in range(1500, 2000)]
for fname in fnames:
    src = os.path.join(original_dataset_dir, fname)
    dst = os.path.join(test_dogs_dir, fname)
    shutil. copyfile(src, dst)

# Print the dimensions of the new dataset
print('total training cat images:', len(os.listdir(train_cats_dir)))
print('total training dog images:', len(os. listdir(train_dogs_dir)))
print('total validation cat images:', len(os.listdir(validation_cats_dir)))
print('total validation dog images:', len(os.listdir(validation_dogs_dir)))
print('total test cat images:', len(os.listdir(test_cats_dir)))
print('total test dog images:', len(os.listdir(test_dogs_dir)))

1.2 Building a neural network

  1. Use Keras to build a VGG16 convolutional neural network; the VGG16 network consists of three different layers, namely the convolutional layer, the largest pooling layer, and the fully connected layer.
  2. Set the hyperparameters, set the optimizer, and view the structural details of the neural network model just built;
  3. Model training, print Loss (loss function) and acc (accuracy) information, save the trained model;
  4. Use a line chart to visualize the change trend of Loss with epoch and the change trend of accurary with epoch;
  5. Sample data prediction, visually display the prediction result of 10 sample data 0;
  6. Evaluate the accuracy of the model, and calculate the accuracy of the model through the prediction results of the test set;
# Build a small convolutional network

import tensorflow as tf
from keras import layers
from keras import models

model = models. Sequential()
model.add(tf.keras.layers.Conv2D(32,(3,3),activation="relu",
                               input_shape=(150,150,3)))
model.add(tf.keras.layers.MaxPooling2D((2,2)))

model.add(tf.keras.layers.Conv2D(64,(3,3),activation="relu"))
model.add(tf.keras.layers.MaxPooling2D((2,2)))

model.add(tf.keras.layers.Conv2D(128,(3,3),activation="relu"))
model.add(tf.keras.layers.MaxPooling2D((2,2)))

model.add(tf.keras.layers.Conv2D(128,(3,3),activation="relu"))
model.add(tf.keras.layers.MaxPooling2D((2,2))) #

model.add(tf.keras.layers.Flatten())?
model.add(tf.keras.layers.Dense(512, activation="relu"))
model.add(tf.keras.layers.Dense(1, activation="sigmoid"))

model.summary()

# Use the RMSprop optimizer

from tensorflow.keras import optimizers

model.compile(loss="binary_crossentropy",
             optimizer=optimizers.RMSprop(learning_rate=1e-4),
             metrics=["acc"])

# data preprocessing

from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(rescale=1./255) # scale
test_datagen = ImageDataGenerator(rescale=1./255) # scale

train_generator = train_datagen.flow_from_directory(
    train_dir, # directory to be processed
    target_size=(150,150), # image size setting
    batch_size=20,
    class_mode="binary" # The loss function is binary_crossentropy so use binary labels
)

validation_generator = test_datagen.flow_from_directory(
    validation_dir, # directory to be processed
    target_size=(150,150), # image size setting
    batch_size=20,
    class_mode="binary" # The loss function is binary_crossentropy so use binary labels
)

# View generator output
for data_batch, labels_batch in train_generator:
    print(data_batch. shape)
    print(labels_batch. shape)
    break

# Fit our model to the data using a generator
history = model.fit(
    train_generator, # The first parameter must be a Python generator
    steps_per_epoch=100, # 2000 / 20
    epochs=30, # number of iterations
    validation_data=validation_generator, # data set to be validated
    validation_steps=50
)

# save the model
model.save("cats_and_dogs_small.h5")
# Plot the loss and accuracy of the model on the training and validation data
import matplotlib.pyplot as plt
%matplotlib inline
history_dict = history.history # dictionary form
for key, _ in history_dict.items():
    print(key)

acc = history_dict["acc"]
val_acc = history_dict["val_acc"]

loss = history_dict["loss"]
val_loss = history_dict["val_loss"]
epochs = range(1, len(acc) + 1)

# acc
plt.plot(epochs, acc, "bo", label="Training acc")
plt.plot(epochs, val_acc, "b", label="Validation acc")
plt. title("Training and Validation acc")
plt. legend()

plt. figure()

# loss
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt. title("Training and Validation loss")
plt. legend()

These graphs have the characteristics of overfitting. With the increase of time, the training accuracy is increasing, close to 100%, while the verification accuracy stays at 70-72%. The reason is that the training samples (2000) are relatively small;
Mitigate overfitting methods: dropout and weight decay (L2 regularization); here is a data enhancement method that is almost commonly used when deep learning models process images.

2. Four types of weather image data classification (pytorch)

The folder contains 1,150 images with images of roads in 4 weathers,
They are City_road (road in sunny day), fog (road in foggy day), rain (road in rainy day), snow (road in snowy day),
Construct a multi-classification model (4 classifications) to identify road pictures under different weather conditions.
When constructing the model, please strictly follow the following rules for numerical label mapping {‘City_road’: 0, ‘fog’: 1, ‘rain’: 2, ‘snow’: 3}

Source link

#Related package import
import torch
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch.nn as nn
import torch.nn.functional as F
import torchvision
from torchvision import datasets, transforms
import os
import shut-off
%matplotlib inline import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings. filter warnings('ignore')
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
# data partition
# First, what we need to do is to create a new folder. There are two folders under this folder, namely train and test. The code is as follows:

base_dir = r"./weatherRoad"
if not os.path.isdir(base_dir):
    os.mkdir(base_dir)
    train_dir = os.path.join(base_dir, 'train')
    test_dir = os.path.join(base_dir, 'test')
    os.mkdir(train_dir)
    os.mkdir(test_dir)

# Then, create folders named after the four weather types in the train and test folders, the code is as follows:

species = ['City_road', 'fog', 'rain', 'snow']
for train_or_test in ['train', 'test']:
    for spec in species:
        os.mkdir(os.path.join(base_dir, train_or_test, spec))
image_dir = r'./train'
for i, img in enumerate(os. listdir(image_dir)):
    for spec in species:
        if spec in img:
            s = os.path.join(image_dir, img)
            if i % 5 == 0:
                d = os.path.join(base_dir, 'test', spec, img)
            else:
                d = os.path.join(base_dir, 'train', spec, img)
            shutil. copy(s, d)
# After the operation, we can check how much data is in each folder

for train_or_test in ['train', 'test']:
    for spec in species:
        print(train_or_test, spec, len(os. listdir(os. path. join(base_dir, train_or_test, spec))))

# load data and data preprocessing

transformation = transforms. Compose([
    transforms.Resize((96, 96)), # change image size
    transforms.ToTensor(),
    transforms.Normalize(mean = [0.5, 0.5, 0.5], std = [0.5, 0.5, 0.5]) # normalize
])

train_ds = datasets. ImageFolder(
    train_dir,
    transform = transformation
)

test_ds = datasets. ImageFolder(
    test_dir,
    transform = transformation
)

train_dl = torch.utils.data.DataLoader(train_ds, batch_size = 16, shuffle = True)
test_dl = torch.utils.data.DataLoader(test_ds, batch_size = 16)
train_ds.classes

train_ds.class_to_idx

len(train_ds),len(test_ds)

# Model definition code is as follows:

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 16, 3)
        self.bn1 = nn.BatchNorm2d(16)
        self.pool = nn.MaxPool2d((2, 2))
        self.conv2 = nn.Conv2d(16, 32, 3)
        self.bn2 = nn.BatchNorm2d(32)
        self.conv3 = nn.Conv2d(32, 64, 3)
        self.bn3 = nn.BatchNorm2d(64)
        self.drop = nn.Dropout(0.5)
        self.linear_1 = nn.Linear(64 * 10 * 10, 1024)
        self.bn_l1 = nn.BatchNorm1d(1024)
        self.linear_2 = nn.Linear(1024, 256)
        self.bn_l2 = nn.BatchNorm1d(256)
        self.linear_3 = nn.Linear(256, 4)
    def forward(self, input):
        x = F.relu(self.conv1(input))
        x = self. pool(x)
        x = self.bn1(x)
        x = F.relu(self.conv2(x))
        x = self. pool(x)
        x = self.bn2(x)
        x = F.relu(self.conv3(x))
        x = self. pool(x)
        x = self.bn3(x)
        # print(x. size())
        x = x. view(-1, 64 * 10 * 10)
        x = F.relu(self.linear_1(x))
        x = self.bn_l1(x)
        x = self. drop(x)
        x = F.relu(self.linear_2(x))
        x = self.bn_l2(x)
        x = self. drop(x)
        x = self. linear_3(x)
        return x
# What needs to be noted here is the position of each layer. The BN layer is placed behind the pooling layer to activate the layer and the Dropout layer.
# model training

loss_func = torch.nn.CrossEntropyLoss()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

def fit(epoch, model, trainloader, testloader):
    correct = 0
    total = 0
    running_loss = 0
    
    model.train() # training phase
    for x, y in trainloader:
        x, y = x.to(device), y.to(device)
        y_pred = model(x)
        loss = loss_func(y_pred, y)
        optimizer. zero_grad()
        loss. backward()
        optimizer. step()
        with torch.no_grad():
            y_pred = torch.argmax(y_pred, dim = 1)
            correct += (y_pred == y).sum().item()
            total + = y. size(0)
            running_loss += loss.item()

    epoch_acc = correct / total
    epoch_loss = running_loss / len(trainloader.dataset)
    
    test_correct = 0
    test_total = 0
    test_running_loss = 0
    
    model.eval() # Evaluation phase, generally used when there are dropout layers and BN layers
    with torch.no_grad():
        for x, y in testloader:
            x, y = x.to(device), y.to(device)
            y_pred = model(x)
            loss = loss_func(y_pred, y)
            y_pred = torch.argmax(y_pred, dim = 1)
            test_correct += (y_pred == y).sum().item()
            test_total += y. size(0)
            test_running_loss += loss.item()
    epoch_test_acc = test_correct / test_total
    epoch_test_loss = test_running_loss / len(testloader.dataset)
    
    print('epoch: ', epoch,
          'loss: ', round(epoch_loss, 3),
          'accuracy: ', round(epoch_acc, 3),
          'test_loss: ', round(epoch_test_loss, 3),
          'test_accuracy: ', round(epoch_test_acc, 3))
    
    return epoch_loss, epoch_acc, epoch_test_loss, epoch_test_acc

# It should be noted here that it is necessary to distinguish between the training phase and the evaluation phase, which are generally used when there are Dropout layers and BN layers
model = Model()
model.to(device)
optimizer = torch.optim.Adam(model.parameters(), lr = 0.001)
epochs = 30

train_loss = []
train_acc = []
test_loss = []
test_acc = []
for epoch in range(epochs):
    epoch_loss, epoch_acc, epoch_test_loss, epoch_test_acc = fit(epoch, model, train_dl, test_dl)
    train_loss.append(epoch_loss)
    train_acc.append(epoch_acc)
    test_loss.append(epoch_test_loss)
    test_acc.append(epoch_test_acc)

# save the model
torch.save(model.cpu().state_dict(), './modeldict.pth') # Only keep parameters
torch.save(model, './model.pth') # keep the whole model
plt.plot(range(1,epochs + 1),train_loss,label='train_loss')
plt.plot(range(1,epochs + 1),test_loss,label='test_loss')
plt.plot(range(1,epochs + 1),train_acc,label='train_acc')
plt.plot(range(1,epochs + 1),test_acc,label='test_acc')
plt. show()

# This order is very important, it should be consistent with the order of class names during training
class_names = ['City_road', 'fog', 'rain', 'snow']

# Load the model and read the weights
model.load_state_dict(torch.load('./modeldict.pth'))
model.to(device)
model.eval() # test mode

# Image address list
img_paths = ['weatherRoad/test/City_road/City_road_3.jpg', 'weatherRoad/test/fog/fog_56.jpg', 'weatherRoad/test/rain/rain_22.jpg',
             'weatherRoad/test/snow/snow_13.jpg', 'weatherRoad/test/City_road/City_road_67.jpg']
 
from PIL import Image
# For each address in the image address list
for path in img_paths:
    img = plt.imread(path) # The first method to display pictures
    plt. axis('off')
    plt.imshow(img)
    plt. show()

    img = Image.open(path) # enter the address to open the image
    # img.show() # The second method of displaying pictures

    # Dimension expansion:
    # torch.nn only supports data input in small batches, and does not support inputting a single sample. For example, nn.Conv2d receives 4D
    # tensor as input: nSamples * nChannels * Height * Width,
    # If there is only one sample, then use input.unsqueeze(0) to increase a batch dimension.
    img_ = transformation(img).unsqueeze(0)
    img_ = img_.to(device) # Whether to use GPU
    outputs = model(img_) # get 11 class probabilities

    _, index = torch.max(outputs, 1) # Output the category index with the highest probability, the front is the probability value, and the back is the index
    result = class_names[indice] # get category name
    print('predicted:', result) # output category name

Summary

The above is the implementation of cat and dog binary classification and four kinds of weather image data multi-classification (pytorch).