【问题标题】:expected ndim = 4 found ndim = 5 and other errors - Keras - GTSRB dataset预期 ndim = 4 发现 ndim = 5 和其他错误 - Keras - GTSRB 数据集
【发布时间】:2018-10-24 20:03:22
【问题描述】:

我正在尝试基于 GTSRB 数据集(下面给出的链接)制作一个 CNN 模型,但我遇到了以下错误:

当我设置 input_shape = input_shape=(3, IMG_SIZE, IMG_SIZE) 时,我收到此错误:

ValueError:检查输入时出错:预期 conv2d_34_input 到 有 4 个维度,但得到了形状为 (9030, 1) 的数组

当我研究这个问题时,我发现一种解决方案可能是将 batch_size 作为参数传递,当我尝试这样做时,我得到了这个错误:

ValueError:输入 0 与层 conv2d_40 不兼容:预期 ndim=4,发现 ndim=5

当我尝试重塑 training_images 时,出现此错误:

ValueError: 无法将大小为 9030 的数组重新整形为 (48,48,3)

代码片段: 加载训练数据集:

import csv

# Training dataset
def readTrafficSignsTrain(rootpath):
    '''Reads traffic sign data for German Traffic Sign Recognition Benchmark.

    Arguments: path to the traffic sign data, for example './GTSRB/Training'
    Returns:   list of images, list of corresponding labels'''
    images = [] # images
    labels = [] # corresponding labels

    # loop over all 42 classes
    for c in range(0,43):
#         prefix = rootpath + '/' + format(c, '05d') + '/' # subdirectory for class
#         annFile = open(prefix + 'GT-'+ format(c, '05d') + '.csv') # annotations file
        prefix = rootpath + '/00000' + '/'
        annFile = open(prefix + 'GT-00000' + '.csv')
        annReader = csv.reader(annFile, delimiter=';') # csv parser for annotations file
        next(annReader, None) # skip header

        # loop over all images in current annotations file
        for row in annReader:
            images.append(plt.imread(prefix + row[0])) # the 1st column is the filename
            labels.append(row[7]) # the 8th column is the label

        annFile.close()
    return images, labels

training_images, training_labels = readTrafficSignsTrain('./GTSRB/Training')

这里有个问题,比如图片的形状不一样

print(len(training_images))
print(len(training_labels))
print()
print(training_images[0].shape)
print(training_images[20].shape)
print(training_images[200].shape)
print(training_images[2000].shape)

输出

9030 9030

(30, 29, 3) (54, 57, 3) (69, 63, 3) (52, 51, 3)

层设置(从下面链接的 Keras 文档复制和粘贴):

IMG_SIZE = 48
NUM_CLASSES = 43
K.set_image_data_format('channels_first')

batch_size = 32

