在Keras中更改预训练的AlexNet分类 [英] Changing pretrained AlexNet classification in Keras
问题描述
我使用具有预训练权重的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屋!