Обзор показателей оценки для многоклассовой модели машинного обучения

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

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

Рабочий процесс:

  • Собрать изображения из 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 с помощью трансферного обучения. При таком подходе любая проблема мультиклассовой классификации изображений может быть решена с хорошей точностью за короткий промежуток времени.

Удачного обучения…!!!