Как создать модель классификации изображений за считанные минуты

Глубокое обучение: прогнозирование рака кожи

Создайте сверточную нейронную сеть на Python для распознавания доброкачественных / злокачественных клеток меланомы.

I. || Введение ||

Когда я только начал этот проект, я программировал на Python всего около 2 месяцев. На моем компьютере был установлен Keras, и я изучал алгоритмы классификации и то, как они работают в рамках модели сверточной нейронной сети.
сверточной нейронной сети (которую я теперь буду называть CNN) - это алгоритм глубокого обучения, который принимает входное изображение, назначает важность (обучаемые веса и смещения) различным функциям / объектам на изображении, а затем может отличать одно от другого.

Подобно искусственным нейронным сетям (ANN), но более мощные и продвинутые, CNN более сложны с точки зрения предварительной обработки и вычислений, однако создать CNN с нуля довольно просто. . Вам просто нужно понимать каждый шаг и его важность для общей функции модели.

Создание CNN состоит из 4 этапов:

Шаг 1- Свертка:
Функция, полученная из двух заданных функций путем интегрирования, которая выражает, как форма одной изменяется другой. Есть 3 основных элемента операции свертки:

  • Входное изображение: фактическое изображение в пикселях (в основном наши входные данные)
  • Детектор функций: их можно даже назвать фильтрами. В основном они обнаруживают определенные особенности входного изображения. Детекторы признаков размещаются над входным изображением (хотя их размер намного меньше) и подсчитывают количество ячеек, в которых детектор признаков соответствует подмножеству входного изображения. Затем детектор признаков самостоятельно перемещает входное изображение, чтобы охватить все его области, и расстояния, на которые он перемещается, можно назвать «шагами».

  • Карта функций: содержит аргументы, записанные фильтром по входному изображению. Значение из входного изображения изначально вставляется в верхнюю левую ячейку карты функций и перемещает блок вправо, записывая наблюдение за каждым шагом.

Шаг 2- Максимальный пул:
Цель максимального пула - позволить CNN обнаруживать изображение при представлении с базовой модификацией (перевернутое, зеркальное, верхнее -вниз). На этом этапе мы определяем объединенную карту функций.

  • Примечание. Он отличается от процесса, используемого для определения карт объектов в свертке.
    Этот процесс включает в себя размещение меньшей матрицы поверх карты функций и вставку максимального значения из матрицы в нашу объединенную карту функций. Затем мы продолжаем двигаться вправо, пока не заполним все значения, как это было сделано на этапе свертки.

  • Max Pooling занимается обучением сверточной нейронной сети распознавать, что, несмотря на все эти различия, все они являются изображениями одного и того же. Для этого сети необходимо приобрести свойство, известное как «пространственная дисперсия», чтобы она могла распознавать объект на изображении, даже если он пространственно отличается от другого изображения того же объекта. Существуют также другие методы объединения, такие как Среднее объединение (принимает среднее значение) и Объединение сумм (берет сумму).

Шаг 3 - Сглаживание.

К тому времени, когда мы дойдем до этого шага, у нас уже есть объединенная карта функций. Как следует из названия этого шага, мы буквально сгладим нашу объединенную карту функций в форму столбца. Таким образом, вместо того, чтобы выглядеть как квадратная матрица, наша объединенная карта функций теперь выглядит как вертикальный столбец.

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

Шаг 4 - Полное соединение. Полностью подключенный уровень в CNN аналогичен скрытому уровню в ANN. Роль искусственной нейронной сети состоит в том, чтобы взять эти данные и объединить функции в более широкий спектр атрибутов, которые делают сверточную сеть более способной к классификации изображений.

  • Это также шаг, на котором мы вычисляем функцию ошибок, которую наша сеть принимает во внимание, прежде чем делать прогнозы. В ИНС это называлось функцией потерь. Теперь машина может размещать веса на каждом из полностью связанных слоев, чтобы определить двоичный результат нашей независимой переменной.

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

II. || Сводка рабочего процесса ||

