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

ТИНГКАТКАН КЕМАНДИРЯН ПЕТАНИ МЕЛАЛУ СИСТЕМ ИНФОРМАЗИ РУАНГ ЛАЯНАН ДОКТЕР ТАНАМАН (СИ РУТЭ АМАН) | Динас Перкебунан Провинси Джава Барат (jabarprov.go.id)

«Простая классификация изображений с помощью ResNet-50 | Нина Даниэльсен | Середина"

«Учебное пособие - Классификатор изображений с использованием модели глубокого обучения Resnet50 (Python Flask в Azure) | Венкатеш Нараянан | Середина"