Как да създадете прост класификатор на изображения

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

Няма ограничение за приложенията за класификация на изображенията. Можете да го използвате в следващото си приложение или да го използвате за решаване на някакъв проблем от реалния свят. Всичко зависи от вас. Но за някой, който е сравнително нов в тази сфера, в началото може да изглежда много предизвикателно. Как да получа данните си? Как да изградя своя модел? Какви инструменти трябва да използвам?

В тази статия ще обсъдим всичко това - от намирането на набор от данни до обучението на вашия модел. Ще се опитам да направя нещата възможно най-опростени, като избягвам някои технически подробности ( PS: Моля, обърнете внимание, че това не означава, че тези подробности не са важни. Ще спомена някои страхотни ресурси, към които можете да се обърнете, за да научите повече за тези теми ). Целта на тази статия е да обясни основния процес на изграждане на класификатор на изображения и на това ще се спрем повече тук.

Ще изградим класификатор на изображения за набора от данни Fashion-MNIST. Наборът данни Fashion-MNIST е колекция от изображения на статии на Zalando. Той съдържа 60 000 изображения за учебния комплект и 10 000 изображения за данните от тестовия набор (по-късно ще обсъдим наборите от данни за тестове и обучения заедно с валидиращия набор от данни ). Тези изображения принадлежат на етикетите на 10 различни класа.

Импортиране на библиотеки

Нашата цел е да обучим модел за задълбочено обучение, който може да класифицира даден набор от изображения в един от тези 10 класа. След като разполагаме с набора от данни, трябва да преминем към инструментите, от които се нуждаем. Има много библиотеки и инструменти, които можете да изберете въз основа на вашите собствени изисквания на проекта. За това ще се придържам към следното:

  1. Numpy - Python библиотека за числено изчисление
  2. Pandas - Манипулиране на данни от библиотека на Python
  3. Matplotlib - Визуализация на данни от библиотека на Python
  4. Keras - Python библиотека, базирана на tensorflow за създаване на модели за дълбоко обучение
  5. Jupyter - Ще стартирам целия си код на Jupyter Notebooks. Можете да го инсталирате чрез връзката. Можете да използвате Google Colabs и ако имате нужда от по-добра изчислителна мощ.

Заедно с тези четири, ще използваме и scikit-learn. Целта на тези библиотеки ще стане по-ясна, след като се потопим в кода.

Добре! Имаме готови инструменти и библиотеки. Сега трябва да започнем да настройваме нашия код.

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

import numpy as np import pandas as pd import matplotlib.pyplot as plt import keras from sklearn.model_selection import train_test_split from keras.utils import to_categorical from keras.models import Sequential from keras.layers import Conv2D, MaxPooling2D from keras.layers import Dense, Dropout from keras.layers import Flatten, BatchNormalization

train_test_split: Този модул разделя набора от данни за обучение в данни за обучение и валидиране. Причината зад това разделяне е да проверим дали моделът ни е прекалено подходящ или не. Използваме набор от данни за обучение, за да обучим нашия модел и след това ще сравним получената точност с точността на валидиране. Ако разликата между двете количества е значително голяма, тогава нашият модел вероятно е прекалено подходящ. Ще повторим през нашия процес на изграждане на модели и ще направим необходимите промени по пътя. След като се задоволим с нашите точност на обучение и валидиране, ние ще направим окончателни прогнози на нашите тестови данни.

to_categorical: to_categorical е помощна програма keras. Използва се за преобразуване на категориалните етикети в еднократно кодиране. Да предположим, че имаме три етикета ("ябълки", "портокали", "банани"), тогава едно горещо кодиране за всеки от тях ще бъде [1, 0, 0] -> "ябълки", [0, 1, 0] -> "портокали", [0, 0, 1] -> "банани".

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

Предварителна обработка на данни

Засега ще насочим вниманието си към получаването на нашите данни и тяхното анализиране. Винаги трябва да помните значението на предварителната обработка и анализ на данните. Това не само ви дава представа за данните, но също така помага да се открият несъответствия.

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

train_df = pd.read_csv('./fashion-mnist_train.csv') test_df = pd.read_csv('./fashion-mnist_test.csv')

Първо нека импортираме нашия набор от данни ( Ето връзката за изтегляне на този набор от данни във вашата система ). След като импортирате набора от данни, изпълнете следната команда.

train_df.head()

Тази команда ще ви покаже как изглеждат вашите данни. Следващата екранна снимка показва резултата от тази команда.

Можем да видим как данните ни за изображения се съхраняват под формата на пикселни стойности. Но не можем да подаваме данни към нашия модел в този формат. Така че, ще трябва да го преобразуваме в numpy масиви.

