Обзор
Вы когда-нибудь хотели попробовать машинное обучение? Если да, то это руководство для вас. Вы научитесь создавать классификатор изображений и обучать его с помощью облачных графических процессоров. Что такое классификатор изображений? Это модель машинного обучения, которая может классифицировать изображение. Вы покажете ему изображение, и он расскажет, что он думает о себе. Хотя наша модель не будет такой точной, как современные модели, это хорошая отправная точка.
Задача
Наша цель - создать классификатор изображений, а затем использовать его для прогнозов. Этот процесс включает следующие этапы:
- Создание набора данных изображений (мы сделали это за вас)
- Загрузка набора данных изображения для эффективного обучения
- Построение модели классификатора изображений
- Обучение модели с использованием облачных графических процессоров
- Проверка обученной модели
Важно помнить, что описанный выше процесс не является линейным. Как правило, каждый этап необходимо пересматривать несколько раз, чтобы оптимизировать точность модели.
Кроме того, мы также будем делать прогнозы, используя обученную модель, и экспортировать ее для использования в другом месте.
Начиная
Выполните следующие действия, чтобы попробовать этот код:
Open JupyterLab
с предустановленнымTensorFlow 1.11
.- Откройте
Terminal
в открывшейся лаборатории. - Клонируйте репозиторий Github этого проекта с помощью:
$ git clone https://github.com/PeterChauYEG/animal_classifier.git
- Откройте
Animal Classifier.pynb
в каталогеanimal_classifier
. Это откроет блокнот Jupyter. - Запустите всю записную книжку, используя меню
Run
и выбравRun All Cells
- Прокрутите вниз, чтобы увидеть обучение в действии. Первая часть обучения происходит в
cell 20
.
Загрузка зависимостей
Нам нужно импортировать ряд зависимостей Python.
# Allows division to return a float from __future__ import division # Allows access to the file system import os # Provides an API for scientific computing import numpy as np # Allows use to timestamp the training run from datetime import datetime # Allows us to render images and plot data from keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img import math import matplotlib.pyplot as plt # Machine learning framework that provides an abstract API on top of Tensorflow import keras from keras.callbacks import TensorBoard from keras.layers import Conv2D, Dense, Flatten, MaxPooling2D from keras.models import Sequential from keras import optimizers
Конфигурации
Поскольку мы строим графики в Jupyter Lab, нам нужно настроить matplotlib
для рендеринга графиков в реальном времени.
# configure the matplotlib for Jupyter Lab used for rendering the images %matplotlib inline
Каталоги наборов данных
dataset
содержит все изображения. Отдельный каталог должен быть создан для каждого из следующего:
- Набор обучающих данных: изображения, которые используются во время обучения модели.
- Набор данных проверки: изображения, которые используются во время проверки модели.
Каждый набор данных изображений должен быть организован как каталоги изображений. Они должны быть названы по классу (например, кошка) изображений, которые они хранят. Важно, чтобы ни одно из изображений в наборе обучающих данных не было в наборе данных проверки.
# Paths to datasets to be used train_dir = 'dataset/train' validate_dir = 'dataset/validate'
Гиперпараметры
Гиперпараметры используются для настройки модели и обучения модели. Они сильно влияют на итоговые показатели. Давайте изучим их:
- Размер изображения будет уменьшен до 200x200x3. Это означает, что каждое изображение будет размером 200 пикселей на 200 пикселей с 3 цветовыми каналами (красный, зеленый, синий). Чем больше пикселей, тем лучше модель, так как это может увеличить детализацию изображения.
- Скорость обучения - это скорость, с которой модель будет обновлять градиенты, которые она пытается оптимизировать.
- Размер пакета - это количество изображений, которые будут загружены в модель за одну итерацию.
- Эпоха - это количество раз, которое модель должна перебирать по всему набору данных и обновлять веса модели. В какое-то количество эпох выигрыш от обучения приближается к нулю. Можно перетренировать модель.
- Часто рекомендуется разделить набор данных в соотношении 80:20. Это общее правило, которое работает достаточно хорошо.
# number of images in the training dataset n_train = 8000 # number of images in the validation dataset n_validation = 2000 # the number of pixels for the width and height of the image image_dim = 200 # the size of the image (h,w,c) input_shape = (image_dim, image_dim, 3) # the rate which the model learns learning_rate = 0.001 # size of each mini-batch batch_size = 32 # nunmber of training episodes epochs = 10
Выходы
Выведем 2 элемента:
- Журналы тренировок: их можно передать в Tensorboard для анализа.
- Обученная модель: так что ее можно использовать где угодно
Мы хотим сохранить журналы обучения в каталог с отметкой времени начала обучения и некоторыми данными об используемых гиперпараметрах. Мы также хотим дать обученной модели имя при ее сохранении.
# directory which we will save training outputs to # add a timestamp so that tensorboard show each training session as a different run timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') output_logs_dir = 'logs/' + timestamp + '-' + str(batch_size) + '-' + str(epochs) # directory to save the model model_name = 'trained_model'
Загрузка набора данных изображения для эффективного обучения
Генераторы данных изображений
Наивный подход к загрузке данных - загрузить все изображения и преобразовать их заранее. Это приведет к огромному количеству используемой оперативной памяти до начала обучения. Ваша машина может не справиться с этим, что приведет к сбою ядер. Это также может занять очень много времени в зависимости от набора данных.
Вместо этого мы можем загружать и преобразовывать необходимые изображения именно тогда, когда нам это нужно. Это может быть при загрузке модели во время обучения партии изображений.
Keras предоставляет для этого оптимизированный метод с помощью класса Image Data Generator. Это позволяет нам эффективно загружать изображения из каталога. Эти генераторы также могут преобразовывать набор данных многими другими способами, чтобы пополнить его. Изучите эти дополнительные преобразования, которые помогут сделать вашу модель более общей и повысить точность.
# define data generators train_data_generator = ImageDataGenerator(rescale=1./255, fill_mode='nearest') validation_data_generator = ImageDataGenerator(rescale=1./255, fill_mode='nearest') # tell the data generators to use data from the train and validation directories train_generator = train_data_generator.flow_from_directory(train_dir, target_size=(image_dim, image_dim), batch_size=batch_size, class_mode='categorical') validation_generator = validation_data_generator.flow_from_directory(validate_dir, target_size=(image_dim, image_dim), batch_size=batch_size, class_mode='categorical')
Получить имена классов
Полезно иметь словарь классов изображений. Мы можем использовать этот словарь, чтобы сделать наши прогнозы более удобочитаемыми.
# get a dictionary of class names classes_dictionary = train_generator.class_indices # turn classes dictionary into a list class_keys = list(classes_dictionary.keys()) # get the number of classes n_classes = len(class_keys)
Загрузить пути к изображениям для набора данных проверки
Загрузите пути для всех изображений в наборе данных проверки. Они будут использоваться позже, когда мы будем делать прогнозы.
# Get the name of each directory in the root directory and store them as an array. classes = get_class_labels(validate_dir) # Get the paths of all the images in the first class directory and store them as a 2d array. image_paths = get_class_images(classes, validate_dir)
Построение модели классификатора изображений
Наша модель состоит из множества слоев. Изображения передаются через модель, и выводится набор чисел. Этот набор чисел описывает вероятность того, к какому классу принадлежит изображение. Мы берем наибольшее из этих чисел как наиболее вероятный класс.
Мы будем использовать несколько типов слоев и активаций:
Conv2D
- это двумерный сверточный слой. Он применяет фильтры к введенному изображению. Это помогает модели узнать о пространственных отношениях на изображении.ReLu
- это тип нелинейной функции активации. Это помогает модели понять, какие нейроны активируются.MaxPooling2D
понижает дискретизацию входных данных. Мы используем его, чтобы уменьшить размерность ввода. Это создает более абстрактную форму ввода.Flatten
превратит матрицу в строку. Как лепить булочку из блина. Мы используем его, чтобы можно было подавать вывод в плотные слои.Dense
- это плотно связанный слой нейронной сети.Softmax
- это функция активации. Мы используем его, чтобы преобразовать выходные числа в диапазон от 0 до 1. Это также приведет к тому, что все выведенные числа будут суммироваться до 1. Это можно интерпретировать как десятичную вероятность класса.
Обратите внимание, что последний слой имеет такое же количество нейронов, что и классы. Это означает, что этот слой выведет 10 чисел, сопоставленных с классом.
# define the model # takes in images, convoles them, flattens them, classifies them model = Sequential([ Conv2D(16, (3, 3), activation='relu', padding='same', input_shape=input_shape), Conv2D(16, (3, 3), activation='relu', padding='same'), MaxPooling2D(pool_size=(2,2), strides=None, padding='valid'), Conv2D(32, (3, 3), activation='relu', padding='same'), Conv2D(32, (3, 3), activation='relu', padding='same'), MaxPooling2D(pool_size=(2,2), strides=None, padding='valid'), Conv2D(64, (3, 3), activation='relu', padding='same'), Conv2D(64, (3, 3), activation='relu', padding='same'), MaxPooling2D(pool_size=(2,2), strides=None, padding='valid'), Conv2D(128, (3, 3), activation='relu', padding='same'), Conv2D(128, (3, 3), activation='relu', padding='same'), MaxPooling2D(pool_size=(2,2), strides=None, padding='valid'), Flatten(), Dense(256, activation='relu'), Dense(n_classes, activation='softmax') ]) # define the optimizer and loss to use model.compile(optimizer=optimizers.SGD(lr=learning_rate, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy'])
Изучите модель
Мы можем создать общий обзор структуры модели. Каждая строка - это слой модели.
# look at the defined model model.summary()
Структура модели
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_1 (Conv2D) (None, 200, 200, 16) 448 _________________________________________________________________ conv2d_2 (Conv2D) (None, 200, 200, 16) 2320 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 100, 100, 16) 0 _________________________________________________________________ conv2d_3 (Conv2D) (None, 100, 100, 32) 4640 _________________________________________________________________ conv2d_4 (Conv2D) (None, 100, 100, 32) 9248 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 50, 50, 32) 0 _________________________________________________________________ conv2d_5 (Conv2D) (None, 50, 50, 64) 18496 _________________________________________________________________ conv2d_6 (Conv2D) (None, 50, 50, 64) 36928 _________________________________________________________________ max_pooling2d_3 (MaxPooling2 (None, 25, 25, 64) 0 _________________________________________________________________ conv2d_7 (Conv2D) (None, 25, 25, 128) 73856 _________________________________________________________________ conv2d_8 (Conv2D) (None, 25, 25, 128) 147584 _________________________________________________________________ max_pooling2d_4 (MaxPooling2 (None, 12, 12, 128) 0 _________________________________________________________________ flatten_1 (Flatten) (None, 18432) 0 _________________________________________________________________ dense_1 (Dense) (None, 256) 4718848 _________________________________________________________________ dense_2 (Dense) (None, 10) 2570 ================================================================= Total params: 5,014,938 Trainable params: 5,014,938 Non-trainable params: 0 _________________________________________________________________
Перед обучением проверьте точность модели
Давайте посмотрим, насколько хорошо модель работает, прежде чем тренировать ее. Определим точность модели по 1 классу. Это будет сделано путем прогнозирования всех изображений 1 класса. Помните, что это не является репрезентативным для всей модели, поскольку это только 1 класс из 10.
# label of the class we are making predictions on single_class = class_keys[0] # first class image paths single_class_image_paths = image_paths[0] # make predictions on the first class single_class_predictions = predict(int(n_validation / n_classes), single_class_image_paths, model) # get the accuracy of predictions on the first class single_class_accuracy = predictions_accuracy(class_keys, single_class, single_class_predictions) print("Current accuracy of model for class " + single_class + ": " + str(single_class_accuracy))
Обучение модели с использованием облачных графических процессоров
Эта модель имеет более 5000000 обучаемых параметров - их слишком много, чтобы настраивать их вручную. Нам нужно обучить модель с помощью обучающего набора данных, чтобы модель могла узнать оптимальные веса, которые следует использовать. Эти веса являются значениями параметров модели.
# log information for use with tensorboard tensorboard = TensorBoard(log_dir=output_logs_dir) # train the model using the training data generator model.fit_generator(train_generator, steps_per_epoch=math.floor(n_train/batch_size), validation_data=validation_generator, validation_steps=n_validation, epochs=epochs, callbacks=[tensorboard])
Изучите точность модели после некоторого обучения
Давайте посмотрим, насколько хорошо работает модель, теперь, когда мы немного ее обучили. Опять же, будем определять точность модели по 1 классу.
# make predictions on the first class single_class_predictions = predict(int(n_train / n_classes), single_class_image_paths, model) # get the accuracy of predictions on the first class single_class_accuracy = predictions_accuracy(class_keys, single_class, single_class_predictions) print("Current accuracy of model for class " + single_class + ": " + str(single_class_accuracy))
Продолжить обучение модели
Продолжим обучение модели.
# train the model using the training data generator model.fit_generator(train_generator, steps_per_epoch=math.floor(n_train/batch_size), validation_data=validation_generator, validation_steps=n_validation, epochs=epochs, callbacks=[tensorboard])
Изучите точность модели после обучения
Теперь, когда мы закончили обучение модели, давайте проверим ее точность на 1 классе.
# make predictions on the first class single_class_predictions = predict(int(n_train / n_classes), single_class_image_paths, model) # get the accuracy of predictions on the first class single_class_accuracy = predictions_accuracy(class_keys, single_class, single_class_predictions) print("Current accuracy of model for class " + single_class + ": " + str(single_class_accuracy))
Понимание показателей обучения
Наша цель - максимизировать точность проверки при минимизации потерь при проверке. Набор данных проверки никогда не используется для обучения. Это позволяет нам измерить, насколько хорошо модель работает с изображениями, которые она никогда раньше не видела.
В конце обучения точность обучения и проверки должна быть одинаковой. Если этих значений нет, это может быть признаком переобучения.
Вы должны увидеть уменьшение потерь (потерь) при обучении, повышение точности обучения (соотв.) Для данных обучения.
Вы должны увидеть уменьшение потерь при проверке (val_loss) и повышение точности проверки (val_acc) для данных проверки.
Тензорборд
Tensorboard - это набор инструментов визуализации под названием TensorBoard. Вы можете использовать TensorBoard для визуализации вашего графика TensorFlow, построения количественных показателей выполнения вашего графика и отображения дополнительных данных, таких как изображения, которые проходят через него . Это полезно для понимания того, как сравниваются модели / гиперпараметры.
В JupyterLab вы можете использовать вкладку команд для создания новой Tensorboard.
- Откройте
commands panel
с помощьюCTRL + SHIFT + C
- Искать
Create a new tensorboard
- Выберите этот параметр и укажите на него
animal_classifier/logs
.
Вы сможете визуализировать точность своей модели по эпохам. Каждый тренировочный запуск создает новый набор журналов. Это отображается в Tensorboard в виде отдельной линии.
Ниже приведены скриншоты моих результатов тренировки, нанесенные на Tensorboard. Ваши результаты должны выглядеть примерно одинаково.
Потеря тренировки
Точность тренировки
Утрата валидации
Точность проверки
Предсказывать
Полезно знать, какие изображения были предсказаны правильно, а какие нет. Давайте рассмотрим 10 прогнозов, по 1 прогнозу на класс.
# get 1 image path per class predict_image_paths = [image_path[0] for image_path in image_paths] # Make 1 prediction per class predictions = predict(10, predict_image_paths, model) # plot the image that was predicted plot_prediction(class_keys, predict_image_paths, predictions)
Экспорт обученной модели
Что нам делать с обученной моделью? Экспорт для ваших приложений!
Мы можем использовать модель поезда вместо обучения каждый раз, когда захотим. Есть много форматов, в которые вы можете экспортировать его. Здесь мы экспортируем его, чтобы он мог быть загружен с помощью этой записной книжки.
# export the model for later model.save(model_name)
Следующие шаги
В моем следующем сообщении в блоге мы исследуем поиск гиперпараметров до точности модели. Мы также рассмотрим, как можно улучшить архитектуру модели.
Образовательные ресурсы
- Курс Эндрю Нг по машинному обучению считается стандартным. Это часто рекомендуется.
- Fast.ai предлагает множество отличных курсов для изучения машинного обучения.
- Keras - Guide to the Sequential Model - отличный стартер для создания моделей с Keras.