在 Keras 中更改预训练的 AlexNet 分类

Changing pretrained AlexNet classification in Keras

我正在使用具有预训练权重 (heuritech/convnets-keras) 的 AlexNet 来处理 8 类 而不是 1000 的分类问题。在使用 Model(input=..,output=..) 初始化网络并加载初始权重之后,我删除了最后两层,Dense(1000) 和 Activation(softmax),并添加了我自己的两层:Dense(8) 和 Activation(softmax)。 但是,在 运行 之后我得到一个错误

Error when checking model target: expected softmax to have shape (None, 1000) but got array with shape (32, 8)

我猜 32 是来自生成器的批量大小,但我不明白为什么 softmax 仍然期望来自前一层的 1000 个维度。

有人可以帮助我吗?我认为它与模型的输出参数有关,但这只是尝试和谷歌搜索后的半疯狂猜测。 谢谢!

代码:

import ...

pp = os.path.dirname(os.path.abspath(__file__))

##### Define Model #####
inputs = Input(shape=(3,227,227))
conv_1 = Convolution2D(96, 11, 11,subsample=(4,4),activation='relu', name='conv_1')(inputs)
...
...
...
dense_1 = MaxPooling2D((3, 3), strides=(2,2),name="convpool_5")(conv_5)
dense_1 = Flatten(name="flatten")(dense_1)
dense_1 = Dense(4096, activation='relu',name='dense_1')(dense_1)
dense_2 = Dropout(0.5)(dense_1)
dense_2 = Dense(4096, activation='relu',name='dense_2')(dense_2)
dense_3 = Dropout(0.5)(dense_2)  
dense_3 = Dense(1000,name='dense_3')(dense_3)
prediction = Activation("softmax",name="softmax")(dense_3)

model = Model(input=inputs, output=prediction)

for layer in model.layers[:27]:
    print layer.name
    layer.trainable = False

model.load_weights(pp+"/weights/alexnet_weights.h5")
print model.output_shape

print model.layers[-1]
model.layers.pop()
print model.output_shape
model.layers.pop()
print model.layers[-1]
print model.output_shape
model.layers.append(Dense(8, activation='softmax',name='dense_4'))

print model.layers[-1]
#####  Get Data #####
train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2)

test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(
        pp+'/dataset/training', 
        target_size=(227,227), 
        class_mode='categorical')  

validation_generator = test_datagen.flow_from_directory(
        pp+'/dataset/test',
        target_size=(227,227),
        class_mode='categorical')

##### Compile and Fit ####
sgd = SGD(lr=1e-4, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(optimizer=sgd, loss='mse')

model.fit_generator(
        train_generator,
        samples_per_epoch=500,
        nb_epoch=5,
        validation_data=validation_generator,
        nb_val_samples=150)

model.save_weights('first_try.h5')

好吧,看来我不能只更改网络定义,因为即使在 popping/putting 新层加入之后,似乎也没有任何变化。 所以我这样做了:

1) Load the default AlexNet

2) Load the pre-trained weights

3) Pop the 2 top layers

4) Add two new top layers

5) Save the weights

6) Change Network definition to use the two new layers

7) Load the new AlexNet with the saved weights

8) Profit!

尽管我仍然想知道如何更改由函数 api 定义的加载网络。