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
- 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.
- 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.
- 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%.
- 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
- 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.
- Set the hyperparameters, set the optimizer, and view the structural details of the neural network model just built;
- Model training, print Loss (loss function) and acc (accuracy) information, save the trained model;
- Use a line chart to visualize the change trend of Loss with epoch and the change trend of accurary with epoch;
- Sample data prediction, visually display the prediction result of 10 sample data 0;
- 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).