Задача «кошки против собак» — классический пример классификации изображений в компьютерном зрении, где задача состоит в том, чтобы научить модель различать изображения кошек и собак. Эта задача часто используется в качестве эталона для оценки производительности алгоритмов компьютерного зрения и для сравнения различных подходов к классификации изображений.
В этой задаче я использовал очистку данных, дополнение и передачу обучения более новым моделям CNN, построенным на Tensorflow, для классификации изображений.
Этапы проекта:
- Доступ к данным
- Очистка и анализ данных
- Увеличение данных и разделение набора обучения/проверки
- Модель обучения с трансферным обучением
- Получение результатов на веб-изображениях
Вот полный код проекта для получения дополнительных ссылок и лучшего понимания:«https://www.kaggle.com/code/harshag811/dogs-vs-cats-prediction-with-98-5-accuracy. /блокнот"
1. Доступ к данным и очистка данных
Хотя в Интернете доступно множество наборов данных, я предпочел этот набор данных от Kaggle, который содержит около 25 000 изображений (12 500 для кошек и 12 500 для собак). Набор данных такого размера идеально подходит для обучения нашей модели.
Чтобы запустить новое ядро на Kaggle с набором данных и использовать ускорение графического процессора:
- Перейдите по ссылке, содержащей набор данных.
- Нажмите «Новая записная книжка» в правом верхнем углу страницы.
- Откроется новый блокнот.
- Чтобы запустить код на графическом процессоре, перейдите в раскрывающийся список настроек в правой части экрана.
- Смените ускоритель на GPU. Это настроит GPU для проекта.
- Теперь удалите первую ячейку записной книжки.
- После этих шагов вы можете теперь следовать руководству с этого момента. Это позволит вам работать с набором данных, не загружая его на свой компьютер, а также позволит вам работать с ядром с дополнительной инфраструктурой графического процессора, что ускорит процесс обучения.
ШАГ 1. Загрузка библиотек
# importing basic python libraries import os import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns # importing tensorflow library and keras images API methods for data augmentation import tensorflow as tf from keras.preprocessing.image import ImageDataGenerator, image_dataset_from_directory # libraries for handling images and paths import PIL from pathlib import Path from PIL import UnidentifiedImageError # importing warnings to prevent from unnecessary outputs import warnings warnings.filterwarnings('ignore')
На данный момент мы импортировали важные библиотеки, которые будут полезны для этого проекта. Теперь пришло время поработать с данными.
ШАГ 2. Загрузка и очистка данных
Теперь пришло время получить доступ к данным, которые мы будем использовать для нашей задачи классификации изображений. В правой части записной книжки в разделе input вы найдете "microsoft-catsvsdogs-dataset". В этом разделе внутри PetImages у нас есть разделы «Кошки» и «собаки», содержащие изображения. Мы будем загружать эти данные, чтобы их можно было использовать для нашей задачи классификации.
Проработав несколько итераций и решив случай непригодных изображений, я придумал код, который идентифицирует бесполезные изображения (в нашем случае 2 из 25000 изображений). Давайте запустим код ниже, чтобы узнать, какие это изображения в нашем наборе данных.
path = Path("../input/microsoft-catsvsdogs-dataset/PetImages").rglob("*.jpg") for img_p in path: try: img = PIL.Image.open(img_p) except PIL.UnidentifiedImageError: print(img_p) # path here is our image dataset path => and it looks into .jpg files # if any image is unidentified, that image path is printed
Приведенный выше код печатает:
../input/microsoft-catsvsdogs-dataset/PetImages/Dog/11702.jpg ../input/microsoft-catsvsdogs-dataset/PetImages/Cat/666.jpg
Эти 2 файла изображений не идентифицированы.
Теперь у нас есть большинство файлов .jpg и несколько файлов .db, которые бесполезны. Итак, в этом коде мы попытаемся найти в наших файлах расширения, отличные от .jpg, и удалим их.
# changing the file path !cp -r ../input/microsoft-catsvsdogs-dataset/PetImages ./ # ends will take down the file extensions except .jpg ends = [] # the code below will make sure that non jpg files are removed for content in ('Cat', 'Dog'): path = os.path.join('./PetImages/', content) print(path) print(len(os.listdir(path))) for file in os.listdir(path): dot = file.index('.') end = file[dot+1:] if end != 'jpg': if ends.count(end) == 0: ends.append(end) fpath = path + '/' + file os.remove(fpath) # printing list of non-jpg extensions set(ends)
Был получен следующий вывод:
./PetImages/Cat 12501 ./PetImages/Dog 12501 {'db'}
Это говорит о том, что у нас есть 12501 изображение кошек и собак, а также файлы с расширениями .db.
Теперь удаляем поврежденные файлы:
to_skip = ['./PetImages/Dog/11702.jpg', './PetImages/Cat/666.jpg', './PetImages/Dog/3982.jpg'] for lnks in to_skip: os.remove(lnks)
Наш набор данных теперь чист, и мы готовы работать над дополнением, разделением набора и моделированием.
2. Анализ данных
- Разделение данных без увеличения => Здесь мы будем использовать метод image_dataset_from_directory, который мы импортировали ранее, и зададим ему такие параметры, как batch_size=32, image_size=(224, 224) и validation_split=0.1. соответственно.
train_df = image_dataset_from_directory( directory='./PetImages', color_mode='rgb', batch_size=32, image_size=(224, 224), validation_split=0.1, subset='training', seed=45 ) val_df = image_dataset_from_directory( directory='./PetImages', color_mode='rgb', batch_size=32, image_size=(224, 224), validation_split=0.1, subset='validation', seed=45 )
- Нанесение изображений
# using matplotlib library for plotting cats and dogs images of our dataset plt.figure(figsize=(12, 12)) num_rows = 3 num_cols = 3 for imgs, labels in train_df.take(1): print(imgs.shape) print(labels) for i in range(9): s = plt.subplot(num_rows, num_cols, i+1) plt.imshow(imgs[i].numpy().astype('uint8')) plt.title(int(labels[i])) plt.axis('off')
Следующее изображение было получено с ключом 1, помеченным как собаки, и ключом 2, пометившим кошек.
3. Расширение данных
Использование метода image.ImageDataGenerator() из keras.preprocessing API для увеличения данных. Это гарантирует создание filp-изображений, повернутых на 20 градусов и масштабированных до 1/255. Из этих дополненных изображений создается обучающий и проверочный набор изображений.
MAIN_PATH = './PetImages' CLASSES = os.listdir(MAIN_PATH) NUM_CLASSES = 2 HEIGHT,WIDTH = 224, 224 BATCH_SIZE = 32 SPLIT = 0.2 train_datagen = tf.keras.preprocessing.image.ImageDataGenerator( rescale=1./255, rotation_range=20, horizontal_flip=True, validation_split=SPLIT) train_ds = train_datagen.flow_from_directory( MAIN_PATH, target_size = (HEIGHT,WIDTH), batch_size = BATCH_SIZE, subset = "training", class_mode = "categorical", shuffle = True ) val_ds = train_datagen.flow_from_directory( MAIN_PATH, target_size = (HEIGHT,WIDTH), batch_size = BATCH_SIZE, subset = "validation", class_mode = "categorical", shuffle = True )
Теперь основная задача — применение модели трансферного обучения.
4. ПЕРЕНОС ОБУЧЕНИЯ
ШАГ 1.Импорт трансферного обучения — модель DENSENET201 с помощью Keras API.
from keras.applications.densenet import DenseNet201
ШАГ 2. Использование DenseNet с параметром include_top=False
Мы выбираем веса imagenet и входную форму (224, 224, 3)
dnsnet = DenseNet201(include_top=False, weights='imagenet', input_shape=(224, 224, 3))
ШАГ 3. Модель
Использовалась модель плотности сети201 с весами imagenet и дополнительно были добавлены 2 скрытых слоя.
Уровень-1 со 100 узлами и уровень-2 с 50 узлами. Уровень 3 — это выходной слой с двумя узлами, дающими результат для классификации кошек и собак.
for layer in dnsnet.layers: layer.trainable=False x = tf.keras.layers.Flatten()(dnsnet.output) x = tf.keras.layers.Dense(100, activation='relu')(x) x = tf.keras.layers.Dense(50, activation='relu')(x) preds = tf.keras.layers.Dense(2, activation='sigmoid')(x) model1 = tf.keras.models.Model(inputs=dnsnet.input, outputs=preds) # Creating the callback function def create_callbacks(): cpk_path = './best_model.h5' checkpoint = tf.keras.callbacks.ModelCheckpoint( filepath=cpk_path, monitor='val_accuracy', mode='max', save_best_only=True, verbose=1, ) reducelr = tf.keras.callbacks.ReduceLROnPlateau( monitor='val_accuracy', mode='max', factor=0.1, patience=3, verbose=0 ) earlystop = tf.keras.callbacks.EarlyStopping( monitor='val_accuracy', mode='max', patience=10, verbose=1 ) callbacks = [checkpoint, reducelr, earlystop] return callbacks
Компиляция, обучение и прогнозирование
model1.compile( loss=tf.keras.losses.binary_crossentropy, optimizer=tf.keras.optimizers.Adam(lr=1e-4), metrics=['accuracy'] ) callbacks = create_callbacks() model1.fit(train_ds, epochs=15, validation_data=val_ds, callbacks=callbacks) preds = model1.predict(val_ds) preds = np.argmax(preds) print((preds == val_ds.labels).sum()) print(len(val_ds.labels)) print(model1.evaluate(val_ds))
Эта модель обеспечивает точность 99,7 % на тренировочном наборе.
5. Прогнозы
- Сохранение, загрузка и оценка модели
model1.save('densenet_best_model.h5') new_model = tf.keras.models.load_model('best_model.h5') new_model2 = tf.keras.models.load_model('densenet_best_model.h5') new_model.evaluate(val_ds) new_model2.evaluate(val_ds)
Теперь, чтобы проверить, хорошо ли работает модель, я составил небольшой набор данных из 20 изображений кошек и собак, взятых случайным образом из Google, и пометил их соответствующим образом.
Ссылку на набор данных можно найти здесь. Вы также можете создать свой аналогичный набор данных для этой цели.
- Загрузка нового набора данных и получение прогнозов
Вы можете поместить этот набор данных в раздел ввода справа и получить к нему доступ непосредственно оттуда.
images = os.listdir('../input/catdogsforCheck') # Plotting images plt.figure(figsize=(12, 12)) num_rows = 3 num_cols = 3 for i in range(9): s = plt.subplot(num_rows, num_cols, i+1) img = Image.open('../input/catdogsforCheck/' + str(images[i])) img = np.array(img) plt.imshow(img) plt.title(images[i][:1]) plt.axis('off')
Вот некоторые из изображений различных входных форм и типов, которые я поместил в набор данных.
- Прогноз
from keras.applications.densenet import preprocess_input prediction_table = [] for i in range(len(images)): actual_label = images[i][:1] img = Image.open('../input/catdogsforCheck/' + str(images[i])) img = img.resize(val_ds.target_size) img = np.array(img) x = np.expand_dims(img, axis=0) x = preprocess_input(x) prediction = np.argmax(new_model.predict(x), axis=1) data = {'Image': i, 'ActualLabel': actual_label, 'Prediction': prediction[0]} prediction_table.append(data) prediction_table = pd.DataFrame(prediction_table) from sklearn.preprocessing import LabelEncoder le = LabelEncoder() prediction_table.ActualLabel = le.fit_transform(prediction_table.ActualLabel) prediction_table
- Результаты
19 из 20 изображений были предсказаны хорошо.
Итак, точность составляет 95%. Но если в предсказание будут включены тысячи изображений, например, тренировочный набор, он будет точно иметь 98–99% исправлений.
Спасибо за чтение этого. Это мой самый первый учебник по программированию, поэтому, пожалуйста, извините меня за плохой сценарий, но я обещаю дать мне лучшее в следующих уроках.
С уважением и благодарностью.