1. Начнем с входного изображения. В нашем случае мы использовали бы одно изображение из нашего набора данных, состоящего из 1000 изображений, а позже мы бы зациклили функцию на других изображениях.
2. Мы применяем фильтры или карты функций ко входным данным. изображение, которое дает нам сверточный слой.
3. Затем мы нарушаем линейность этого изображения с помощью функции выпрямителя.
4. Изображение готово к объединению, цель которого - предоставить нашей CNN «пространственные данные». инвариантность ». Вы увидите, как это объясняется более подробно в руководстве по пулингу. После объединения мы получаем объединенную карту функций.
5 . Затем мы выравниваем нашу объединенную карту функций перед вставкой в ​​искусственную нейронную сеть.

На протяжении всего этого процесса строительные блоки сети, такие как веса и карты характеристик, обучаются и многократно изменяются, чтобы сеть достигла оптимальной производительности, которая позволит ей классифицировать изображения и объекты с максимальной точностью.

III. || Определение проблемы ||

Набор данных, который я использую, - это изображения из Базы данных ISIC. Это микроскопические изображения клеток доброкачественного и злокачественного рака кожи. Основная проблема заключается в том, что изображения довольно большие, и поэтому мне потребуется графический процессор или лучший процессор для обработки всех этих изображений без постоянного сбоя Jupyter. Для целей этого проекта я использую 1000 изображений в моем наборе обучающих данных (500 доброкачественных и 500 злокачественных) и 400 изображений в моем тестовом наборе данных (200 доброкачественных и 200 злокачественных).

Примечание. Я понимаю, что точность моей модели может быть не такой высокой из-за небольшого размера выборки, однако это лучшее, что я могу, работая над MacBook с Intel M3. процессор.

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

IV. || Модель конвейера ||

Чтобы построить модель CNN, мы проходим следующий процесс:

  1. Импорт пакетов и библиотек Keras
  2. Инициализация CNN
  3. Добавление слоя свертки
  4. Добавление слоя объединения
  5. Добавление сворачивания к слою
  6. Добавление полностью связанного слоя
  7. Составление CNN
  8. Подгонка CNN к моему набору данных изображений

В. || Создание модели CNN ||

Начнем с импорта пакетов Keras, необходимых для этого конвейера.
Ниже описаны 5 классов Keras, вы можете прочитать их, чтобы понять, как каждый из них будет использоваться в модели:

1. Последовательный: этот класс используется для инициализации нашей CNN. Есть два способа инициализации класса: во-первых, с помощью последовательного, а во-вторых, с помощью графа.

2. Convolution2D: это класс для нашей операции свертки. Как упоминалось выше, операция свертки - один из наиболее важных шагов в построении CNN. Этот класс используется для 2D-моделей, что и есть у нас.

3. MaxPooling2D: еще один 2D-класс, который запускает операцию Max pooling на нашей CNN, учитывая несколько параметров, касающихся наших данных. Как упоминалось ранее, Max Pooling - необходимый шаг в построении CNN, поскольку он делает модель более жесткой и восприимчивой к таким изменениям, как переворачивание, зеркальное отображение изображения и т. Д.

4. Flatten: этот класс участвует на следующем этапе построения нашей модели. Чтобы наша машина могла понять данные, мы должны преобразовать их из матрицы в столбец, что может быть выполнено путем сглаживания данных.

5. Плотный: это наиболее важный класс, поскольку он создает выходной слой для ИНС, который будет важен при оптимизации наших весов для модели и назначении функции потерь / ошибок для оценки эффективности модели.

In [1]: # Importing Keras packages
from keras.models import Sequential
from keras.layers import Convolution2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
Output: Using TensorFlow backend.

V.i ~ Инициализация CNN

Я создал объект, названный классификатором, который, по сути, является моделью классификации CNN, которую я буду строить на протяжении всего этого проекта. Я прикрепил этот объект к классу Sequential, чтобы инициализировать модель CNN как последовательность слоев.

In [2]: #initializing the CNN
classifier = Sequential()

V.ii ~ Добавление слоя свертки

