为什么这些模型不同? keras 是否归一化梯度?
Why are these models different? Does keras normalize gradients?
我在模型中测试了一些偶然的归一化,我发现了一些很奇怪的东西。
对于输出完全相同的结果,但使用技术获得更大权重的模型,训练速度差异很大。
为什么会这样?如果权重更大,梯度应该更大,最后结果应该是相同的训练速度。导致此更改的隐藏魔法 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
你假设梯度不会改变是错误的。
假设最后一层的这个简化模型:单个神经元,没有激活。在第一种情况下,输出是
y = w.h
其中h
是上一层的输出。我们有 dy/dw = h
.
现在让我们引入一个比例因子λ
,
y = λ.w.h
现在输出的导数是dy/dw = λ.h
。 w
本身的值被 1/λ
.
缩放并不重要
要获得相同的梯度幅度,您实际上需要将前一层的输出 h
缩放 1/λ
倍。但是由于您保留了输出的比例,因此不会发生这种情况。
我在模型中测试了一些偶然的归一化,我发现了一些很奇怪的东西。
对于输出完全相同的结果,但使用技术获得更大权重的模型,训练速度差异很大。
为什么会这样?如果权重更大,梯度应该更大,最后结果应该是相同的训练速度。导致此更改的隐藏魔法 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
你假设梯度不会改变是错误的。
假设最后一层的这个简化模型:单个神经元,没有激活。在第一种情况下,输出是
y = w.h
其中h
是上一层的输出。我们有 dy/dw = h
.
现在让我们引入一个比例因子λ
,
y = λ.w.h
现在输出的导数是dy/dw = λ.h
。 w
本身的值被 1/λ
.
要获得相同的梯度幅度,您实际上需要将前一层的输出 h
缩放 1/λ
倍。但是由于您保留了输出的比例,因此不会发生这种情况。