Исходя из опыта выращивания растений, который невозможно отделить от угрозы нападений вредителей и болезней, некоторые исследователи обнаружили тот факт, что необнаруженные и неконтролируемые нападения вредителей снижают урожайность растений на 30–80% и могут вызвать неурожай. Часто мелкие фермеры имеют ограниченные знания о типах болезней и вредителей растений. В 2016 году только 40% фермеров в Западной Яве, Индонезия, распознали тип атаки вредителей и болезней.
Поэтому, чтобы помочь мелким фермерам в диагностике болезней их сельскохозяйственных культур, я попытался создать модель, которая может обнаруживать болезни у растений. Изображения листьев будут классифицированы с использованием модели ResNet50, чтобы определить, является ли растение здоровым или больным.
На этот раз я расскажу, как построить модель системы обнаружения болезней растений с использованием модели ResNet50.
Что такое ResNet50?
ResNet - это краткое название остаточной сети, которая поддерживает остаточное обучение. Resnet50 означает остаточную сеть с 50 уровнями, предварительно обученную версию этой сети, обученную более чем на миллионе изображений из базы данных ImageNet, и она используется в качестве основы для многих задач компьютерного зрения. Эта модель стала победителем конкурса ImageNet в 2015 году.
Почему мы используем модель Resnet50?
Мы пробовали несколько моделей, таких как CNN, InceptionV3, MobileNetV2, GoogLeNet и т. Д. Однако точность ResNet50 выше, чем у других моделей. Несколько журналов / статей доказали, что Resnet50 - лучшая модель для идентификации болезней растений, и эта модель Resnet50 включена в 4 лучших предварительно обученных моделей для классификации изображений. Помимо этих трех вещей, модель ResNet50 представляет собой модель обучения с переносом, что означает, что ResNet50 не требует тяжелых вычислений, поскольку она была обучена на больших данных, миллионе изображений из базы данных ImageNet.
Давайте начнем!
Шаг 1. Импорт необходимых библиотек
Первый шаг - импортировать необходимые библиотеки, необходимые для классификации изображений. В этом случае вам нужно использовать numpy, pandas, tensorflow, keras, scikit learn и другие.
#Copy the Code HERE! # Import Packages import numpy as np import pandas as pd import matplotlib.pyplot as plt import tensorflow as tf import tensorflow_hub as hub from IPython.display import Image from keras.preprocessing import image from sklearn.model_selection import train_test_split import os import zipfile import random import datetime import shutil from google.colab import files
Шаг 2. Прочтите и разархивируйте файл.
Данные, которые мы используем, являются вторичными данными, полученными с сайта Kaggle. У нас есть Набор данных риса и Набор данных кукурузы. Чтобы загрузить файл набора данных kaggle в Google Colab, полезно использовать команду! Kaggle. Затем он будет добавлен в ваше хранилище файлов в colab, и оттуда вы можете создать путь к изображению или набору данных, которые хотите использовать.
#Copy the Code HERE! # input kaggle.json file !pip install -q kaggle !mkdir -p ~/.kaggle !cp kaggle.json ~/.kaggle/ !ls ~/.kaggle !chmod 600 /root/.kaggle/kaggle.json # import data rice !kaggle datasets download -d minhhuy2810/rice-diseases-image-dataset # import data corn !kaggle datasets download -d smaranjitghose/corn-or-maize-leaf-disease-dataset
Шаг 3. Создайте фрейм данных
Создайте путь к изображению или набору данных, которые вы хотите использовать, сформируйте его в фрейм данных и разделите на набор для обучения и проверки.
#Copy the Code HERE! # make augmentation directory for the results !mkdir '/content/LabelledRice/Labelled/augmented' # list of image path and label for dataframe IMAGE_PATH = [] LABEL = [] # RICE rice_train_list = ['/content/LabelledRice/Labelled/BrownSpot/', '/content/LabelledRice/Labelled/Healthy/', '/content/LabelledRice/Labelled/Hispa/', '/content/LabelledRice/Labelled/LeafBlast/'] for index in range(len(rice_train_list)): for image in os.listdir(rice_train_list[index]): IMAGE_PATH.append(os.path.join(rice_train_list[index], image)) # Rice label for i in range(523): LABEL.append("Padi: Bercak Daun Coklat") for i in range(1488): LABEL.append("Padi: Sehat") for i in range(565): LABEL.append("Padi: Hispa") for i in range(779): LABEL.append("Padi: Blas Daun") # CORN corn_train_list = ['/content/data/Blight/', '/content/data/Common_Rust/', '/content/data/Gray_Leaf_Spot/', '/content/data/Healthy/'] for index in range(len(corn_train_list)): for image in os.listdir(corn_train_list[index]): IMAGE_PATH.append(os.path.join(corn_train_list[index], image)) # Corn label for i in range(1146): LABEL.append("Jagung: Hawar Daun") for i in range(1306): LABEL.append("Jagung: Karat Daun") for i in range(574): LABEL.append("Jagung: Bercak Abu-Abu Daun") for i in range(1162): LABEL.append("Jagung: Sehat")
#Copy the Code HERE! # Create dataframe database = pd.DataFrame(IMAGE_PATH, columns=['path']) database['label'] = LABEL database.head() # Split train & validation set X_train, X_val, y_train, y_val = train_test_split(database['path'], database['label'], test_size=0.1)
Шаг 4. Превратите метку в логический массив
Мы собираемся создать модель, которая генерирует коэффициенты для каждой категории, поэтому нам нужно преобразовать метки в логический массив.
#Copy the Code HERE! # unique labels unique_label = np.array(database['label'].unique()) unique_label # num unique labels num_unique_label = len(unique_label) num_unique_label # Encoding labels # Turns into boolean array for all index # train boolean_array_train = [i == unique_label for i in y_train] # validation boolean_array_val = [i == unique_label for i in y_val] # check boolean array for data in index 0 boolean_array_train[0]
Шаг 5. Превратите данные в тензорный набор
Преобразуйте набор данных в тензор, чтобы избежать ошибок значений несовместимости форм, ошибок логитов и ошибок меток.
#Copy the Code HERE! # Turn into tensor set # train train_set = tf.data.Dataset.from_tensor_slices(( tf.constant(X_train), tf.constant(boolean_array_train) )) # validation val_set = tf.data.Dataset.from_tensor_slices(( tf.constant(X_val), tf.constant(boolean_array_val) ))
После того, как мы создали тензорный набор для набора данных для обучения и проверки, мы перемешиваем обучающий набор, чтобы помочь обучению быстро сходиться, предотвратить любое смещение во время обучения и предотвратить обучение модели в соответствии с порядком обучения.
#Copy the Code HERE! # shuffle train set BUFFER_SIZE = len(train_set) train_set = train_set.shuffle(BUFFER_SIZE)
Шаг 6: предварительная обработка изображения
Превратите изображение в числа, нормализуйте значения пикселей и измените размер изображения.
#Copy the Code HERE! # our desired image size IMAGE_SIZE = 224 # read, turn image into number, normalize, resize def preprocess_image(image_path, labels=None): # read image image = tf.io.read_file(image_path) # turn jpeg into numbers image = tf.image.decode_jpeg(image, channels=3) # scaling / normalize (0,255) menjadi (0,1) image = tf.image.convert_image_dtype(image, dtype=tf.float32) # resize to (224,224) image = tf.image.resize(image, size=[IMAGE_SIZE, IMAGE_SIZE]) # return return image, labels # apply train_set = train_set.map(preprocess_image) val_set = val_set.map(preprocess_image)
После этого мы определяем размер партии и выполняем пакетную обработку. Размер пакета - это термин, используемый в машинном обучении и относящийся к количеству обучающих примеров, используемых за одну итерацию.
#Copy the Code HERE! # batch size BATCH_SIZE = 32 # batching train & validation set train_set = train_set.batch(BATCH_SIZE) val_set = val_set.batch(BATCH_SIZE) # check element spec train_set.element_spec
Шаг 7. Покажите изображения (необязательно)
Показывать изображения и этикетку в пакете (32 изображения)
#Copy the Code HERE! def show_images_in_a_batch(images, labels): # create a figure plt.figure(figsize=(15, 15)) # for each image in one batch (32 images) for i in range(32): # Create subplots (8 rows, 5 columns) ax = plt.subplot(8, 5, i+1) # i = index # Show the image plt.imshow(images[i]) # Add the image label as the title plt.title(unique_label[np.argmax(labels[i])]) # Turn the grid lines off plt.axis("off") # take one random batch from training set sample_train_images, sample_train_labels = next(iter(train_set)) # show show_images_in_a_batch(sample_train_images, sample_train_labels)
Шаг 8: Постройте модель трансферного обучения
Постройте модель трансферного обучения с ResNet50. Сначала мы создаем модель, затем компилируем ее, создаем обратный вызов для ранней остановки, который отслеживает потерю проверки, чтобы предотвратить переобучение, и обучаем модель с 50 эпохами.
#Copy the Code HERE! # 1. Create Model model = tf.keras.Sequential([ # transfer learning model hub.KerasLayer(“https://tfhub.dev/tensorflow/resnet_50/feature_vector/1”), # output layer tf.keras.layers.Dense(units=num_unique_label, activation=’softmax’)]) # 2. Compile Model model.compile(optimizer=’adam’, loss=’categorical_crossentropy’, metrics=[‘accuracy’]) # build the model and pass the input shape model.build(input_shape = [None, 224, 224, 3]) # 3. Create Callback # EARLYSTOPPING CALLBACK, monitor the val loss (prevent overfitting) early_stopping = tf.keras.callbacks.EarlyStopping(monitor=’val_loss’, patience=3) # 4. Training Model history_train = model.fit(train_set, epochs=50, validation_data = val_set, callbacks=[early_stopping])
Из истории обучения мы знаем, что обучение модели прекращается после 9-й эпохи. это происходит потому, что мы используем обратный вызов ранней остановки, который предотвращает переобучение. Модель имеет точность обучения 0,8612 и точность проверки 0,7772. То есть из 10 изображений модель может правильно предсказать 8–9 изображений.
Шаг 9: точность и потеря
Затем мы смотрим на модель точности и потерь.
#Copy the Code HERE! # train acc = history_train.history['accuracy'] loss = history_train.history['loss'] # validation val_acc = history_train.history['val_accuracy'] val_loss = history_train.history['val_loss'] # range number of epochs epochs = range(len(acc)) # plot training and validation accuracy per epoch plt.plot(epochs, acc) plt.plot(epochs, val_acc) plt.title('Training and validation accuracy') plt.figure() # plot training and validation loss per epoch plt.plot(epochs, loss) plt.plot(epochs, val_loss) plt.title('Training and validation loss') plt.legend(['train', 'val'])
Шаг 10: тестирование
Посмотрев на точность и потерю модели, если она чувствует, что модель достаточно хороша, переходите к последнему этапу; тестирование. Здесь мы пытаемся предоставить изображение, которого модель никогда не видела, и пытаемся его предсказать.
#Copy the Code HERE! # upload files uploaded=files.upload() filename = [] test_images = [] for fn in uploaded.keys(): filename.append(fn) path='/content/' + fn test_images.append(path) # turn into set test_set = tf.data.Dataset.from_tensor_slices(( tf.constant(test_images) )) # preprocess test_set = test_set.map(preprocess_image) # batching test_set = test_set.batch(batch_size=32) # predict test_predictions = model.predict(test_set) label_prediction = [] for i in range(len(test_predictions)): label_prediction.append(unique_label[np.argmax(test_prediction[i])]) # show prediction results for i in range(len(test_images)): print(label_prediction[i]) pil_img = Image(filename=test_images[i], width=150, height=150) display(pill_img)
Оказывается, модель дает правильные прогнозы для тестирования этих четырех изображений.
ЗАКЛЮЧЕНИЕ
Как видите, модель ResNet50 позволяет легко классифицировать болезни растений. Хотя в настоящее время мы обнаруживаем только рис и кукурузу, эту модель можно расширить и обнаружить больше культур. В рамках этого проекта мы надеемся, что фермеры смогут использовать наш MVP и легко обнаруживать болезни на своих растениях. Вы можете легко попробовать этот код, изменить архитектуру модели, выполнить некоторую настройку или попробовать модель ResNet50 с другими наборами данных.
Я очень открыт для вопросов и обсуждений, если у вас есть вопросы, просто свяжитесь со мной через мой LinkedIn. Спасибо и продолжайте учиться!
Список литературы:
Так Мемпан Обат, Хама Улат Серанг Джагунг Петани Давунг (bloktuban.com)
«Простая классификация изображений с помощью ResNet-50 | Нина Даниэльсен | Середина"
«Учебное пособие - Классификатор изображений с использованием модели глубокого обучения Resnet50 (Python Flask в Azure) | Венкатеш Нараянан | Середина"