Следующим шагом будет добавление сверточного слоя. Как я уже упоминал выше, сверточный слой применяет фильтр или детектор признаков к входному изображению и создает карту признаков для изображений. Я использовал класс Convolution 2D, для которого я объясняю параметры ниже:

  • Первый параметр относится к количеству детекторов признаков. Значение по умолчанию - 64, но поскольку я использую ЦП, а не графический процессор, я решил использовать 32 детектора функций, чтобы сэкономить время и быть более изобретательным, поскольку у меня есть 1000 обучающих изображений и 400 тестовых изображений. Однако 64 детектора признаков могут сделать эту модель намного более точной.
  • Второй и третий параметры относятся к размеру или размерам наших детекторов признаков, которые будут матрицей 3 x 3, поэтому я ввожу (3, 3).
  • Третий параметр - это форма ввода, то есть форма и размер входного изображения. Поскольку все мои изображения имеют разные размеры, позже я конвертирую их в 32 x 32 пикселя. Я указал 3 для количества цветовых каналов, так как это цветные изображения, использующие 3 канала (RBG). Если бы он был черно-белым, я бы ввел 1 вместо 3.
  • Последний параметр - функция активации, которую мы используем для активации нейронов нейронной сети. Я использую функцию активации выпрямителя, поскольку это нелинейная модель, поэтому мы вводим "relu"
In [3]: #Adding the Convolution Layer
classifier.add(Convolution2D(32, 3, 3, input_shape = (32, 32, 3), activation = ‘relu’))

V.iii ~ Добавление уровня объединения

Следующий шаг состоит в добавлении уровня объединения в модель CNN. Снова используя метод добавления, я добавляю класс MaxPooling2D и указываю размер пула, который будет перемещаться по карте объектов для создания объединенной карты объектов. В этом случае я буду использовать бассейн размером 2 X 2. Этот шаг важен для уменьшения размера нашей карты функций, делая модель менее сложной и вычислительной.

In [4]: #Adding the Pooling Layer
classifier.add(MaxPooling2D(pool_size=(2, 2)))

V.iv ~ Добавление сглаживания к слою

Ниже я снова использовал функцию добавления, чтобы добавить класс Flatten к нашему объекту classifier. Это, как я уже упоминал ранее, создает форму столбца из объединенной матрицы признаков путем ее выравнивания. Для этого класса не требуются параметры, поэтому квадратные скобки я оставляю пустыми.

In [5]: #Flattening the layer
classifier.add(Flatten())

V.v ~ Добавление полностью подключенного слоя и выходного слоя.

Следующий шаг - заключительная часть построения модели CNN. В этой модели я создаю полностью связанный слой, который похож на скрытые слои в моей модели ИНС. Итак, первая строка кода ниже создает скрытый слой. Используя метод добавления, я использую функцию Dense, которая имеет 2 параметра:

  • Первый - это количество узлов для выходного слоя. В моей модели ИНС я взял среднее значение суммы входных и выходных слоев, однако в этом случае даже это число было бы слишком большим. Таким образом, я провел небольшое исследование и обнаружил, что мы не должны использовать слишком маленькое число. Я узнал, что для начала неплохо иметь как минимум 128 узлов.
    • Второй параметр - это функция активации, которая снова будет relu, поскольку я использую функцию выпрямителя для этой нелинейной модели. Затем я создал выходной слой с аналогичной строкой кода. Поскольку выходные данные представляют собой двоичную переменную, у нее будет 1 узел, и поскольку я хочу знать вероятность того, что эта модель предскажет, является ли клетка доброкачественной или злокачественной, я использую функцию активации сигмовидной кишки.
In [6]: # Full Connection
classifier.add(Dense(output_dim = 128, activation = ‘relu’))
classifier.add(Dense(output_dim = 1, activation = ‘sigmoid’))
  • Это отдельный от пакета ipykernel, поэтому мы можем избежать импорта на потом.

V.vi ~ Составление CNN

Теперь, когда я построил модель CNN, мне нужно скомпилировать ее и оптимизировать веса и функцию потерь для оценки модели. Для этого я использую метод компиляции в своем объекте классификатора и
ввожу следующие параметры:
• Оптимизатор - алгоритм, который я использовал для нахождения оптимальных весов для модели CNN. Я использую adam, алгоритм стохастического градиентного спуска. Алгоритм «adam» - один из самых быстрых.
• Функция потерь, которая будет двоичной_кросцентропией (как и моя модель ИНС), поскольку то, что мы пытаемся предсказать, является двоичной переменной (1 или 0; или злокачественный).
• Функция показателей, которая будет оценивать модель. Я снова использую точность, которая определяется делением истинных предсказаний на общие предсказания.