train_data = np.array(train_df.iloc[:, 1:]) test_data = np.array(test_df.iloc[:, 1:])

Сега е време да вземем нашите етикети.

train_labels = to_categorical(train_df.iloc[:, 0]) test_labels = to_categorical(test_df.iloc[:, 0])

Тук можете да видите, че сме използвали to_categorical, за да преобразуваме нашите категорични данни в едно горещо кодиране.

Сега ще преформатираме данните и ще ги прехвърлим във тип float32 , за да можем да ги използваме удобно.

rows, cols = 28, 28 train_data = train_data.reshape(train_data.shape[0], rows, cols, 1) test_data = test_data.reshape(test_data.shape[0], rows, cols, 1) train_data = train_data.astype('float32') test_data = test_data.astype('float32')

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

train_data /= 255.0 test_data /= 255.0

Конволюционни невронни мрежи

И така, предварителната обработка на данните е направена. Сега можем да започнем да изграждаме нашия модел. Ще изградим Конволюционна невронна мрежа за моделиране на данните за изображението. CNN са модифицирани версии на обикновени невронни мрежи. Те са модифицирани специално за данни за изображения. Храненето на изображения в обикновени невронни мрежи ще изисква нашата мрежа да има голям брой входни неврони. Например, само за изображение 28x28, ще са ни необходими 784 входни неврона. Това би създало огромна бъркотия в параметрите за обучение.

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

The visualization above shows how convolution operation works. And the Conv2D layer we imported earlier does the same thing. The first matrix (from the left) in the demonstration is the input to the convolutional layer. Then another matrix called "filter" or "kernel" is multiplied (matrix multiplication) to each window of the input matrix. The output of this multiplication is the input to the next layer.

Other than convolutional layers, a typical CNN also has two other types of layers: 1) a  pooling layer, and 2) a fully connected layer.

Pooling layers are used to generalize the output of the convolutional layers. Along with generalizing, it also reduces the number of parameters in the model by down-sampling the output of the convolutional layer.

As we just learned, convolutional layers represent high level features from image data. Fully connected layers use these high level features to train the parameters and to learn to classify those images.

We will also use the Dropout, Batch-normalization and Flatten layers in addition to the layers mentioned above. Flatten layer converts the output of convolutional layers into a one dimensional feature vector. It is important to flatten the outputs because Dense (Fully connected) layers only accept a feature vector as input. Dropout and Batch-normalization layers are for preventing the model from overfitting.

train_x, val_x, train_y, val_y = train_test_split(train_data, train_labels, test_size=0.2) batch_size = 256 epochs = 5 input_shape = (rows, cols, 1)
def baseline_model(): model = Sequential() model.add(BatchNormalization(input_shape=input_shape)) model.add(Conv2D(32, (3, 3), padding="same", activation="relu")) model.add(MaxPooling2D(pool_size=(2, 2), strides=(2,2))) model.add(Dropout(0.25)) model.add(BatchNormalization()) model.add(Conv2D(32, (3, 3), padding="same", activation="relu")) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128, activation="relu")) model.add(Dropout(0.5)) model.add(Dense(10, activation="softmax")) return model

The code that you see above is the code for our CNN model. You can structure these layers in many different ways to get good results. There are many popular CNN architectures which give state of the art results. Here, I have just created my own simple architecture for the purpose of this problem. Feel free to try your own and let me know what results you get :)

Training the model

Once you have created the model you can import it and then compile it by using the code below.

model = baseline_model() model.compile(loss='categorical_crossentropy', optimizer="sgd", metrics=['accuracy']) 

model.compile configures the learning process for our model. We have passed it three arguments. These arguments define the loss function for our model, optimizer and metrics.

history = model.fit(train_x, train_y, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(val_x, val_y)) 

And finally by running the code above you can train your model. I am training this model for just five epochs but you can increase the number of epochs. After your training process is completed you can make predictions on the test set by using the following code.

predictions= model.predict(test_data)

Conclusion

Congrats! You did it, you have taken your first step into the amazing world of computer vision.

You have created a your own image classifier. Even though this is a great achievement, we have just scratched the surface.

There is a lot you can do with CNNs. The applications are limitless. I hope that this article helped you to get an understanding of how the process of training these models works.

Working on other datasets on your own will help you understand this even better. I have also created a GitHub repository for the code I used in this article. So, if this article was useful for you please let me know.

If you have any questions or you want to share your own results or if you just want to say "hi", feel free to hit me up on twitter, and I'll try to do my best to help you. And finally Thanks a lot for reading this article!! :)