这些模型是否等效?

发布于 2021-01-29 17:40:43

主要问题: 我用两种不同的方式定义相同的模型。为什么会得到不同的结果?它们似乎是相同的模型。

第二个问题(在下面回答)如果再次运行代码,则会再次得到不同的结果。我已经在开始时设置了种子以修复随机性。为什么会这样呢?

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
被浏览
33
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    问题的根源在于模型定义和随机性的 预期 行为 与实际 行为。要查看发生了什么,我们必须了解“ RNG”的工作原理:

    • “随机数生成器”(RNG)实际上是一种生成数字的函数,以便将它们映射到“长期”的概率分布上
    • 例如,当RNG()调用RNG函数时,它将返回一个“随机”值,并将 其内部计数器加1 。呼叫此计数器n-然后:random_value = RNG(n)
    • 当设置SEED,设置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的权重是根据nfrom100 + 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,则不是完美的-
    由于操作的并行性;这个视频很好地解释了。为了获得更好的重现性,请PYHTONHASHSEED在官方Keras常见问题解答中设置your -that和其他信息。

    “完美”的可重复性相当多余,因为您的结果应该在大部分时间的0.1%之内达成一致-
    但是,如果您确实需要它,那么当前唯一的方法可能就是切换到CPU并停止使用CUDA-但这会减慢速度极大地训练(通过x10 +)。


    随机性的来源

    • 权重初始化(每个默认的Keras初始化程序都使用随机性)
    • 噪声层(降落,高斯噪声等)
    • 散列基于散列的操作,例如集合或字典中的项目顺序
    • GPU并行性(请参阅链接的视频)

    模型随机性演示

    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")
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看