在Keras中更改预训练的AlexNet分类 [英] Changing pretrained AlexNet classification in Keras

查看:496
本文介绍了在Keras中更改预训练的AlexNet分类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using a AlexNet with pretrained weights(heuritech/convnets-keras) for a classification problem with 8 classes instead of 1000. After initialising the network with Model(input=..,output=..) and loading the initial weights, I drop the last two layers, Dense(1000) and Activation(softmax), and add my own two layers: Dense(8) and Activation(softmax). But then, after running I get an error

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

32是我猜想的生成器的批处理大小,但是我不明白为什么softmax仍然希望从上一层获得1000个尺寸.

The 32 is the batch size from the generator I guess, but I don't understand why the softmax still expects 1000 dimensions from the previous layer.

有人可以帮助我吗?我认为它与Model的输出参数有关,但这只是尝试和谷歌搜索之后的半野蛮猜测. 谢谢!

Can someone help me? I think it has something to do the output parameter of the Model, but this is only semi-wild guessing after trying and googling around. Thanks!

代码:

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')

推荐答案

好吧,看来我不能只更改网络定义,因为即使在弹出/放入新图层之后,似乎也没有什么改变. 所以我这样做了:

Ok, it seems that I can't just change the network definition, because even after popping/putting new layers in, nothing seems to change. So I did this:

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定义的已加载网络.

Although I would still like to know how to change a loaded network defined by the functional api.

这篇关于在Keras中更改预训练的AlexNet分类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