如何修复VGG16 ValueError:无法将输入数组从形状(20,4)广播到形状(20)?

时间:2019-04-18 17:07:15

标签: python tensorflow keras

CNN Keras VGG16存在一些问题。

这里正在做的是尝试使用CNN和Keras和VGG16训练一些图像。看来它不能采用32号图像。即使将其更改为48号,仍然会出现错误。

---> 32         labels[i * batch_size : (i + 1) * batch_size] = labels_batch
     33         i += 1
     34         if i * batch_size >= sample_count:

ValueError: could not broadcast input array from shape (20,4) into shape (20)

我的代码如下。它使用Keras VGG16训练猫,狗,青蛙,螃蟹。出现输入数组形状错误:

from keras.applications import VGG16
conv_base = VGG16(weights='imagenet',
                  include_top=False, 
                  input_shape=(32, 32, 3)) 

conv_base.summary()


import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
base_dir = '../cat_dog_frog_crab/cat_dog_frog_crab' 
train_dir = os.path.join(base_dir, 'trainS') 
val_dir = os.path.join(base_dir, 'valS') 
test_dir = os.path.join(base_dir, 'testS')

datagen = ImageDataGenerator(rescale=1./255) 
batch_size = 20

from keras.applications import VGG16
conv_base = VGG16(weights='imagenet',
                  include_top=False, 
                  input_shape=(32, 32, 3)) 

def extract_features(directory, sample_count):
    features = np.zeros(shape=(sample_count, 4, 4, 512)) 
    labels = np.zeros(shape=(sample_count))
    generator = datagen.flow_from_directory(
        directory, 
        target_size=(32, 32), 
        batch_size=batch_size, 
        class_mode='categorical')
    i=0
    print ("before for loop")
    for inputs_batch, labels_batch in generator:
        features_batch = conv_base.predict(inputs_batch)
        features[i * batch_size : (i + 1) * batch_size] = features_batch 
        labels[i * batch_size : (i + 1) * batch_size] = labels_batch
        i += 1
        if i * batch_size >= sample_count:
            break
    return features, labels

train_features, train_labels = extract_features(train_dir, 2000) 
validation_features, validation_labels = extract_features(val_dir, 1000) 
test_features, test_labels = extract_features(test_dir, 1000)

train_features = np.reshape(train_features, (2000, 4 * 4 * 512))
validation_features = np.reshape(validation_features, (1000, 4 * 4 * 512))
test_features = np.reshape(test_features, (1000, 4 * 4 * 512))

from keras import models
from keras import layers
from keras import optimizers
model = models.Sequential()
model.add(layers.Dense(256, activation='relu', input_dim=4 * 4 * 512))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(4, activation='softmax'))
model.compile(optimizer=optimizers.RMSprop(lr=2e-5),
              loss='categorical_crossentropy',
              metrics=['acc'])


history = model.fit(train_features, train_labels, 
                    epochs=30,
                    batch_size=20,
                    validation_data=
                    (validation_features,validation_labels))

2 个答案:

答案 0 :(得分:0)

从看到的错误消息中可以很明显地看出您的问题。您正在尝试为形状为label的{​​{1}}分配大小为(20)的值。发生这种情况是因为您在(20,4)中选择了class_mode='categorical',因此标签是一个热编码的标签。您的flow_from_directory(...)应该类似于labels

答案 1 :(得分:0)

使用下面的代码,如果您遇到任何问题,请告诉我。

from keras.applications import VGG16
conv_base = VGG16(weights='imagenet',
                  include_top=False, 
                  input_shape=(32, 32, 3)) 

conv_base.summary()


import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
base_dir = '../cat_dog_frog_crab/cat_dog_frog_crab' 
train_dir = os.path.join(base_dir, 'trainS') 
val_dir = os.path.join(base_dir, 'valS') 
test_dir = os.path.join(base_dir, 'testS')

datagen = ImageDataGenerator(rescale=1./255) 
batch_size = 20

from keras.applications import VGG16
conv_base = VGG16(weights='imagenet',
                  include_top=False, 
                  input_shape=(32, 32, 3)) 

def extract_features(directory, sample_count):
    features = np.zeros(shape=(sample_count, 4, 4, 512)) 
    labels = np.zeros(shape=(sample_count, num_of_categories)) # Changes have been done here.@borarak's explanation is right.
    generator = datagen.flow_from_directory(
        directory, 
        target_size=(32, 32), 
        batch_size=batch_size, 
        class_mode='categorical')
    i=0
    print ("before for loop")
    for inputs_batch, labels_batch in generator:
        features_batch = conv_base.predict(inputs_batch)
        features[i * batch_size : (i + 1) * batch_size] = features_batch 
        labels[i * batch_size : (i + 1) * batch_size] = labels_batch
        i += 1
        if i * batch_size >= sample_count:
            break
    return features, labels

train_features, train_labels = extract_features(train_dir, 2000) 
validation_features, validation_labels = extract_features(val_dir, 1000) 
test_features, test_labels = extract_features(test_dir, 1000)

train_features = np.reshape(train_features, (2000, 4 * 4 * 512))
validation_features = np.reshape(validation_features, (1000, 4 * 4 * 512))
test_features = np.reshape(test_features, (1000, 4 * 4 * 512))

from keras import models
from keras import layers
from keras import optimizers
model = models.Sequential()
model.add(layers.Dense(256, activation='relu', input_dim=4 * 4 * 512))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(4, activation='softmax'))
model.compile(optimizer=optimizers.RMSprop(lr=2e-5),
              loss='categorical_crossentropy',
              metrics=['acc'])


history = model.fit(train_features, train_labels, 
                    epochs=30,
                    batch_size=20,
                    validation_data=
                    (validation_features,validation_labels))