Будучи ребенком 90-х, я вставал рано утром в субботу, чтобы посмотреть новые серии Pokemon. Я вырос, играя во все игры про покемонов, и мне нравилось коллекционировать коллекционные карточки. Один общий элемент во всей серии Pokemon - это покедекс.

Покедекс - это устройство, используемое для идентификации любого покемона, которого вы встречаете. Это дает вам информацию о покемоне; от того, что он ест, до того, сколько весит покемон.

Сегодня я попытаюсь создать простой покедекс, используя сверточную нейронную сеть.

Вы можете просмотреть мой код здесь.

Загрузка необходимых пакетов

import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from sklearn.utils import shuffle
from sklearn.cross_validation import train_test_split
from keras import backend as K
K.set_image_dim_ordering('tf')
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers import GlobalAveragePooling2D, Lambda, Conv2D, MaxPooling2D, Dropout, Dense, Flatten, Activation
from keras.layers.normalization import BatchNormalization
from keras.optimizers import SGD, RMSprop, Adam

Для этого CNN мы будем использовать Keras с Tensorflow в качестве бэкэнда.

Если у вас нет Tensorflow, посетите этот пост.

Загрузка в набор данных

img_rows = 128
img_cols = 128
num_channel = 1 # to set gray-scale
img_data_list = []
for dataset in data_dir_list:
    img_list = os.listdir(data_path + '/' + dataset)
    print('Loaded the images of dataset-' + '{}\n'.format(dataset))
    for img in img_list:
        input_img = cv2.imread(data_path + '/' + dataset + '/' + img)
        input_img = cv2.cvtColor(input_img, cv2.COLOR_BGR2GRAY)
        input_img_resize = cv2.resize(input_img, (128, 128))
        img_data_list.append(input_img_resize)
img_data = np.array(img_data_list)
img_data = img_data.astype('float32')
img_data /= 255
print(img_data.shape)

Здесь я определяю размер желаемого изображения и меняю наши входные изображения на полутоновые, которые будут использоваться в нашей CNN.

Мой результат был:

