keras 模型中的平均权重
Posted
技术标签:
【中文标题】keras 模型中的平均权重【英文标题】:Average weights in keras models 【发布时间】:2018-06-21 01:56:09 【问题描述】:当我训练几个具有相同架构和不同初始化的模型时,如何在 Keras 模型中平均权重?
现在我的代码看起来像这样?
datagen = ImageDataGenerator(rotation_range=15,
width_shift_range=2.0/28,
height_shift_range=2.0/28
)
epochs = 40
lr = (1.234e-3)
optimizer = Adam(lr=lr)
main_input = Input(shape= (28,28,1), name='main_input')
sub_models = []
for i in range(5):
x = Conv2D(32, kernel_size=(3,3), strides=1)(main_input)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = MaxPool2D(pool_size=2)(x)
x = Conv2D(64, kernel_size=(3,3), strides=1)(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = MaxPool2D(pool_size=2)(x)
x = Conv2D(64, kernel_size=(3,3), strides=1)(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Flatten()(x)
x = Dense(1024)(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Dropout(0.1)(x)
x = Dense(256)(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = Dropout(0.4)(x)
x = Dense(10, activation='softmax')(x)
sub_models.append(x)
x = keras.layers.average(sub_models)
main_output = keras.layers.average(sub_models)
model = Model(inputs=[main_input], outputs=[main_output])
model.compile(loss='categorical_crossentropy', metrics=['accuracy'],
optimizer=optimizer)
print(model.summary())
plot_model(model, to_file='model.png')
filepath="weights.best.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
tensorboard = TensorBoard(log_dir='./Graph', histogram_freq=0, write_graph=True, write_images=True)
callbacks = [checkpoint, tensorboard]
model.fit_generator(datagen.flow(X_train, y_train, batch_size=128),
steps_per_epoch=len(X_train) / 128,
epochs=epochs,
callbacks=callbacks,
verbose=1,
validation_data=(X_test, y_test))
所以现在我只平均最后一层,但我想在单独训练每一层后平均所有层的权重。
谢谢!
【问题讨论】:
你根本无法平均神经网络的权重。 到目前为止你尝试过什么?如果在每一层之间调用keras.layers.average()
会怎样?
不想在每一层之间进行平均,因为我想分别训练每个模型。如果在每一层之后进行平均,那就不同了。同样是当我在训练前对最后一层的模型进行平均时,这也是不同的。
@MatiasValdenegro 是的,你可以:arxiv.org/abs/1803.05407
@Scratch 这篇论文不支持这个问题中提出的想法,它是关于对 SGD 轨迹进行平均的,它是在提出这个问题之后出现的。
【参考方案1】:
所以让我们假设models
是您的模型的集合。首先 - 收集所有权重:
weights = [model.get_weights() for model in models]
现在 - 创建一个新的平均权重:
new_weights = list()
for weights_list_tuple in zip(*weights):
new_weights.append(
[numpy.array(weights_).mean(axis=0)\
for weights_ in zip(*weights_list_tuple)])
剩下的就是在新模型中设置这些权重:
new_model.set_weights(new_weights)
当然 - 平均权重可能不是一个好主意,但如果你尝试 - 你应该遵循这种方法。
【讨论】:
为什么这是个坏主意?我受到cs231n.github.io/neural-networks-3/#ensemble 的启发,据说这是个好主意;) 只是给你一个例子,为什么这可能会出错 - 采用一个模型并以一致的方式排列所有过滤器。该网络在数学上将是等效的 - 但平均值可能与原始函数有很大不同。而且我并不是说这是个坏主意-我声称它可能;) 我还有一个问题。我得到:'NoneType' 对象没有属性'evaluate' 我发现它连接到 fit_generator,但不知道如何解决这个问题,你能帮忙吗?谢谢! github.com/miloszbednarzak/mnist/blob/master/… 将此行new_model = model.set_weights(new_weights)
更改为`model.set_weights(new_weights)
【参考方案2】:
我无法对已接受的答案发表评论,但要使其在 tensorflow 2.0
和 tf.keras
上工作,我必须将循环中的列表变成一个 numpy 数组:
new_weights = list()
for weights_list_tuple in zip(*weights):
new_weights.append(
np.array([np.array(w).mean(axis=0) for w in zip(*weights_list_tuple)])
)
如果不同的输入模型需要不同的权重,则需要将np.array(w).mean(axis=0)
替换为np.average(np.array(w),axis=0, weights=relative_weights)
,其中relative_weights
是一个数组,每个模型都有一个权重因子。
【讨论】:
以上是关于keras 模型中的平均权重的主要内容,如果未能解决你的问题,请参考以下文章