def cnn_model():
    model = Sequential()

    model.add(Conv2D(32, (3, 3), padding='same',
                     input_shape=(3, IMG_SIZE, IMG_SIZE),
                     activation='relu',
                     data_format="channels_first"))
    model.add(Conv2D(32, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_first"))
    model.add(Dropout(0.2))

    model.add(Conv2D(64, (3, 3), padding='same',
                     activation='relu'))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.2))

    model.add(Conv2D(128, (3, 3), padding='same',
                     activation='relu'))
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.2))

    model.add(Flatten())
    model.add(Dense(512, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(NUM_CLASSES, activation='softmax'))
    return model

model = cnn_model()

训练模型(暂时只是model.fit

import numpy

trim = numpy.array(training_images)
trlb = numpy.array(training_labels)

print(training_images[0].shape)
print(trim.shape)

trim - trim.reshape(48, 48, 3)

model.fit(trim, trlb, epochs = 30, batch_size = 32)

输出

ValueError: 无法将大小为 9030 的数组重新整形为 (48,48,3)

当我移除重塑

ValueError:检查输入时出错:预期 conv2d_41_input 到 有 4 个维度,但得到了形状为 (9030, 1) 的数组

当我改用这个时

model.fit(training_images, training_labels, epochs = 30, batch_size = 32)

输出

> ValueError: Error when checking model input: the list of Numpy arrays
> that you are passing to your model is not the size the model expected.
> Expected to see 1 array(s), but instead got the following list of 9030
> arrays: [array([[[ 75,  78,  80],
>             [ 74,  76,  78],
>             [ 86,  87,  84],
>             ...,
>             [ 68,  75,  75],
>             [ 65,  69,  68],
>             [ 66,  67,  66]],
>     
>            [[ 83,  84,  86],
>             [...

所以,如果我这样做(不确定为什么)

for i in range(len(training_images)):
    model.fit(training_images[i], training_labels[i], epochs = 30, batch_size = 32)

我明白了

ValueError:检查输入时出错:预期 conv2d_41_input 到 有 4 个维度,但得到了形状为 (30, 29, 3) 的数组

那就是

input_shape=(3, IMG_SIZE, IMG_SIZE)

如果我做

input_shape=(batch_size, 3, IMG_SIZE, IMG_SIZE)

我明白了

ValueError:输入 0 与层 conv2d_47 不兼容:预期 ndim=4,发现 ndim=5

model.summary() 的输出

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_34 (Conv2D)           (None, 32, 48, 48)        896       
_________________________________________________________________
conv2d_35 (Conv2D)           (None, 32, 46, 46)        9248      
_________________________________________________________________
max_pooling2d_14 (MaxPooling (None, 32, 23, 23)        0         
_________________________________________________________________
dropout_14 (Dropout)         (None, 32, 23, 23)        0         
_________________________________________________________________
conv2d_36 (Conv2D)           (None, 64, 23, 23)        18496     
_________________________________________________________________
conv2d_37 (Conv2D)           (None, 64, 21, 21)        36928     
_________________________________________________________________
max_pooling2d_15 (MaxPooling (None, 64, 10, 10)        0         
_________________________________________________________________
dropout_15 (Dropout)         (None, 64, 10, 10)        0         
_________________________________________________________________
conv2d_38 (Conv2D)           (None, 128, 10, 10)       73856     
_________________________________________________________________
conv2d_39 (Conv2D)           (None, 128, 8, 8)         147584    
_________________________________________________________________
max_pooling2d_16 (MaxPooling (None, 128, 4, 4)         0         
_________________________________________________________________
dropout_16 (Dropout)         (None, 128, 4, 4)         0         
_________________________________________________________________
flatten_4 (Flatten)          (None, 2048)              0         
_________________________________________________________________
dense_10 (Dense)             (None, 512)               1049088   
_________________________________________________________________
dropout_17 (Dropout)         (None, 512)               0         
_________________________________________________________________
dense_11 (Dense)             (None, 43)                22059     
=================================================================
Total params: 1,358,155
Trainable params: 1,358,155
Non-trainable params: 0
_________________________________________________________________
None

如果有人能提供帮助,将不胜感激。

链接 GTSRB:http://benchmark.ini.rub.de/?section=gtsrb&subsection=news 我从 Keras 文档中获取模型:https://chsasank.github.io/keras-tutorial.html

github上完整项目的链接:https://github.com/PavlySz/TSR-Project

谢谢!

【问题讨论】:

    标签: python arrays tensorflow keras training-data


    【解决方案1】:

    您不能将 np.array 重塑为尺寸不允许的东西。这是你可以做的事情

    import numpy as np 
    img_arr = np.array([np.ones((30, 29, 3)), 
                        np.ones((54, 57, 3)), 
                        np.ones((69, 63, 3)), 
                        np.ones((52, 51, 3))])
    
    print(img_arr.shape)
    
    import cv2
    img_arr_conv = np.array([cv2.resize(img, dsize=(48, 48)) for img in img_arr])
    print(img_arr_conv.shape)
    
    >>>(4,)
    >>>(4, 48, 48, 3)
    

    你得到了ValueError: cannot reshape array of size 9030 into shape (48,48,3),因为如果元素的大小都不同,numpy 无法推断数组的维度,并且它无法重塑维度不允许的数组。 ValueError: Error when checking input: expected conv2d_41_input to have 4 dimensions, but got array with shape (9030, 1) 也是如此。 Numpy 只知道数组中有 9030 个元素。它不能做更多的事情,因为元素的所有维度都是不同的。
    示例

    img_arr_bad = np.array([np.ones((30, 29, 3)), 
                            np.ones((54, 57, 3)), 
                            np.ones((69, 63, 3)), 
                            np.ones((52, 51, 3))])
    
    img_arr_good = np.array([np.ones((48, 48, 3)), 
                             np.ones((48, 48, 3)), 
                             np.ones((48, 48, 3)), 
                             np.ones((48, 48, 3))])
    
    print(img_arr_bad.shape)
    print(img_arr_good.shape)
    
    >>>(4,)
    >>>(4, 48, 48, 3)
    

    希望对你有帮助

    【讨论】:

    • 那么,一个可能的解决方法是将 img_width 和 img_height 传递给 input_shape?因此 input_shape(3, img_width, img_height)
    • 不,我是说将您的图像调整为相同的img_arr_conv = np.array([cv2.resize(img, dsize=(48, 48)) for img in training_images])
    • 会尝试的。谢谢。
    • 非常感谢您,好先生。你不知道我在这个错误上浪费了多少时间。我想我只是在装傻。再次感谢您!
    猜你喜欢
    • 1970-01-01
    • 2021-04-08
    • 2019-06-22
    • 2022-01-20
    • 2021-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多