5

我想在 Keras 中使用 InceptionV3 使用瓶颈进行迁移学习。我使用了来自 https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html的一些关于创建、加载和使用瓶颈的技巧

我的问题是我不知道如何使用瓶颈(numpy 数组)作为具有新顶层的 InceptionV3 的输入。

我收到以下错误:

ValueError:检查输入时出错:预期 input_3 的形状为 (None, None, None, 3) 但得到的数组的形状为 (248, 8, 8, 2048)

248 是指本例中的图像总数。

我知道这条线是错误的,但我不知道如何纠正它:

模型=模型(输入=base_model.input,输出=预测)

将瓶颈输入 InceptionV3 的正确方法是什么?

创建 InceptionV3 瓶颈:

def create_bottlenecks():
datagen = ImageDataGenerator(rescale=1. / 255)

model = InceptionV3(include_top=False, weights='imagenet')

# Generate bottlenecks for all training images
generator = datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode=None,
    shuffle=False)

nb_train_samples = len(generator.filenames)
bottlenecks_train = model.predict_generator(generator, int(math.ceil(nb_train_samples / float(batch_size))), verbose=1)
np.save(open(train_bottlenecks_file, 'w'), bottlenecks_train)

# Generate bottlenecks for all validation images
generator = datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode=None,
    shuffle=False)

nb_validation_samples = len(generator.filenames)

bottlenecks_validation = model.predict_generator(generator, int(math.ceil(nb_validation_samples / float(batch_size))), verbose=1)
np.save(open(validation_bottlenecks_file, 'w'), bottlenecks_validation)

加载瓶颈:

def load_bottlenecks(src_dir, bottleneck_file):
    datagen = ImageDataGenerator(rescale=1. / 255)
    generator = datagen.flow_from_directory(
        src_dir,
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='categorical',
        shuffle=False)

    num_classes = len(generator.class_indices)

    # load the bottleneck features saved earlier
    bottleneck_data = np.load(bottleneck_file)

    # get the class lebels for the training data, in the original order
    bottleneck_class_labels = generator.classes

    # convert the training labels to categorical vectors
    bottleneck_class_labels = to_categorical(bottleneck_class_labels, num_classes=num_classes)

    return bottleneck_data, bottleneck_class_labels

开始训练:

def start_training():
global nb_train_samples, nb_validation_samples

create_bottlenecks()

train_data, train_labels = load_bottlenecks(train_data_dir, train_bottlenecks_file)
validation_data, validation_labels = load_bottlenecks(validation_data_dir, validation_bottlenecks_file)

nb_train_samples = len(train_data)
nb_validation_samples = len(validation_data)

base_model = InceptionV3(weights='imagenet', include_top=False)

# add a global spatial average pooling layer
x = base_model.output
x = GlobalAveragePooling2D()(x)

# let's add a fully-connected layer
x = Dense(1024, activation='relu')(x)

# and a logistic layer -- let's say we have 2 classes
predictions = Dense(2, activation='softmax')(x)

# What is the correct input? Obviously not base_model.input.
model = Model(inputs=base_model.input, outputs=predictions)

# first: train only the top layers (which were randomly initialized)
# i.e. freeze all convolutional InceptionV3 layers
for layer in base_model.layers:
    layer.trainable = False

model.compile(optimizer=optimizers.SGD(lr=0.01, momentum=0.9), loss='categorical_crossentropy', metrics=['accuracy'])

# train the model on the new data for a few epochs
history = model.fit(train_data, train_labels,
                    epochs=epochs,
                    batch_size=batch_size,
                    validation_data=(validation_data, validation_labels),
)

任何帮助,将不胜感激!

4

1 回答 1

5

当您尝试使用与模型支持的形状不同的输​​入数据来训练模型时,会发生此错误。

您的模型支持(None, None, None, 3),这意味着:

  • 任意数量的图像
  • 任何高度
  • 任意宽度
  • 3个频道

因此,您必须确保train_data(and validation_data) 与此形状匹配。

系统告诉你train_data.shape = (248,8,8,2048)

我看到它train_data来自load_botlenecks. 它真的应该来自​​那里吗?火车数据应该是什么?一个图像?还有什么?什么是瓶颈?


您的模型从 Inception 模型开始,Inception 模型拍摄图像。

但是,如果瓶颈已经是 Inception 模型的结果,并且您只想提供瓶颈,那么 Inception 模型根本不应该参与任何事情。

从...开始:

inputTensor = Input((8,8,2048)) #Use (None,None,2048) if bottlenecks vary in size    
x = GlobalAveragePooling2D()(inputTensor)

.....

使用以下命令创建模型:

model = Model(inputTensor, predictions)

这个想法是:

  • 初始模型:图像 -> 初始 -> 瓶颈
  • 你的模型:瓶颈 -> 模型 -> 标签

仅当您没有预加载瓶颈时才需要结合这两个模型,但是您有自己的图像,并且要首先预测瓶颈。(当然你也可以使用单独的模型)

然后你将只输入图像(瓶颈将由 Inception 创建并传递给你的模型,一切都在内部):

  • 组合模型:图像->初始->(瓶颈)->模型->标签

为了那个原因:

inputImage = Input((None,None,3))
bottleNecks = base_model(inputImage)
predictions = model(bottleNecks)

fullModel = Model(inputImage, predictions)
于 2017-09-19T21:23:31.440 回答