И така, конволюционните невронни мрежи станаха толкова известни в наши дни! И всеки път, когато чуете думата CNN, обзалагам се, че в главата ви изскачат различни набори от изображения. хайде! Понякога неща като MNIST, CIFAR-10 твърде изскачат, нали?

Е, този урок ще ви научи да създавате свой собствен набор от данни и да обучавате вашия CNN модел върху него. Да, знам, че мрежата е пълна с модели, обучени от MNIST, и много малко от тях ви учат да обучавате индивидуален. Добре тогава, да започваме!

Ще обучим класификатор да прави разлика между роза, слънчоглед и лалета. Можете да се обърнете към моя GitHub за изтегляне на код или файлове, свързани с код. Отново се уверете, че всички папки, които създавате, набори от данни, които създавате, са в една и съща папка. Ето GitHub: https://github.com/kaiwalya4850/Custom_CNN.

Ето връзката за изтегляне на персонализиран набор от данни: https://drive.google.com/open?id=1czBqp0Fk2F7fDoakizZPrSFRcUQ7WHow

Добре, това беше достатъчно, нали? Нека се захванем със сериозно кодиране!

Импортирайте нашите любими библиотеки! pip install, ако вашата машина няма нито едно от тези.

import numpy as np
np.random.seed(1337)  # for reproducibility
from keras.datasets import mnist
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Input, Conv2D, MaxPool2D
from keras.utils import np_utils
from keras.models import Model
import matplotlib.pyplot as plt
import matplotlib
import os
from keras.models import Sequential
import theano
from PIL import Image
from numpy import *
from sklearn.utils import shuffle
from sklearn.cross_validation import train_test_split

Сега дефинираме batch_size (показва колко изображения трябва да изпратите за обучение в даден момент). nb_epoch са броят пъти, които искате да изпълните кода. 200x200 е формата, до която изображенията ще бъдат преоразмерени.

batch_size = 5
nb_classes = 3
nb_epoch = 32

# input image dimensions
img_rows, img_cols = 200, 200
# number of convolutional filters to use
nb_filters = 32
# size of pooling area for max pooling
pool_size = (2, 2)  ## 4 ELEMENTS, TOOK MAX OF IT
# convolution kernel size
kernel_size = (3, 3)

Сега добавяме пътищата на нашите папки.

path1 = 'C:/Users/Kaiwalya/Desktop/ML/Datasets/flowers/Mixed/'    #path of folder of images    
path2 ='C:/Users/Kaiwalya/Desktop/ML/Datasets/flowers/Mix_greyscale/'  #path of folder to save images

Скриптът по-долу търси по даден път.

listing = os.listdir(path1)

Нека отпечатаме броя на изображенията, които имаме в нашия набор от данни за обучение. Потребителите на Python2 премахват скобите при печат.

num_samples=size(listing)
print (num_samples)

Сега нека запазим изображенията в сив цвят. Можете да конвертирате изображенията в червен/зелен/син цвят според вашите нужди. Просто направете наклонени черти назад към наклонени черти напред, ако получите някакви грешки, защото трябваше да го направя, докато работех в облак.

for file in listing:
    im = Image.open(path1 + '\\' + file)   
    img = im.resize((img_rows,img_cols))
    gray = img.convert('L')
                #need to do some more processing here           
    gray.save(path2 +'\\' +  file, "JPEG")

Отново. използвайки os.listdir за проверка на файловете в папката. Този път се проверява папката, която съдържа изображения в сивата скала.

imlist = os.listdir(path2)

Да вземем размера на изображенията.

img_data_list=[]
im1 = array(Image.open('Mix_greyscale' + '\\'+ imlist[0])) # open one image to get size
m,n = im1.shape[0:2] # get the size of the images
imnbr = len(imlist) # get the number of images

Както знаете, изображението е основно матрица. Сега нека преобразуваме тази матрица в правилна форма на масив, за да извършим допълнителна обработка на масива. Просто се обърнете към GitHub, ако получите някакви преднамерени грешки!

immatrix = array([array(Image.open('Mix_greyscale'+'\\'+im2)).flatten()
              for im2 in imlist],'f')

И така, как вашата машина знае, че това е роза, слънчоглед или лале? Защото може да забележи само функциите, а не имената! Така че, нека просто етикетираме изображенията. Назовах ги по ред. Първите 177 бяха рози, следващите 177 слънчогледи и след това 177 лалета.

label=np.ones((num_samples,),dtype = int)
label[0:178]=0   ##Python needs +1 of the total
label[178:354]=1 ## ie, if 177 images, write till 178
label[354:]=2    ## because last image is'nt counted

Нека разбъркаме всички изображения, за да не получим най-дразнещия проблем! Да, преустройване! И да, можете да присвоите произволно число на random_state.

data,Label = shuffle(immatrix,label, random_state=2)
train_data = [data,Label]

Да видим произволно изображение. Ще получите нещо като „(531, 40000)“, където 40000 е 200x200, не забравяйте, че преоразмерихме изображенията.

img=immatrix[167].reshape(img_rows,img_cols)
plt.imshow(img)
plt.imshow(img,cmap='gray')
print (train_data[0].shape)
print (train_data[1].shape)