In [7]: #Compiling the CNN
classifier.compile(optimizer = ‘adam’, loss = ‘binary_crossentropy’, metrics = [‘accuracy’])

VI. || Подгонка модели CNN к набору данных ||

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

Объясняя код, я буду ссылаться на некоторые важные параметры:

  • Сначала мне пришлось импортировать ImageDataGeneratorclass, который используется для масштабирования, масштабирования и переворачивания изображений (чтобы сделать нашу модель CNN более жесткой). Я сохранил параметры по умолчанию при масштабировании, shear_range, zoom_range и horizontal_flip. Затем мы масштабируем данные тестового изображения на ту же величину. Затем я использую поток из метода каталога, чтобы подогнать обучающий набор и тестовый набор к нашим данным изображения. Для этого использовались следующие параметры:
  1. Первый параметр указывает путь к обучающим / тестовым данным в каталоге.
  2. Целевой размер относится к размеру целевого изображения, которое составляет 32 x 32 пикселя.
  3. batch_size относится к тому, как часто мы хотим изменять наши веса. Я выбрал 10 для набора обучающих данных и 32 для набора тестовых данных, чтобы повторно оптимизировать веса после 10 и 32 наблюдений для двух наборов соответственно.
  4. class_mode будет двоичным, поскольку машина предсказывает двоичную переменную. Наконец, мы подбираем набор данных с помощью метода fit_generator. Здесь я указываю следующие параметры:
  • Шаги на эпоху относятся к количеству изображений в нашем обучающем наборе, которое составляет 1000.
  • Эпохи: сколько раз я хочу запустить полную модель. Согласно моим исследованиям, чем больше, тем лучше. Но чем больше у вас есть, тем больше на это уходит времени. А пока давайте рассмотрим 25 эпох.
  • Данные проверки - это наш тестовый набор, который покажет, насколько точно машина может предсказать новые данные.
  • Шаги проверки относятся к количеству изображений в нашем тестовом наборе, которое составляет 400.
