Компьютерное зрение — это область искусственного интеллекта (ИИ), которая позволяет компьютерам и системам извлекать значимую информацию из цифровых изображений, видео и других визуальных входных данных, а также предпринимать действия или давать рекомендации на основе этой информации. (Источник: https://www.ibm.com/)

Машинное обучение похоже на компьютерный мозг, который извлекает информацию из входных данных. Чем больше входных данных для модели машинного обучения, тем она точнее (например, когда мы учим детей).

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

В этой статье вы узнаете, как использовать Python с библиотекой Keras для выполнения классификации изображений. Это будет простое руководство, которое может добавить более продвинутые функции позже.

📔 Резюме шага

  1. Чтение набора данных
  2. Исследование данных
  3. Предварительная обработка данных
  4. Создать модель
  5. Обучить модель
  6. Оценка модели

💽 Набор данных

Пример набора данных: изображения риса. В Турции часто выращивают пять различных сортов риса: арборио, басмати, ипсала, жасмин и каракадаг. Есть 75 000 изображений; 15 000 штук каждого из этих сортов.



Шаг 1: Чтение набора данных

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

1. Определите расположение основной папки

img_path = "C:/Project/Rice_Classification/Rice_Image_Dataset/"

⚠️ Не забудьте поставить / в конце пути.

2. список всех классов/категорий/ярлыков изображений

rice_label = ['Arborio','Basmati','Ipsala','Jasmine','Karacadag']

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

3. Создайте фрейм данных пути к изображению и метки

import pandas as pd
import os
img_list = []
label_list = []
for label in rice_label:
    for img_file in os.listdir(img_path+label):
        img_list.append(img_path+label+'/'+img_file)
        label_list.append(label)
        
df = pd.DataFrame({'img':img_list, 'label':label_list})

Объяснение кода

  • img_list: расположение файла изображения
    label_list: метка каждого изображения
  • Перебрать все подпапки (img_path+метка)
  • Найдите все файлы изображений в каждой подпапке и добавьте местоположение файла в img_list.
  • Затем добавьте метку на основе имени подпапки
  • Создайте фрейм данных из столбцов img_list и label_list
df.head()

Мы получим такой фрейм данных.

Шаг 2. Исследование данных

1. Подсчитайте количество изображений каждой категории риса

df['label'].value_counts()

В каждой категории 15 000 изображений. ХОРОШО!

2. Показать примеры изображений

import matplotlib.pyplot as plt
fig, ax = plt.subplots(ncols=len(rice_label), figsize=(20,4))
fig.suptitle('Rice Category')
random_num = 12
for i,label in enumerate(rice_label):
    ax[i].set_title(label)
    ax[i].imshow(plt.imread(df[df['label']==label]['img'].iloc[random_num]))

Используйте matplotlib для показа образцов изображений (Вы можете просто открывать файлы изображений в папках, но этот метод круче. Шучу. Показ изображений с помощью matplotlib можно адаптировать для иллюстрации изображений после увеличения изображения, поэтому рекомендуется научиться использовать matplotlib с изображениями.

Объяснение кода

  • Создайте подзаголовок с количеством столбцов, равным количеству категории
  • random_num используется для случайного выбора изображений для показа. Вы можете изменить эту переменную, чтобы изменить отображаемые изображения.
  • Прокрутите по методу Risk_label, чтобы отобразить по 1 изображению каждой этикетки с рисом.

plt.imread используется для чтения изображения из файла в массив

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

⚠️ Если вы используете OpenCV для чтения изображений, цвет изображения может быть неправильным, поскольку OpenCV использует BGR в качестве порядка цветов по умолчанию для изображений, а matplotlib использует RGB. Когда вы отображаете изображение, загруженное с помощью OpenCv в matplotlib, каналы будут обратными. (Вы можете прочитать больше здесь")

3. Знать форму изображения

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

plt.imread(df['img'][0]).shape

.shape используется с массивом изображений, чтобы узнать размер изображения.

Результат (250, 250, 3).

Шаг 3: Предварительная обработка данных

1. Кодировать ярлык

Модель глубокого обучения требует, чтобы прогнозируемые результаты были числовыми, поэтому перед обучением модели метки должны быть закодированы (изменены) с категориального на числовое значение.

# Create a dataframe for mapping label
df_labels = {
    'Arborio' : 0,
    'Basmati' : 1,
    'Ipsala' : 2,
    'Jasmine' : 3,
    'Karacadag': 4
}
# Encode
df['encode_label'] = df['label'].map(df_labels)
df.head()

Объяснение кода

  • Создайте словарь df_labels, в котором ключи — это категории риса, а значения — порядковые номера.
  • Используйте .map для кодирования «метки» столбца фрейма данных с помощью df_labels
  • df будет иметь новый столбец encode_label, который является закодированным номером столбца метки.

2. Подготовьте набор данных для обучения модели

Ввод (X): изображение

import cv2
X = []
for img in df['img']:
    img = cv2.imread(str(img))
    # img = augment_function(img)
    img = cv2.resize(img, (96, 96))
    img = img/255
    X.append(img)

Прежде чем изображение будет введено для обучения модели, оно должно быть преобразовано в массив определенного размера для модели и масштабировано, чтобы иметь значение от 0 до 1.

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

Вывод (y):закодированная метка каждого изображения.

y = df['encode_label']

3. Разделение обучения/проверки/тестирования

from sklearn.model_selection import train_test_split
X_train, X_test_val, y_train, y_test_val = train_test_split(X, y)
X_test, X_val, y_test, y_val = train_test_split(X_test_val, y_test_val)

обучение 80 %, проверка для настройки модели 4 %, тестовый набор 16 %

Шаг 4: Создайте модель

1. Использовать VGG16 в качестве базовой модели

VGG16 — известная архитектура сверточной нейронной сети (CNN), изобретенная Кареном Симоняном и Эндрю Зиссерманом в 2014 году.

Вместо обучения модели глубокого обучения с нуля я использую метод трансферного обучения, чтобы использовать предварительно обученную модель (VGG16) в качестве отправной точки и добавить несколько слоев, соответствующих нашей задаче.

Сначала импортируйте модель VGG16 и установите входную форму (96,96,3).

from keras.applications.vgg16 import VGG16

base_model = VGG16(input_shape=(96,96,3), include_top=False, weights='imagenet')

base_model.summary()

Затем заморозьте параметры модели VGG16 и разрешите настраивать только параметры в последнем слое, чтобы уменьшить вычислительную нагрузку.

for layer in base_model.layers:
    layer.trainable = False
base_model.layers[-2].trainable = True
base_model.layers[-3].trainable = True
base_model.layers[-4].trainable = True

2. Добавьте слои в модель

Пришло время добавить пользовательские слои в базовую модель для нашей задачи.

from tensorflow.keras.models import *
from tensorflow.keras.layers import *
model = Sequential()
model.add(Input(shape=(96,96,3)))
model.add(base_model)
model.add(Flatten())
model.add(Dropout(0.2))
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(len(rice_label), activation='softmax'))
model.summary()

Как вы можете видеть в обзоре модели, VGG16 является отправной точкой. Затем добавляются слои Flatten, Dropout и Dense.

Я не буду вдаваться в детали каждого слоя в этой статье. Важным слоем, на котором вы должны сосредоточиться, является последний плотный слой. Этот слой даст результат классификации изображений. Он настроен на выходную форму, равную len(rice_label), которая в данном случае равна 5, поэтому результатом будут вероятности 5 категорий риса, а функция softmax суммирует категорию с наибольшей вероятностью.

Шаг 5: Обучите модель

Обучим модель!!

model.compile(
  optimizer="adam",
  loss='sparse_categorical_crossentropy',
  metrics=['acc'])
history = model.fit(X_train, y_train, epochs=5, validation_data=(X_val, y_val))

Этот шаг может занять много времени.

Вы увидите точность каждой эпохи.

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

Шаг 6: Оценка модели

1. Протестируйте модель с помощью тестового набора

model.evaluate(X_test,y_test)

Точность составляет 91,49 % (может достигать 99 % при использовании всех 75 000 изображений).

2. Визуализируйте модель

Точность графика каждой эпохи. Скорее всего, вы увидите более высокую точность в более высокой эпохе (модель лучше).

plt.plot(history.history['acc'], marker='o')
plt.plot(history.history['val_acc'], marker='o')
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'val'], loc='lower right')
plt.show()

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

plt.plot(history.history['loss'], marker='o')
plt.plot(history.history['val_loss'], marker='o')
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'val'], loc='upper right')
plt.show()

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

Заключение

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

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