И така, сега, когато всичко е дефинирано и настроено, нека напишем нещо за обучение на всички тези! Разделихме данните, за всичко това използвахме вградената библиотека от sk-learn.

(X, y) = (train_data[0],train_data[1])
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=4)

Сега променяме формата на масива за по-добро обучение. Това е част от кода, която има вариации. Ще видите нещо различно в документацията на keras или scikit.

X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1)
X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1)
input_shape = (1, img_rows, img_cols)

И така, нека отпечатаме и да видим какво точно сме променили.

X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')

Прилагане на едно горещо кодиране.

Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)

Данни за валидиране на сграда.

split = 0.7
split_value = int(0.7 * len(X_train))

X_val = X_train[split_value:]
Y_val = Y_train[split_value:]

X_train = X_train[:split_value]
Y_train = Y_train[:split_value]

Визуализиране на изображения и проверка дали всичко е перфектно.

fig, ax = plt.subplots(nrows=3, ncols=3, figsize=(16, 9))
for i, axes in enumerate(ax.flat):
    axes.imshow(X_train[i, :, :, 0], cmap='gray')

Изграждане на слоеве. Това е една от важните части във всеки модел на CNN. И можете да промените/добавите/премахнете произволен брой слоеве, които искате. Добавих няколко слоя в слоевете, които бяха използвани за обучение на набор от данни на MNIST. Преди да финализирате тези слоеве. Сменял съм ги много и много пъти.

inp = Input(shape=[200, 200, 1]) ## GREY SCALE 200X200 IMAGE

## BUILD LAYERS, KERNEL SIZE IS FILTER SIDE
layer1 = Conv2D(filters=nb_filters, 
                kernel_size=kernel_size, 
                strides=(1, 1), ## STEPS WE WANT TO SHIFT
                padding='same', ## IF WE DONT, WE MAY HAVE SMALLER SIZE OF IMAGE IN OUTPUT 
## LIKE MAYBE WE'LL LOSE A DIMENSION, WE WANT SAME DIMENSION SO USE IT!
                activation='relu')(inp) 
layer1_maxpool = MaxPool2D(pool_size=(2, 2), padding='same')(layer1) ## ATTACH ARCHITECTURE OF LAYER1, BY layer1
layer2 = Conv2D(filters=nb_filters,    
                kernel_size=kernel_size, 
                strides=(1, 1), 
                padding='same', 
                activation='relu')(layer1_maxpool)
layer2_maxpool = MaxPool2D(pool_size=(2, 2), padding='same')(layer2)
layer2x = Conv2D(filters=nb_filters,  
                kernel_size=kernel_size, 
                strides=(1, 1), 
                padding='same', 
                activation='relu')(layer2_maxpool)## AFTER THIS OUTPUT IS 14X14, AND HAVE 32 KERNELS, 14X14X32
layer2x_maxpool = MaxPool2D(pool_size=(2, 2), padding='same')(layer2x)
layer3x = Conv2D(filters=nb_filters,    
                kernel_size=kernel_size, 
                strides=(1, 1), 
                padding='same', 
                activation='relu')(layer2x_maxpool)
layer3x_maxpool = MaxPool2D(pool_size=(2, 2), padding='same')(layer3x)


layer3 = Flatten()(layer3x_maxpool)         
layer4 = Dense(units=128, activation='relu')(layer3)                
layer5 = Dense(units=nb_classes, activation='softmax')(layer4)

Слой 5 съдържа всички данни на модела. Така че използваме това в действителните стъпки за обучение на модела. Това също имаше оптимизатори, има много и можете да промените този. Просто отидете на документацията.

model = path2
model = Model(inputs=inp, outputs=layer5)                             ## DEFINE ACTUAL MODEL, INP. OUTPUT IS LAYER5
## THIS CONTAINS WHOLE CNN MODEL. NOW GO FOR OPTIMISER AND ALL

model.compile(loss='categorical_crossentropy',## SGD IS LIKE EXTENSION OF BINARY CROSS ENTROPY
              optimizer='sgd',                                      
              metrics=['accuracy'])

Следващият ред ще покаже параметрите, които могат да се обучават. И те се променят всеки път, когато играете със слоеве.

model.summary()

И така, ето го! обучението започва!

history = model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch,verbose=1, validation_data=(X_val, Y_val))

Да видим резултата от нашия тест.

score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])

Нека начертаем графика и да видим как параметрите са се променили в продължителността на обучението.

plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

Нека най-накрая да видим обучението срещу точността на теста и точността на валидиране.

train_loss=history.history['loss']
val_loss=history.history['val_loss']
train_acc=history.history['acc']
val_acc=history.history['val_acc']
xc=range(nb_epoch)
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'])

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

Добре! Това е. Опитайте да добавите матрица на объркване, за да надникнете по-дълбоко във вашия модел. Опитайте се да подобрите тези графики. Моделът ми беше доста объркан на моменти. Този, който съм тренирал също не е на ниво предполагам. Но всичко е свързано с настройване, удряне и проследяване и достигане до вашата дестинация! Чувствайте се свободни да се свържете, ако имате въпроси! Надявам се, че помогна! Благодаря за четенето!