Keras 训练 ValueError:用序列设置数组元素。请求的数组在 3 维后具有不均匀的形状

问题描述 投票:0回答:1

我正在尝试在大约 21,000 张图像的数据集上使用

Keras
Tensorflow
训练一个简单的二元分类模型。但是当我运行训练代码时,它会抛出此错误:

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.')
python numpy tensorflow keras deep-learning
1个回答
0
投票

问题是,显然我的数据集中有一些灰度图像(1 个通道)导致了错误。所以我在

load_data()
中添加了这一行,以确保只添加 3 通道图像,并解决了问题:

if img.mode != 'RGB':
    continue  # Skip grayscale images if colored flag is True
© www.soinside.com 2019 - 2024. All rights reserved.