‘Входные данные в `NumpyArrayIterator` должны иметь ранг 4. Вы передали массив с формой’, (120000, 0)

#tensorflow #machine-learning #keras #deep-learning #conv-neural-network

#tensorflow #машинное обучение #keras #глубокое обучение #conv-нейронная сеть

Вопрос:

Я создал систему классификации изображений, которая обнаруживает болезни листьев растений, используя набор данных PlantVillage. Я создал весь процесс, начиная с предварительной обработки и заканчивая построением модели, но когда я пытаюсь запустить программу, появляется вышеуказанная ошибка. Теперь я много чего перепробовал и, честно говоря, я не хочу связываться с набором данных в colab, так что кто-нибудь, пожалуйста, помогите мне с этим, я буду очень благодарен. Это часть предварительной обработки моего кода.

 import numpy as np
import pickle
import cv2
import os
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow import keras
from os import listdir
from sklearn.preprocessing import LabelBinarizer
from keras.models import Sequential
from keras.layers.normalization import BatchNormalization
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Activation, Flatten, Dropout, Dense
from keras import backend as K
from keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
from keras.preprocessing import image
from keras.preprocessing.image import img_to_array
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.model_selection import train_test_split

from google.colab import drive
drive.mount('/content/drive')

#Resize the image to match the input shape of the layer
default_image_size = tuple((256, 256))
image_size = 0

#dataset directory
directory_root = '/content/drive/MyDrive/proj/PlantVillage'

width = 256
height = 256
depth = 3

def convert_image_to_array(image_dir):
    #loads an image from the directory if the image exists
    image = cv2.imread(image_dir)

    if image is not None:
        #changes the dimensions of the image, width or height or both and also maintains the original aspect ratio in the resized version
        image = cv2.resize(image, default_image_size)
        return img_to_array(image)
    else:
        #if the image does not exist, it returns an empty array
        return np.array([])

image_list, label_list = [], []

print("[INFO] Loading Images...")
root_dir = listdir(directory_root)

for plant_folder in root_dir:
    plant_disease_folderlist = listdir(f"{directory_root}/{plant_folder}")

    for plant_disease_folder in plant_disease_folderlist:
        print(f"[INFO] Processing {plant_disease_folder} ...")
        plant_disease_image_list = listdir(f"{directory_root}/{plant_folder}/")

        for image in plant_disease_image_list[:200]:
            image_directory = f"{directory_root}/{plant_folder}/{plant_disease_folder}/{image}"
            if image_directory.endswith(".jpg") == True or image_directory.endswith(".JPG") == True:
                image_list.append(convert_image_to_array(image_directory))
                label_list.append(plant_disease_folder)

print("[INFO] Image Loading Complete!")  

#transforms the resized image data into numpy array
np_image_list = np.array(image_list, dtype = np.float16) / 255.0

#checks for the number of images loaded for training
image_size = len(image_list)
print(f"Total number of images: {image_size}")

#each class or label is assigned a unique value for training
label_binarizer = LabelBinarizer()
image_labels = label_binarizer.fit_transform(label_list)

#dumping the labels in the pkl file so it can be used for predictions 
pickle.dump(label_binarizer,open('plantlabel.pkl', 'wb'))
n_classes = len(label_binarizer.classes_)

print("Total number of classes: ", n_classes)
print("Labels: ", label_binarizer.classes_)

print("[INFO] Splitting Data Into Training and Testing Set...")
#splitting the data with a 0.2 split ratio
x_train, x_test, y_train, y_test = train_test_split(np_image_list, image_labels, test_size=0.2, random_state = 42)

#data augmentation is used to generate more images in the dataset. The different operations are applied on the image to diversify the dataset so it performs well with unseen images
#only the object is created here, this will be used later in the training
aug = ImageDataGenerator(rotation_range=25, 
                         width_shift_range=0.1,
                         height_shift_range=0.1, 
                         shear_range=0.2, 
                         zoom_range=0.2,
                         horizontal_flip=True, 
                         fill_mode="nearest")
 

Теперь я построил модель с помощью keras и добавил слои, все было распознано правильно до этой части.

 EPOCHS = 10
LR = 1e-3
BATCH_SIZE = 32
WIDTH = 256
HEIGHT = 256
DEPTH = 3

#creating the model
inputShape = (HEIGHT, WIDTH, DEPTH)
chanDim = -1

if K.image_data_format() == "channels_first":
    inputShape = (DEPTH, HEIGHT, WIDTH)
    chanDim = -1

model = Sequential()
model.add(Conv2D(32, (3, 3), padding = "same", input_shape = inputShape))
model.add(Activation("relu"))
model.add(BatchNormalization(axis = chanDim))
model.add(MaxPooling2D(pool_size = (3, 3)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), padding = "same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis = chanDim))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(128, (3, 3), padding = "same"))
model.add(Activation("relu"))
model.add(BatchNormalization(axis = chanDim))
model.add(MaxPooling2D(pool_size = (2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation("relu"))
model.add(BatchNormalization())
model.add(Dropout(0.5))

model.add(Dense(n_classes))
model.add(Activation("softmax"))

model.summary()

opt = Adam(lr = LR, decay = LR/EPOCHS)
model.compile(loss="binary_crossentropy", optimizer=opt,metrics=["accuracy"])

print("[INFO] Training Begins...")
history = model.fit_generator(
    aug.flow(x_train, y_train, batch_size=BATCH_SIZE),
    validation_data=(x_test, y_test),
    steps_per_epoch=len(x_train) // BATCH_SIZE,
    epochs=EPOCHS, verbose=1
    )
print("[INFO] Training Complete...")
 

Здесь, в aug.flow(x_train, batch_size=BATCH_SIZE,...) части, возникает ошибка. Ошибка заключается в следующем.

 ValueError                                Traceback (most recent call last)
<ipython-input-13-a2fb6e262c72> in <module>()
      4 print("[INFO] Training Begins...")
      5 history = model.fit_generator(
----> 6     aug.flow(x_train, y_train, batch_size=BATCH_SIZE),
      7     validation_data=(x_test, y_test),
      8     steps_per_epoch=len(x_train) // BATCH_SIZE,

2 frames
/usr/local/lib/python3.6/dist-packages/keras_preprocessing/image/numpy_array_iterator.py in __init__(self, x, y, image_data_generator, batch_size, shuffle, sample_weight, seed, data_format, save_to_dir, save_prefix, save_format, subset, dtype)
    124             raise ValueError('Input data in `NumpyArrayIterator` '
    125                              'should have rank 4. You passed an array '
--> 126                              'with shape', self.x.shape)
    127         channels_axis = 3 if data_format == 'channels_last' else 1
    128         if self.x.shape[channels_axis] not in {1, 3, 4}:

ValueError: ('Input data in `NumpyArrayIterator` should have rank 4. You passed an array with shape', (120000, 0))
 

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

Комментарии:

1. Можете ли вы сделать next(aug) , чтобы получить образец из генератора изображений? Пожалуйста, добавьте выходные данные или их формы в вопрос.