为什么这些型号不同? keras是否规范了渐变?

时间:2018-06-05 22:01:31

标签: python tensorflow keras backpropagation

我正在测试模型中的一些标准化,我发现了一些非常奇怪的东西。

对于输出完全相同结果但使用技术来获得更大权重的模型,训练速度非常不同。

为什么会这样?如果权重较大,则梯度应该更大,最后结果应该是相同的训练速度。隐藏的魔法keras或tensorflow正在做什么导致这种变化?

详细说明:

模型

在这里,我定义了3个模型,其中2个中间张量除以一个值,并且在补偿时,它们的权重乘以相同的值。

考虑到每个神经元的输出是w1*i1 + w2*i2 + w3*i3 ...的变化,如果我将所有权重乘以一个值并将所有输入除以相同的值,则结果完全相同。 (where: w = weight ; i = input)

我从所有图层中移除了偏见,因此它们不会影响结果。

模型1 - 未更改的模型

inp1 = Input((smallSide,bigSide,3))
out1 = Conv2D(200,3,activation='tanh', use_bias=False, padding = 'same', name="conv1")(inp1)
out1 = Conv2D(1,3,activation='sigmoid', use_bias=False, padding = 'same', name="conv2")(out1)
model1 = Model(inp1,out1)

模型2 - 在激活之前,将输出除以输入数

inp2 = Input((smallSide,bigSide,3))

out2 = Conv2D(200,3,activation='linear', use_bias=False, padding = 'same', name="conv1a")(inp2)
out2 = Lambda(lambda x: x/3.)(out2)
out2 = Activation('tanh')(out2)

out2 = Conv2D(1,3,activation='linear', use_bias=False, padding = 'same', name="conv2a")(out2)
out2 = Lambda(lambda x: x/200.)(out2)
out2 = Activation('sigmoid')(out2)

model2 = Model(inp2,out2)

模型3(应与2相同,顺序不同)

inp3 = Input((smallSide,bigSide,3))
out3 = Lambda(lambda x: x/3.)(inp3)

out3 = Conv2D(200,3,activation='tanh', use_bias=False, padding = 'same', name="conv1b")(out3)
out3 = Lambda(lambda x: x/200.)(out3)

out3 = Conv2D(1,3,activation='sigmoid', use_bias=False, padding = 'same', name="conv2b")(out3)

model3 = Model(inp3,out3)

编译和调整权重

编译,所有模型的相同配置:

model1.compile(optimizer='adam', loss='binary_crossentropy')
model2.compile(optimizer='adam', loss='binary_crossentropy')
model3.compile(optimizer='adam', loss='binary_crossentropy')

在这里,我将权重从模型1转移到其他模型,应用正确的乘法因子来补偿分割输出:

model2.get_layer('conv1a').set_weights([3 * model1.get_layer('conv1').get_weights()[0]])
model2.get_layer('conv2a').set_weights([200 * model1.get_layer('conv2').get_weights()[0]])

model3.get_layer('conv1b').set_weights([3 * model1.get_layer('conv1').get_weights()[0]])
model3.get_layer('conv2b').set_weights([200 * model1.get_layer('conv2').get_weights()[0]])

确保平等

在这里,我测试每个模型的输出,看它们是否相等:

y1 = model1.predict(X[:10])
y2 = model2.predict(X[:10])
y3 = model3.predict(X[:10])

inspectValues(y1-y2) #this is a custom function that prints min, max and mean
inspectValues(y1-y3)
inspectValues(y2-y3)

输出结果为:

inspecting values:
    shape: (10, 64, 96, 1)
    min: -1.19209e-07
    max: 1.19209e-07
    mean: -2.00477e-09
inspecting values:
    shape: (10, 64, 96, 1)
    min: -1.19209e-07
    max: 5.96046e-08
    mean: -2.35159e-09
inspecting values:
    shape: (10, 64, 96, 1)
    min: -1.19209e-07
    max: 1.19209e-07
    mean: -3.46821e-10

考虑到输出范围是0到1,我们可以看到值几乎相同。

培训差异

在这里,我快速训练这三个模型,并且有一个显着的可再现差异,model1始终领先于其他模型。为什么会这样?

for epoch in range(20):
    print("\n\n\nfitting model 3")
    model3.fit(X,Y,epochs=2)
    print("\n\n\nfitting model 1")
    model1.fit(X,Y,epochs=2)
    print("\n\n\nfitting model 2")
    model2.fit(X,Y,epochs=2)

输出:

fitting model 3
Epoch 1/2
5088/5088 [==============================] - 302s 59ms/step - loss: 0.1057
Epoch 2/2
5088/5088 [==============================] - 300s 59ms/step - loss: 0.0260

fitting model 1
Epoch 1/2
5088/5088 [==============================] - 284s 56ms/step - loss: 0.0280
Epoch 2/2
5088/5088 [==============================] - 282s 55ms/step - loss: 0.0111

fitting model 2
Epoch 1/2
5088/5088 [==============================] - 296s 58ms/step - loss: 0.1059
Epoch 2/2
5088/5088 [==============================] - 296s 58ms/step - loss: 0.0260

fitting model 3
Epoch 1/2
5088/5088 [==============================] - 300s 59ms/step - loss: 0.0187
Epoch 2/2
5088/5088 [==============================] - 301s 59ms/step - loss: 0.0155

fitting model 1
Epoch 1/2
5088/5088 [==============================] - 281s 55ms/step - loss: 0.0110
Epoch 2/2
5088/5088 [==============================] - 283s 56ms/step - loss: 0.0105

fitting model 2
Epoch 1/2
5088/5088 [==============================] - 294s 58ms/step - loss: 0.0187
Epoch 2/2

1 个答案:

答案 0 :(得分:2)

你认为渐变不会改变是错误的。

假设最后一层的这个简化模型:单个神经元,没有激活。在第一种情况下,输出是

y = w.h

其中h是前一层的输出。我们有dy/dw = h

现在让我们介绍一个比例因子λ

y = λ.w.h

现在输出的导数是dy/dw = λ.hw本身的值按1/λ缩放并不重要。

要获得相同的渐变幅度,您实际上需要将前一层h的输出缩放1/λ因子。但由于你保留了输出的规模,所以不会发生这种情况。