numpy Keras training ValueError:用序列设置数组元素,请求的数组在3维之后具有不均匀的形状

thigvfpy  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(83)

我正在尝试使用KerasTensorflow在大约21,000张图像的数据集上训练一个简单的二进制分类模型。但是当我运行训练代码时,它会抛出这个错误:

Traceback (most recent call last):
  File "train.py", line 83, in <module>
    training_images = np.array([i[0] for i in training_data])
ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 3 dimensions. The detected shape was (21527, 300, 300) + inhomogeneous part.

我以前使用过这个数据集和训练代码,所以现在不确定是什么导致了这个问题。什么是问题?如何解决这一问题?
下面是我的简单训练代码,它加载数据集并尝试训练/拟合模型:

from keras.models import Sequential, load_model
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import BatchNormalization
from PIL import Image
from random import shuffle, choice
import numpy as np
import os
from keras.callbacks import ModelCheckpoint
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential, Model
from sklearn.model_selection import train_test_split
from keras import optimizers

IMAGE_SIZE = 300
epochs_num = 50
batch_size = 64
IMAGE_DIRECTORY = './data'
retrain_from_prior_model=True

def label_img(name):
    if name == 'object': return np.array([1, 0])
    elif name == 'none' : return np.array([0, 1])

def load_data():
    print("Loading images...")
    train_data = []
    directories = next(os.walk(IMAGE_DIRECTORY))[1]

    for dirname in directories:
        print("Loading {0}".format(dirname))
        file_names = next(os.walk(os.path.join(IMAGE_DIRECTORY, dirname)))[2]
        for i in range(len(file_names)):
            image_name = choice(file_names)
            image_path = os.path.join(IMAGE_DIRECTORY, dirname, image_name)
            label = label_img(dirname)
            if "DS_Store" not in image_path:
                try:
                    img = Image.open(image_path)
                    img = img.resize((IMAGE_SIZE, IMAGE_SIZE), Image.LANCZOS)
                    train_data.append([np.array(img), label])
                except Exception as e:
                    print(f"Error processing image: {image_path}")
                    print(f"Error message: {str(e)}")
                    continue  # Skip this image and continue with the next one

    shuffle(train_data)
    return train_data

def create_model():
    channels = 3
    model = Sequential()
    #change first one to 64
    model.add(Conv2D(32, kernel_size = (5, 5), activation='relu', input_shape=(IMAGE_SIZE, IMAGE_SIZE, channels)))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(BatchNormalization())
    model.add(Conv2D(64, kernel_size=(3,3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(BatchNormalization())
    model.add(Conv2D(128, kernel_size=(3,3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(BatchNormalization())
    model.add(Conv2D(256, kernel_size=(3,3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(BatchNormalization())
    
    model.add(Conv2D(64, kernel_size=(3,3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(BatchNormalization())
    model.add(Dropout(0.2))
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.2))
    model.add(Dense(128, activation='relu'))
    model.add(Dense(2, activation = 'softmax'))
    
    return model
  
training_data = load_data()

training_images = np.array([i[0] for i in training_data])

training_labels = np.array([i[1] for i in training_data])

print(str(len(training_images)))
# Split the data
training_images, validation_images, training_labels, validation_labels = train_test_split(training_images, training_labels, test_size=0.2, shuffle= True)
print(str(len(training_images)))

print('creating model')
#========================
if retrain_from_prior_model == False:
    model = create_model()
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    print('training model...model.count_params: '+str(model.count_params()) + '...model.count_layers: '+ str(len(model.layers)))
else:
    model = load_model("model_0.989.h5")
    model.compile(loss='binary_crossentropy', optimizer= optimizers.Adam(learning_rate=0.0001), metrics=['accuracy'])

filepath="./checkpoints/model_{epoch:03d}_{accuracy:.4f}_{val_accuracy:.4f}_{val_loss:.7f}.h5"
checkpoint = ModelCheckpoint(filepath, monitor=["accuracy"], verbose=1, mode='max', save_weights_only=False)
callbacks_list = [checkpoint]

# if you want data augmentation: rotation_range=20, width_shift_range=0.2, height_shift_range=0.2, brightness_range=[0.9,1.1]
datagen = ImageDataGenerator(zoom_range=0.2, horizontal_flip=True)
datagen.fit(training_images)
train_gen=datagen.flow(training_images, training_labels, batch_size=batch_size)
#validation
val_datagen = ImageDataGenerator(horizontal_flip=True)
val_datagen.fit(training_images)
val_gen=datagen.flow(validation_images, validation_labels, batch_size=batch_size)

model.fit(train_gen, validation_data=val_gen, epochs=epochs_num, verbose=1, callbacks=callbacks_list)

print('Training finished. Model saved.')
jjhzyzn0

jjhzyzn01#

问题是,显然有一些灰度图像(1通道)在我的数据集,导致错误。所以我在load_data()中添加了这行代码,以确保只添加3通道图像,并解决了这个问题:

if img.mode != 'RGB':
    continue  # Skip grayscale images if colored flag is True

相关问题