【问题标题】:Rewriting Sequential model using Functional API使用功能 API 重写序列模型
【发布时间】:2018-05-23 22:18:53
【问题描述】:

我正在尝试使用功能 API 重写 Network In Network CNN 的顺序模型。我将它与 CIFAR-10 数据集一起使用。 Sequential 模型训练没有问题,但 Functional API 模型卡住了。我可能在重写模型时遗漏了一些东西。

这是一个可重现的例子:

依赖关系:

from keras.models import Model, Input, Sequential
from keras.layers import Conv2D, MaxPooling2D, GlobalAveragePooling2D, Dropout, Activation
from keras.utils import to_categorical
from keras.losses import categorical_crossentropy
from keras.optimizers import Adam
from keras.datasets import cifar10

加载数据集:

(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train / 255.
x_test = x_test / 255.
y_train = to_categorical(y_train, num_classes=10)
y_test = to_categorical(y_test, num_classes=10)
input_shape = x_train[0,:,:,:].shape

这是工作的顺序模型:

model = Sequential()

#mlpconv block1
model.add(Conv2D(32, (5, 5), activation='relu',padding='valid',input_shape=input_shape))
model.add(Conv2D(32, (1, 1), activation='relu'))
model.add(Conv2D(32, (1, 1), activation='relu'))
model.add(MaxPooling2D((2,2)))
model.add(Dropout(0.5))

#mlpconv block2
model.add(Conv2D(64, (3, 3), activation='relu',padding='valid'))
model.add(Conv2D(64, (1, 1), activation='relu'))
model.add(Conv2D(64, (1, 1), activation='relu'))
model.add(MaxPooling2D((2,2)))
model.add(Dropout(0.5))

#mlpconv block3
model.add(Conv2D(128, (3, 3), activation='relu',padding='valid'))
model.add(Conv2D(32, (1, 1), activation='relu'))
model.add(Conv2D(10, (1, 1), activation='relu'))
model.add(GlobalAveragePooling2D())

model.add(Activation('softmax'))

编译和训练:

model.compile(loss=categorical_crossentropy, optimizer=Adam(), metrics=['acc']) 

_ = model.fit(x=x_train, y=y_train, batch_size=32, 
          epochs=200, verbose=1,validation_split=0.2)

在三个 epoch 中,模型的验证准确率接近 50%。

这是使用功能 API 重写的相同模型:

model_input = Input(shape=input_shape)

#mlpconv block1
x = Conv2D(32, (5, 5), activation='relu',padding='valid')(model_input)
x = Conv2D(32, (1, 1), activation='relu')(x)
x = Conv2D(32, (1, 1), activation='relu')(x)
x = MaxPooling2D((2,2))(x)
x = Dropout(0.5)(x)

#mlpconv block2
x = Conv2D(64, (3, 3), activation='relu',padding='valid')(x)
x = Conv2D(64, (1, 1), activation='relu')(x)
x = Conv2D(64, (1, 1), activation='relu')(x)
x = MaxPooling2D((2,2))(x)
x = Dropout(0.5)(x)

#mlpconv block3
x = Conv2D(128, (3, 3), activation='relu',padding='valid')(x)
x = Conv2D(32, (1, 1), activation='relu')(x)
x = Conv2D(10, (1, 1), activation='relu')(x)

x = GlobalAveragePooling2D()(x)
x = Activation(activation='softmax')(x)

model = Model(model_input, x, name='nin_cnn')

然后使用与顺序模型相同的参数编译此模型。训练后,训练准确率卡在0.10,这意味着模型并没有变得更好,而是随机选择了 10 个类中的一个。

在重写模型时我错过了什么?调用 model.summary() 时,模型看起来相同,但功能 API 模型中的显式 Input 层除外。

【问题讨论】:

    标签: machine-learning neural-network computer-vision keras conv-neural-network


    【解决方案1】:

    在最后的conv层去掉activation解决了这个问题:

    x = Conv2D(10, (1, 1))(x)
    

    仍然不确定为什么 Sequential 模型可以在该层中正常工作。

    【讨论】:

    • @desertnaut 你的意思是GlobalAveragePooling2D之后的softmax吗?它只是使用 softmax 的最终 FC 层的替代方案。
    • 它对我有用,但我不明白为什么要从最终的 conv 层中删除激活函数?!你能证明一下吗?
    • @N.IT 这是不久前的事了......无法真正证明为什么它会这样工作。我与全局池的工作方式有关
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 2019-03-11
    相关资源
    最近更新 更多