主要问题:我以两种不同的方式定义相同的模型。为什么会得到不同的结果?它们似乎是相同的模型。
第二个问题(在下面回答)如果再次运行代码,则会再次得到不同的结果。我已经在开始时设置了种子以修复随机性。为什么会这样?
import numpy as np
np.random.seed(1)
from keras.models import Model, Sequential
from keras.layers import Input, Dense
model1= Sequential([
Dense(20, activation='sigmoid',kernel_initializer='glorot_normal',
input_shape=(2,)),
Dense(2, activation='linear', kernel_initializer='glorot_normal'),
])
model1.compile(optimizer='adam', loss='mean_squared_error')
ipt = Input(shape=(2,))
x = Dense(20, activation='sigmoid', kernel_initializer='glorot_normal')(ipt)
out = Dense(2, activation='linear', kernel_initializer='glorot_normal')(x)
model2 = Model(ipt, out)
model2.compile(optimizer='adam', loss='mean_squared_error')
x_train=np.array([[1,2],[3,4],[3,4]])
model1.fit(x_train, x_train,epochs=2, validation_split=0.1, shuffle=False)
model2.fit(x_train, x_train,epochs=2, validation_split=0.1, shuffle=False)
第一次,输出是:
2/2 [==============================] - 0s 68ms/step - loss: 14.4394 - val_loss: 21.5747
Epoch 2/2
2/2 [==============================] - 0s 502us/step - loss: 14.3199 - val_loss: 21.4163
Train on 2 samples, validate on 1 samples
Epoch 1/2
2/2 [==============================] - 0s 72ms/step - loss: 11.0523 - val_loss: 17.7059
Epoch 2/2
2/2 [==============================] - 0s 491us/step - loss: 10.9833 - val_loss: 17.5785
第二次,输出为:
2/2 [==============================] - 0s 80ms/step - loss: 14.4394 - val_loss: 21.5747
Epoch 2/2
2/2 [==============================] - 0s 501us/step - loss: 14.3199 - val_loss: 21.4163
Train on 2 samples, validate on 1 samples
Epoch 1/2
2/2 [==============================] - 0s 72ms/step - loss: 11.0523 - val_loss: 17.6733
Epoch 2/2
2/2 [==============================] - 0s 485us/step - loss: 10.9597 - val_loss: 17.5459
阅读答案后更新:通过以下答案,我的一个问题已得到回答。我将代码的开头更改为:
import numpy as np
np.random.seed(1)
import random
random.seed(2)
import tensorflow as tf
tf.set_random_seed(3)
而且,现在我得到的数字与以前相同。因此,它是稳定的。但是,我的主要问题仍然没有答案。为什么两个相同的模型每次都会给出不同的结果?
这是我每次得到的结果:
结果1:
Epoch 1/2
2/2 [==============================] - 0s 66ms/sample - loss: 11.9794 - val_loss: 18.9925
Epoch 2/2
2/2 [==============================] - 0s 268us/sample - loss: 11.8813 - val_loss: 18.8572
结果2:
Epoch 1/2
2/2 [==============================] - 0s 67ms/sample - loss: 5.4743 - val_loss: 9.3471
Epoch 2/2
2/2 [==============================] - 0s 3ms/sample - loss: 5.4108 - val_loss: 9.2497
答案 0 :(得分:2)
问题的根源在于模型定义和随机性的预期行为与实际行为。要查看发生了什么,我们必须了解“ RNG”的工作原理:
RNG()
被调用,它返回一个“随机”值,并将其内部计数器递增1 。呼叫此计数器n
-然后:random_value = RNG(n)
n
;我们可以通过柜台上的+ c
来表示这种差异c
将是由种子的非线性但确定性的函数产生的常数:f(seed)
import numpy as np
np.random.seed(4) # internal counter = 0 + c
print(np.random.random()) # internal counter = 1 + c
print(np.random.random()) # internal counter = 2 + c
print(np.random.random()) # internal counter = 3 + c
np.random.seed(4) # internal counter = 0 + c
print(np.random.random()) # internal counter = 1 + c
print(np.random.random()) # internal counter = 2 + c
print(np.random.random()) # internal counter = 3 + c
0.9670298390136767
0.5472322491757223
0.9726843599648843
0.9670298390136767
0.5472322491757223
0.9726843599648843
假设model1
有100个权重,并且您设置了一个种子(n = 0 + c
)。构建model1
后,您的计数器将位于100 + c
。如果您不重置种子,即使您使用完全相同的代码构建model2
,模型也会有所不同-与model2
'相同权重是从n
到100 + c
每200 + c
初始化的。
有三个种子以确保更好的随机性:
import numpy as np
np.random.seed(1) # for Numpy ops
import random
random.seed(2) # for Python ops
import tensorflow as tf
tf.set_random_seed(3) # for tensorfow ops - e.g. Dropout masks
这将提供很好的可重复性,但如果使用GPU,则不是完美的-由于操作的并行性; this video很好地解释了这一点。为了获得更好的重现性,请在官方Keras FAQ中设置您的PYHTONHASHSEED
-和其他信息。
“完美”的可重复性是相当多余的,因为您的结果应该在.1%的大部分时间内达成一致-但是,如果您确实需要它,那么当前唯一的方法可能就是切换到CPU并停止使用CUDA-但这是“会极大地减慢训练速度(快10倍以上)。
随机性源:
模型随机性演示:
import numpy as np
np.random.seed(4)
model1_init_weights = [np.random.random(), np.random.random(), np.random.random()]
model2_init_weights = [np.random.random(), np.random.random(), np.random.random()]
print("model1_init_weights:", model1_init_weights)
print("model2_init_weights:", model2_init_weights)
model1_init_weights: [0.9670298390136767, 0.5472322491757223, 0.9726843599648843]
model2_init_weights: [0.7148159936743647, 0.6977288245972708, 0.21608949558037638]
重新启动内核。现在运行:
import numpy as np
np.random.seed(4)
model2_init_weights = [np.random.random(), np.random.random(), np.random.random()]
model1_init_weights = [np.random.random(), np.random.random(), np.random.random()]
print("model1_init_weights:", model1_init_weights)
print("model2_init_weights:", model2_init_weights)
model1_init_weights: [0.7148159936743647, 0.6977288245972708, 0.21608949558037638]
model2_init_weights: [0.9670298390136767, 0.5472322491757223, 0.9726843599648843]
因此,翻转代码中的model1
和model2
的顺序也可以抵消损失。这是因为种子不会在两个模型的定义之间重置自己,因此您的权重初始化完全不同。
如果希望它们相同,请在定义“每个模型”之前以及在拟合每个模型之前重置种子-并使用如下方便的功能。但是最好的选择是重新启动内核并在单独的.py
文件中工作。
def reset_seeds():
np.random.seed(1)
random.seed(2)
tf.set_random_seed(3)
print("RANDOM SEEDS RESET")