(1167,128,128), который представляет размеры нашего изображения в этой форме: (#of_samples, rows, column)

Количество образцов составило 1167, потому что я буду использовать в общей сложности 1167 изображений покемонов для обучения моего CNN.

Изменение размера изображения

# this 'if' statement is for reshaping gray-scale images
if num_channel == 1:
    if K.image_dim_ordering() == 'th':
        img_data = np.expand_dims(img_data, axis=1)
        print(img_data.shape)
    else:
        img_data = np.expand_dims(img_data, axis=4)
        print(img_data.shape)
# this 'else' statement is for reshaping RGB images
else:
    if K.image_dim_ordering() == 'th':
        img_data = np.rollaxis(img_data, 3, 1)
        print(img_data.shape)

Этот блок кода используется для добавления измерения channel к нашему измерению изображения. Мы хотим, чтобы размер изображения включал количество каналов, которые мы используем.

Теано против TensorFlow

Единственное, о чем вам нужно позаботиться, - это то, как эти два разных серверных модуля влияют на порядок размеров изображения:

Theano: (#of_samples, #of_channels, rows, columns)

Где #of_channels - это 2-й элемент размеров изображения.

TensorFlow: (#of_samples, rows, columns, #of_channels)

Где #of_channels - это 4-й элемент размеров изображения.

В нашем случае наш номер channel будет 1, потому что мы вводим изображения в оттенках серого. Итак, наше измененное измерение будет выглядеть так:

(1167, 128, 128, 1)

Вы можете видеть, что 1 - наш 4-й элемент, потому что мы используем бэкэнд TensorFlow.

Назначение ярлыков

num_classes = 5
num_of_samples = img_data.shape[0]
labels = np.ones((num_of_samples,), dtype='int64')
labels[0:233] = 0    # bulbsaur
labels[233:472] = 1  # charmander
labels[472:711] = 2  # mewtwo
labels[711:946] = 3  # pikachu
labels[946:1170] = 4 # squirtle
names = ['bulbasaur', 'charmander', 'mewtwo', 'pikachu', 'squirtle']
Y = np_utils.to_categorical(labels, num_classes)

Настройка моих целевых меток и одно горячее кодирование моего набора данных.

Train_Test Разделить мой набор данных

x, y = shuffle(img_data, Y, random_state=2)
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=4)
input_shape = img_data[0].shape
# print(input_shape)
# Output: (128, 128, 1) which is our desired image size

Я решил использовать функцию sklearn train_test_split, чтобы разделить набор данных на 80:20 для моего первого прохода.

Создание нашей сверточной нейронной сети

model = Sequential()
model.add(Conv2D(32, (3, 3), padding="same", input_shape=input_shape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=-1))
model.add(MaxPooling2D(pool_size=(3, 3)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=-1))
model.add(Conv2D(64, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=1))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=-1))
model.add(Conv2D(128, (3, 3), padding="same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis=-1))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(1024))
model.add(Activation("relu"))
model.add(BatchNormalization())
model.add(Dropout(0.5))
# softmax classifier
model.add(Dense(5))
# Last 'Dense' input is used to specify the number of classes to predict
model.add(Activation("softmax"))
model.compile(Adam(lr=0.0001), loss='categorical_crossentropy', metrics=["accuracy"])

Если я правильно посчитал, у нас должно быть 13 слоев в нашей CNN. Вы можете использовать model.summary(), чтобы проверить меня.

Я использовал Relu в качестве функции активации повсюду и Softmax в качестве последней.

Я использовал Адама в качестве оптимизатора, но я мог бы попробовать Ада на следующем проходе, чтобы посмотреть, даст ли он лучшие результаты с теми же параметрами.

Обучение модели

hist = model.fit(X_train, y_train, batch_size=32, epochs=20,
                 verbose=1, validation_data=(X_test, y_test))

Теперь я тренирую свой набор данных, и вы должны увидеть что-то вроде этого:

Если ваш TensorFlow настроен на использование графического процессора, этот процесс займет у вас меньше минуты. Опять же, в этом сообщении рассказывается, как его установить.

Результаты точности и потерь

train_loss = hist.history['loss']
val_loss = hist.history['val_loss']
train_acc = hist.history['acc']
val_acc = hist.history['val_acc']
xc = range(20)
plt.figure(1, figsize=(7, 5))
plt.plot(xc, train_loss)
plt.plot(xc, val_loss)
plt.xlabel('num of Epochs')
plt.ylabel('loss')
plt.title('train_loss vs val_loss')
plt.grid(True)
plt.legend(['train', 'val'])
# print plt.style.available # use bmh, classic,ggplot for big pictures
plt.style.use(['classic'])
# saving the figure is optional
plt.savefig('trial_psi_loss.png', bbox_inches='tight')

Как видите, потери при проверке значительно выше, чем потери при обучении, что означает, что моя модель переобучена. В будущем вы можете попытаться отрегулировать его, уменьшив количество слоев или увеличив набор данных, чтобы получить лучшие результаты.

plt.figure(2, figsize=(7, 5))
plt.plot(xc, train_acc)
plt.plot(xc, val_acc)
plt.xlabel('num of Epochs')
plt.ylabel('accuracy')
plt.title('train_acc vs val_acc')
plt.grid(True)
plt.legend(['train', 'val'], loc=4)
# print plt.style.available # use bmh, classic,ggplot for big pictures
plt.style.use(['classic'])
# saving the figure is optional
plt.savefig('trial_psi_acc.png', bbox_inches='tight')

Точность наших тренировок - это всего лишь тест на вменяемость, который для нас отлично работает. Хотя точность нашей проверки не так высока, как хотелось бы.

Заключение

Эта модель определенно неполная, если не сказать больше. Я вернусь к этому, чтобы посмотреть, смогу ли я добиться большей точности.

Если есть предложения по улучшению модели или вопросы, не стесняйтесь оставлять комментарии, и я свяжусь с вами в ближайшее время.

Ссылки и ссылки

  1. Https://www.youtube.com/watch?v=u8BW_fl6WRc
  2. Https://www.youtube.com/watch?v=KdhphuuHyxA
  3. Https://www.youtube.com/watch?v=7n1SpeudvAE&index=9&list=PLZbbT5o_s2xrwRnXk_yCPtnqqo4_u2YGL
  4. Https://www.pyimagesearch.com/2018/04/09/how-to-quickly-build-a-deep-learning-image-dataset/
  5. Https://www.pyimagesearch.com/2018/04/16/keras-and-convolutional-neural-networks-cnns/