Обзор показателей оценки для многоклассовой модели машинного обучения
Будь то мультикласс или мультикласс, наука одна и та же. Мультиклассовая классификация изображений — это обычная задача в компьютерном зрении, когда мы распределяем изображение по трем или более классам.
Мы слышали о методах классификации и регрессии в машинном обучении. Мы знаем, что эти два метода работают на разных алгоритмах для дискретных и непрерывных данных соответственно. В этой статье мы узнаем больше о классификации.
Рабочий процесс:
- Собрать изображения из Google
- удаление дубликатов изображений
- Доминирует цвет фона
- Обучение модели
- прогнозирование категории изображения
Когда мы можем классифицировать изображение более чем по одному классу, это называется проблемой классификации изображений с несколькими метками.
Первоначальные запуски:
import os import pandas as pd import numpy as np import matplotlib.pyplot as plt import cv2 import csv import glob import pickle import time from simple_image_download import simple_image_download from sklearn.cluster import KMeans from PIL import Image, ImageStat from keras.preprocessing import image from keras.preprocessing.image import img_to_array, load_img, ImageDataGenerator from sklearn.model_selection import train_test_split from keras.applications.inception_v3 import InceptionV3 from keras.layers import Dense, GlobalAveragePooling2D from keras.models import Model from keras.optimizers import Adam import warnings warnings.filterwarnings('ignore')
Создайте CSV-файл для категорий, которые вы хотите загрузить, и сохраните его в каталоге проекта. мы будем использовать 16 категорий в этом проекте.
Шаг 1. Получите изображения из Google
def images_scrapped_from_google(): number_of_images_download = 100 response = simple_image_download.simple_image_download with open(load_queries_from_file) as file: queries = list(x[0] for x in csv.reader(file)) for query in queries: response().download(query,number_of_images_download)
simple_image_download — это библиотека Python с открытым исходным кодом, которая удобна для загрузки изображений из Интернета и создания наборов данных для обучения модели.
Шаг 2. Удаление повторяющихся изображений из папки
folders = glob.glob(os.path.join(os.getcwd(), 'simple_images/*')) images_storing = [] duplicated_files = [] for folder in folders: for image in glob.glob(folder + '/*'): if not image in duplicated_files: img_org = Image.open(image) pixel_mean1 = ImageStat.Stat(img_org).mean for image_2 in glob.glob(folder + '/*'): if image != image_2: img_check = Image.open(image_2) pixel_mean2 = ImageStat.Stat(img_check).mean if pixel_mean1 == pixel_mean2: duplicated_files.append(image) duplicated_files.append(image_2) try: os.remove(image_2) except: pass if not image in images_storing: images_storing.append(image) else: if not image in images_storing: images_storing.append(image) return images_storing
Что такое glob.glob?
Таким образом, он позволит вам получить все файлы или папки из каталога с помощью Regex. Например,
folders = glob.glob(“simple_images/*”) print(folders) ------------------------------------------------------------------ ['simple_images/baseball bat', 'simple_images/cricket bat', 'simple_images/volleyball', 'simple_images/basketball', 'simple_images/drum', 'simple_images/piano']
Шаг 3. Определение преобладающего цвета фона
def getting_percentage_of_dominant_colors(cluster, centroids): labels = np.arange(0, len(np.unique(cluster.labels_)) + 1) (hist, _) = np.histogram(cluster.labels_, bins=labels) hist = hist.astype("float") hist /= hist.sum() # iterate through each cluster's color and percentage colors = sorted([(percent, color) for (percent, color) in zip(hist, centroids)]) for (percent, color) in colors: try: if percent > 0.50: print(color, "{:0.2f}%".format(percent * 100)) return True except Exception as e: print(str(e)) return False
Функция проверит, имеет ли изображение преобладающий цвет фона › 0,50, затем изображение будет сохранено, в противном случае удалите его. Причина в том, что когда у вас есть многоцветный фон, модель не сможет точно определить объект.
# Load images and convert to a list of pixels load_images = images_scrapped_from_google() images_for_model_train = [] count = 0 for img in load_images: try: count += 1 print(count) try: image = cv2.imread(img) except Exception: pass image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) reshape = image.reshape((image.shape[0] * image.shape[1], 3)) # Find and display most dominant colors kmeans = KMeans(n_clusters=5).fit(reshape) visualize = getting_percentage_of_dominant_colors(kmeans, kmeans.cluster_centers_) if visualize is True: images_for_model_train.append(img) with open("labels_list_of_single_images.csv", "w", newline="") as f: columns = ['image_path', 'category'] writer = csv.writer(f) writer.writerow(columns) for img_to_csv in images_for_model_train: writer.writerow([img_to_csv, img_to_csv.split("\\")[-2]]) else: try: os.remove(img) except: pass except: print("Unrecognized Input of an Image") os.remove(img)
Написание CSV-файла с категорией, чтобы указать путь к модели, откуда она берет изображение и тренироваться на ней.
Шаг 4. Загрузите модель для обучения
Теперь мы готовы приступить к написанию кода для обучения нашей модели. Мы будем использовать предварительно обученную модель InceptionV3, которая была обучена на данных изображений, имеющих 1000 классов.
Зачем использовать предварительно обученную модель CNN? Начальные слои CNN тренируются только на низкоуровневых и среднеуровневых функциях, таких как края, линии, границы и т. д. Все виды изображений содержат эти функции. Эти характеристики предварительно обученной CNN делают ее многоразовой. Отсюда имеет смысл использовать такие предобученные модели, которые уже прошли обучение на большом наборе данных, для чего многие компании вложили немалые деньги.
try: df = pd.read_csv(os.path.join(os.getcwd(), "labels_list_of_single_images.csv")) top_categories = sorted(list(df['category'].value_counts().index)) target_labels = df['category'] train_data = np.array( [img_to_array(load_img(train_img, target_size=(299, 299))) for train_img in df['image_path'].values.tolist()]) \ .astype('float32') x_train, x_validation, y_train, y_validation = train_test_split(train_data, target_labels, test_size=0.2, random_state=100) print("x_train samples: ", x_train.shape) print("x_validation samples: ", x_validation.shape) y_train = pd.get_dummies(y_train.reset_index(drop=True)).values y_validation = pd.get_dummies(y_validation.reset_index(drop=True)).values # Train Generator train_datagen = ImageDataGenerator(rescale=1. / 255, rotation_range=30, width_shift_range=0.2, height_shift_range=0.2, horizontal_flip='true') train_generator = train_datagen.flow(x_train, y_train, shuffle=False, batch_size=40, seed=42) # Validation Generator val_datagen = ImageDataGenerator(rescale=1. / 255) val_generator = val_datagen.flow(x_validation, y_validation, shuffle=False, batch_size=40, seed=42) # Model Intialize base_model = InceptionV3(weights='imagenet', include_top=False, input_shape=(299, 299, 3)) x = base_model.output x = GlobalAveragePooling2D()(x) # Add a fully-connected layer x = Dense(512, activation='relu')(x) predictions = Dense(16, activation='sigmoid')(x) model = Model(inputs=base_model.input, outputs=predictions) model.compile(Adam(lr=.0001), loss= 'categorical_crossentropy', metrics=['accuracy']) # Train the model start = time.time() model.fit_generator(train_generator, steps_per_epoch=len(x_train) // 40, validation_data=val_generator, validation_steps=len(x_validation) // 40, epochs=5, verbose=2) end = time.time() print("\nTotal Time Taken:", round((end - start) / 60, 2), "Minutes") try: file = open("multi_class_model.pkl", "wb") pickle.dump(model, file) print("Model Saved..!!") except Exception as e: print(str(e)) except Exception as e: print(str(e))
Перенос обучения:
Чтобы использовать предварительно обученную модель, нам нужно оставить все предыдущие слои как есть и изменить только последний слой в соответствии с нашим вариантом использования. InceptionV3 был обучен на 1000 классах изображений. В нашей задаче всего 16 различных классов изображений. Следовательно, мы изменим последний слой InceptionV3 до 16 классов. Трансферное обучение экономит много времени на обучение и усилия инженеров.
ImageDataGenerator работает для дополненных изображений. Мы можем сделать гораздо больше предварительной обработки для увеличения данных. Нейронные сети лучше работают с большим количеством данных. Увеличение данных — это стратегия, которую мы используем во время обучения, чтобы увеличить количество имеющихся у нас данных.
Шаг 5. Прогнозирование категории изображения
# For Prediction def predict_from_image(img_path): model_classes = pickle.load(open("multi_class_model.pkl", "rb")) print(model_classes.summary()) img = image.load_img(img_path, target_size=(299, 299)) img_tensor = image.img_to_array(img) # (height, width, channels) img_tensor = np.expand_dims(img_tensor, axis=0) # (1, height, width, channels), #add a dimension because the model expects this shape: (batch_size, height, width, channels) img_tensor /= 255. pred = model_classes.predict(img_tensor) sorted_category_list = sorted(top_categories) predicted_class = sorted_category_list[np.argmax(pred)] return predicted_class, max(pred) img_path = os.path.join(os.getcwd(), "baseball bat_3.jpg") classes, prob = predict_from_image(img_path) print(f"\n{classes}\n{prob[top_categories.index(classes)]}")
Прогноз модели:
baseball_bat 0.9999959468841553
Сейчас мы успешно построили модель CNN с помощью трансферного обучения. При таком подходе любая проблема мультиклассовой классификации изображений может быть решена с хорошей точностью за короткий промежуток времени.
Удачного обучения…!!!