In [9]: #Fitting our CNN to the image dataset
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(
                    rescale=1./255,
                    shear_range=0.2,
                    zoom_range=0.2,
                    horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
training_set = train_datagen.flow_from_directory                    
                     (‘dataset/training_set’,
                       target_size=(32, 32),
                       batch_size=10,
                       class_mode=’binary’)
test_set = test_datagen.flow_from_directory
                (‘dataset/test_set’,
                  target_size=(32, 32),
                  batch_size=32,
                  class_mode=’binary’)
classifier.fit_generator(training_set,
                         steps_per_epoch=1000,
                         epochs=25,
                         validation_data= test_set, 
                         validation_steps=400)
____________________________________________________________________
>> Found 1000 images belonging to 2 classes.
Found 400 images belonging to 2 classes.
Epoch 1/25
1000/1000 [==============================] - 919s 919ms/step - loss: 0.4773 - acc: 0.7762 - val_loss: 0.5675 - val_acc: 0.7172
Epoch 2/25
1000/1000 [==============================] - 997s 997ms/step - loss: 0.4522 - acc: 0.7902 - val_loss: 0.6097 - val_acc: 0.7027
Epoch 3/25
1000/1000 [==============================] - 1016s 1s/step - loss: 0.4267 - acc: 0.8085 - val_loss: 0.7107 - val_acc: 0.6717
Epoch 4/25
1000/1000 [==============================] - 916s 916ms/step - loss: 0.4042 - acc: 0.8189 - val_loss: 0.6394 - val_acc: 0.7077
Epoch 5/25
1000/1000 [==============================] - 911s 911ms/step - loss: 0.3837 - acc: 0.8260 - val_loss: 0.5823 - val_acc: 0.7525
Epoch 6/25
1000/1000 [==============================] - 926s 926ms/step - loss: 0.3641 - acc: 0.8367 - val_loss: 0.5997 - val_acc: 0.7272
Epoch 7/25
1000/1000 [==============================] - 924s 924ms/step - loss: 0.3371 - acc: 0.8508 - val_loss: 0.6877 - val_acc: 0.6772
Epoch 8/25
1000/1000 [==============================] - 936s 936ms/step - loss: 0.3034 - acc: 0.8683 - val_loss: 0.6646 - val_acc: 0.7198
Epoch 9/25
1000/1000 [==============================] - 909s 909ms/step - loss: 0.2874 - acc: 0.8775 - val_loss: 0.7226 - val_acc: 0.7223
Epoch 10/25
1000/1000 [==============================] - 910s 910ms/step - loss: 0.2605 - acc: 0.8910 - val_loss: 0.7102 - val_acc: 0.7284
Epoch 11/25
1000/1000 [==============================] - 995s 995ms/step - loss: 0.2333 - acc: 0.9042 - val_loss: 0.7932 - val_acc: 0.7145
Epoch 12/25
1000/1000 [==============================] - 971s 971ms/step - loss: 0.2208 - acc: 0.9053 - val_loss: 0.7419 - val_acc: 0.7276
Epoch 13/25
1000/1000 [==============================] - 1010s 1s/step - loss: 0.2065 - acc: 0.9163 - val_loss: 0.7350 - val_acc: 0.7478
Epoch 14/25
1000/1000 [==============================] - 1009s 1s/step - loss: 0.1859 - acc: 0.9286 - val_loss: 0.9156 - val_acc: 0.7075
Epoch 15/25
1000/1000 [==============================] - 1692s 2s/step - loss: 0.1768 - acc: 0.9314 - val_loss: 0.8815 - val_acc: 0.7484
Epoch 16/25
1000/1000 [==============================] - 920s 920ms/step - loss: 0.1598 - acc: 0.9381 - val_loss: 1.1154 - val_acc: 0.7016
Epoch 17/25
1000/1000 [==============================] - 945s 945ms/step - loss: 0.1499 - acc: 0.9410 - val_loss: 0.9679 - val_acc: 0.7255
Epoch 18/25
1000/1000 [==============================] - 875s 875ms/step - loss: 0.1445 - acc: 0.9441 - val_loss: 1.0249 - val_acc: 0.7328
Epoch 19/25
1000/1000 [==============================] - 806s 806ms/step - loss: 0.1286 - acc: 0.9523 - val_loss: 0.9636 - val_acc: 0.7497
Epoch 20/25
1000/1000 [==============================] - 722s 722ms/step - loss: 0.1154 - acc: 0.9573 - val_loss: 1.0162 - val_acc: 0.7304
Epoch 21/25
1000/1000 [==============================] - 744s 744ms/step - loss: 0.1180 - acc: 0.9562 - val_loss: 1.1624 - val_acc: 0.7396
Epoch 22/25
1000/1000 [==============================] - 748s 748ms/step - loss: 0.1082 - acc: 0.9592 - val_loss: 1.2905 - val_acc: 0.7351
Epoch 23/25
1000/1000 [==============================] - 719s 719ms/step - loss: 0.0949 - acc: 0.9686 - val_loss: 1.2683 - val_acc: 0.7246
Epoch 24/25
1000/1000 [==============================] - 714s 714ms/step - loss: 0.0941 - acc: 0.9668 - val_loss: 1.2653 - val_acc: 0.7249
Epoch 25/25
1000/1000 [==============================] - 721s 721ms/step - loss: 0.0890 - acc: 0.9670 - val_loss: 1.4443 - val_acc: 0.7151
>>> Out[9]: <keras.callbacks.History at 0xb34753908>

VII. || Заключение ||

Модель CNN, созданная мною выше, была протестирована на распознавание по изображению, является ли раковая клетка кожи доброкачественной или злокачественной.
Модель имеет коэффициент точности на обучающем наборе 96,7% с потерей 0,089 в последнем. эпохи, причем этот показатель является самым высоким среди всех других эпох.
Модель имеет показатель точности на тестовой выборке 71,51% с потерей 1,4443 за последнюю эпоху. Однако самый высокий уровень точности модели - 75,25% - был в эпоху 5/25.
В целом, я бы сказал, что модель показала хорошие результаты и достигла моей цели - более 70% точности.

Ссылки: