Проблема классификации нескольких классов с использованием нейронной сети

Описание Проекта

Вдохновение

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

Набор данных

Выбран набор данных овощей, содержащий 21 000 изображений:

  • обучающий набор содержит 15 000 примеров
  • тестовый набор содержит 3000 примеров
  • набор проверки содержит 3000 примеров

Овощи должны быть разделены на 15 различных типов:

  • Бин
  • Горькая тыква
  • Бутылочная тыква
  • Бринжал
  • Капуста
  • стручковый перец
  • Морковь
  • Цветная капуста
  • Огурец
  • Папайя
  • Картофель
  • тыква
  • Редька
  • Помидор

Запрос на цитирование

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

Вы можете получить доступ к этому набору данных через Kaggle.

Примечание

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

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

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

Итак, сначала мы импортируем связанные библиотеки:

# import library
import os
import numpy as np

Доступ к файлу изображения

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

# Dir:(one example) Vegetable Image/train/Pumpkin/12345.jpg
fileDirVege = 'Vegetable Images' 
vege_dataset = os.listdir(fileDirVege) # [train,test.validation]
vege_train = [] # list: data for training set
vege_test = [] # list: data for test set 
vege_validation = [] # list: data for validation set

for typedir in vege_dataset:
    if(not r'.' in typedir):
        # typeDirName: Vegetable Image/train
        typeDirName = os.path.join(fileDirVege,typedir)
        # vegedir: a list of 15 kinds of vegetables
        vegedir=os.listdir(typeDirName)
        for v in vegedir:
            if v != '.DS_Store': # Note to remove this
                # vegeDirName: Vegetable Image/train/Pumpkin
                vegeDirName = os.path.join(typeDirName,v)
                # vedir: a list of all the jpg file for one type of vegetable
                vedir = np.array(os.listdir(vegeDirName))
             
                for vegetable in vedir: # access each image one by one
                    if(vegetable[-3:]=='jpg'):
                        fn=os.path.join(vegeDirName,vegetable)
                        if typedir == 'train':
                            vege_train.append(fn)
                        elif typedir == 'test':
                            vege_test.append(fn)
                        else:
                            vege_validation.append(fn)

Обработка изображений и маркировка

Способ, которым компьютер решает задачу, заключается в обработке числовых данных. Итак, нам нужно преобразовать изображение в числовое представление.

Перед преобразованием мы можем немного обработать изображение. Чтобы сократить время вычислений, мы можем изменить изображение RGB на уровень серого. И поскольку размеры изображений не равны, нам также нужно изменить их размер до одинакового размера. Здесь мы используем библиотеку Python Pillow для ее обработки.

Затем, после предварительной обработки данных, данные изображения сохраняются в массиве NumPy в числовом виде. И здесь мы получаем доступ к файлу, следуя пути к файлу, чтобы получить метку изображения.

# image manipulation
from PIL import Image

# label the data
def label(path):
    img, labels = [], []
    
    l1 = os.listdir(path)
    for i in l1: # in order to get the class (label)
        if i != '.DS_Store':
            l2 = os.listdir(path+'/'+i)
            for j in l2:
                image = Image.open(path+'/'+i+'/'+j)
                image.convert('L') # RGB to Gray level
                image = image.resize(size = (28,28)) # Normalizing
                img.append(np.array(image).flatten()) # Store in numerical way
                labels.append(i)
    return np.array(img), labels

Разделить набор данных

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

# Split Dataset
X_train, y_train = label("Vegetable Images/train")
X_test, y_test = label("Vegetable Images/test")
X_val, y_val = label("Vegetable Images/validation")

Метка хранится в строке, и нам нужно преобразовать ее в число:

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit(y_train)
y_train = le.fit_transform(y_train)

le.fit(y_test)
y_test = le.fit_transform(y_test)

le.fit(y_val)
y_val = le.fit_transform(y_val)

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

Построить модель

Теперь все было готово. Мы собираемся внедрить модель обучения. Здесь TensorFlow используется для построения нейронной сети.

# Build the model
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

model =Sequential([
    tf.keras.Input(shape=(X_train.shape[1]),),
    Dense(512, activation = 'relu', name = "L1"),
    Dense(256, activation = 'relu', name = "L2"),
    Dense(128, activation = 'relu', name = "L3"),
    Dense(64, activation = 'relu', name = "L4"), 
    Dense(15, activation = 'linear', name = "L5")   
], name = 'Vege Recognition')
model.summary()

Входная форма — это количество объектов для ввода (не записей!). И Dense представляет каждый слой в модели NN. Число обозначает количество нейронов в каждом слое. И выходной слой всегда 15, так как мы хотим классифицировать их по 15 категориям. Так как это мультиклассовые задачи, мы используем активацию Softmax в выходных слоях. Результатом слоя softmax является набор вероятностей отнесения примера к каждому классу. Затем он выбирает класс с наибольшей вероятностью. И выход - предсказание примеров.

Количество слоев и нейронов не уникально. Вы можете попробовать с другими значениями. И отрегулируйте параметры в соответствии с точностью обучения и проверки.

Ниже приведено краткое описание модели:

Оптимизация модели и перекрестная проверка

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

model.compile(
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), #softmax layer
    optimizer=tf.keras.optimizers.Adam(0.001), # Adam optimizer
    metrics=['acc'])
history = model.fit(X_train, y_train, epochs = 100, validation_data = (X_val, y_val)) 

Затем мы наносим точность и потери в каждую эпоху.

import matplotlib.pyplot as plt

plt.subplot(2,1,1)
plt.title("Accuracy")
plt.plot(history.history["acc"], color="blue", label="train")
plt.plot(history.history["val_acc"], color="red", label="validation")
plt.legend(loc="best")

plt.subplot(2,1,2)
plt.title("Loss/Contrastive Loss")
plt.plot(history.history["loss"], color="blue", label="train")
plt.plot(history.history["val_loss"], color="red", label="validation")
plt.legend(loc="best")

plt.tight_layout()
plt.show()

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

Тестовая модель

Затем мы тестируем модель, делая прогноз для тестового набора. Поскольку существует 3000 тестовых примеров, завершение всего процесса может занять больше времени.

# Test the model
y_pred = []
for i in range(X_test.shape[0]):
    v = X_test[i]
    # fit the num of features, remember your input shape!
    prediction = model.predict(v.reshape(1,2352)) 
    # calculate the probability for each class
    p = tf.nn.softmax(prediction) 
    # Choose the class with highest probability
    y_hat = np.argmax(p)
    y_pred.append(y_hat)
y_pred = np.array(y_pred)

Оценить модель

Наконец, мы оцениваем модель, вычисляя точность, точность/отзыв, F1-оценку и отображая матрицу путаницы.

# Model Evaluation
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, ConfusionMatrixDisplay
acc = accuracy_score(y_pred,y_test) # accuracy
cm = confusion_matrix(y_test,y_pred) # Confusion Matrix
cm_display = ConfusionMatrixDisplay(confusion_matrix = cm)
# Demo the evaluation
print('Accuracy:',acc)
print(classification_report(y_test,y_pred)) # Precision/Recall/F1-Score
cm_display.plot()
plt.show()

Точность модели составляет 85,8%, что можно считать идеальной моделью.

Вот и все о сегодняшней статье, буду рад, если моя статья вам понравится! И я также буду рад любым комментариям/обсуждениям о других превосходных алгоритмах для решения этой проблемы, поскольку я также изучаю область науки о данных! Спасибо за ваше чтение! Весь код доступен в моем GitHub.