AI: a cat or a dog, that is the question

If you do not like kittens and puppies, you may not know specifically what kind they breed, but in general, you can distinguish that this is a cat or a dog, cats and dogs is not the same characteristics, then we how machine learning methods to train a network to distinguish between cats and dogs do?

We use the Kaggle of a data set ( https://www.kaggle.com/c/dogs-vs-cats/data ), training model with neural network. Data sets downloaded data for us to test it a little big, there were 12,500 dogs and cats have trained the picture, let's look to narrow the training set, and then to set up and training model. Our approach is to approach training cats and dogs were selected 1000 pictures, 500 500 validation set and test set, we can do this manually, you need to do is:

// 如下非可执行代码,含义非常清楚的表达,最后会附上可执行代码
mkdir dog-vs-cats-small
cp dog-vs-cats/train/cat/pic-{0-999}.jpg dog-vs-cats-small/train/cat/
cp dog-vs-cats/train/dog/pic-{0-999}.jpg dog-vs-cats-small/train/dog/
cp dog-vs-cats/validation/cat/pic-{1000-1499}.jpg dog-vs-cats-small/validation/cat/
cp dog-vs-cats/validation/dog/pic-{1000-1499}.jpg dog-vs-cats-small/validation/dog/
cp dog-vs-cats/test/cat/pic-{1500-1999}.jpg dog-vs-cats-small/test/cat/
cp dog-vs-cats/test/dog/pic-{1500-1999}.jpg dog-vs-cats-small/test/dog/

From the experience of our previous articles, we can know that this convolution neural network we can use relu activated Conv2D layer and the layer stacking MaxPooling2D, need to be modified slightly compared with the previous is the size of the network, the greater the network processing more mostly data.

Network depth convolutional neural network are often associated with the size of the negative features of the FIG., The size of each feature deeper FIG network are often smaller, often the data I see: Depth 32-> 128, feature dimensions 150x150 FIG. -> 7x7. Below, this is our network architecture:

image

The optimizer still uses RMSprop, learning rate of 0.001 default is set to 0.0001, we will also follow different optimization is introduced. As a result of required output is "a cat or a dog," so we finally one activation parameters for the sigmoid, it is a natural loss of function binary_crossentropy, and this way, the network is constructed Well, then you should feed the data network.

Since we are here is a picture of another one, jpg format, this is not our favorite network format, need to be processed, reading out the picture, it is decoded into RGB pixels, and then convert the pixel values ​​in RGB into a floating points are calculated, and because the number of our network effect between 0-1 better to deal with, so we need to convert the pixel value range, that is, switching from 0-1 to 0-255, is not that a bit of trouble, indeed! Keras reason that is most easy to use deep learning framework, because it is equally cumbersome but using these tools built in, ImageDataGenerator under the Image package can be a big help, so that we can get the RGB image and binary label consisting of batch.

Next, we have the data fitted, fit_generator, above the generator will also be passed to it, so that we have established a complete network can be trained, as previously described, we still draw loss curve and precision profile.

Accuracy curve

Training gradually close to 100 percent accuracy, remind us of the danger of over-fitting; training accuracy remained at around 70% is no longer up in the fifth (or six) times after.

Loss curve

After the fifth or tenth, verify losses reached a minimum, ah ......, it is clear that over-fitting, and we need to reduce the over-fitting.

The reason for over-fitting of learning samples is too little, we used data enhancement to solve this problem. Our approach is to generate data in existing training more training data, is to increase the number of random transformation, this random variation generated images still have to ensure that it is effective. This model in the training, you can see more images of the different, which makes the trained model generalization ability better. How to do it, you can put pictures random rotation, zoom, pan and flips, ImageDataGenerator provides this capability. At the same time added before a dense layer Dropout layer, would be better to reduce over-fitting, this way, look at the results:

image

image

Can be seen, the effect is a lot better. Training accuracy can reach at least 80%, think greatly improve the accuracy, you need some other method, and the next article we talk later.

The old rules, accompanied by all the code:

#!/usr/bin/env python3

import os
import shutil
import time

import matplotlib.pyplot as plt
from keras import layers
from keras import models
from keras import optimizers
from keras.preprocessing.image import ImageDataGenerator


def make_small():
    original_dataset_dir = '/Users/renyuzhuo/Desktop/cat/dogs-vs-cats/train'
    base_dir = '/Users/renyuzhuo/Desktop/cat/dogs-vs-cats-small'
    os.mkdir(base_dir)

    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)
    train_cats_dir = os.path.join(train_dir, 'cats')
    os.mkdir(train_cats_dir)
    train_dogs_dir = os.path.join(train_dir, 'dogs')
    os.mkdir(train_dogs_dir)
    validation_cats_dir = os.path.join(validation_dir, 'cats')
    os.mkdir(validation_cats_dir)
    validation_dogs_dir = os.path.join(validation_dir, 'dogs')
    os.mkdir(validation_dogs_dir)
    test_cats_dir = os.path.join(test_dir, 'cats')
    os.mkdir(test_cats_dir)
    test_dogs_dir = os.path.join(test_dir, 'dogs')
    os.mkdir(test_dogs_dir)
    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)
    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)
    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)

    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)
    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)
    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)


def cat():
    base_dir = '/Users/renyuzhuo/Desktop/cat/dogs-vs-cats-small'
    train_dir = os.path.join(base_dir, 'train')
    validation_dir = os.path.join(base_dir, 'validation')

    model = models.Sequential()
    model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(64, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(128, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(128, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Flatten())
    model.add(layers.Dropout(0.5))
    model.add(layers.Dense(512, activation='relu'))
    model.add(layers.Dense(1, activation='sigmoid'))

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

    # train_datagen = ImageDataGenerator(rescale=1. / 255)
    train_datagen = ImageDataGenerator(
        rescale=1. / 255,
        rotation_range=40,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True, )

    test_datagen = ImageDataGenerator(rescale=1. / 255)

    train_generator = train_datagen.flow_from_directory(
        train_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')
    validation_generator = test_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=32,
        class_mode='binary')
    history = model.fit_generator(
        train_generator,
        steps_per_epoch=100,
        epochs=100,
        validation_data=validation_generator,
        validation_steps=50)
    model.save('cats_and_dogs_small_2.h5')

    acc = history.history['acc']
    val_acc = history.history['val_acc']
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    epochs = range(len(acc))
    plt.plot(epochs, acc, 'bo', label='Training acc')
    plt.plot(epochs, val_acc, 'b', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend()
    plt.show()
    plt.figure()
    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()
    plt.show()


if __name__ == "__main__":
    time_start = time.time()
    # make_small()
    cat()
    time_end = time.time()
    print('Time Used: ', time_end - time_start)

Guess you like

Origin www.cnblogs.com/renyuzhuo/p/12387898.html
Dog