为什么我的模型的性能稳定?

Why is my Model's performance plateauing?

我正在用一组随机数训练一个非常简单的模型,只是想学习 y=x。代码在下面,但也在此处: https://pastebin.com/6cNdjNNF 。但是,该模型有时会表现异常并且无法训练/达到稳定状态。我应该注意,我为 x 和 y=x 播种了 10000 个值的随机列表,因此每次迭代中的数据都是相同的。

    prng = np.random.RandomState(1234567891)
    x = prng.rand(10000, 1)
    y = x

    def create_model():
        dropout_nodes = 0.0
        intermediary_activation = 'relu'
        final_activation = 'linear'

        # initialize sequential model
        model = tf.keras.models.Sequential()

        layer_nodes = [16, 8, 4, 2]
        for i, layer_node in enumerate(layer_nodes):
            if i==0:
                # first layer
                model.add(tf.keras.layers.Dense(layer_node, input_dim=1))
                model.add(tf.keras.layers.Activation(intermediary_activation))
                model.add(tf.keras.layers.Dropout(dropout_nodes))
                # model.add(tf.keras.layers.BatchNormalization())
            else:
                # other layers
                model.add(tf.keras.layers.Dense(layer_node))
                model.add(tf.keras.layers.Activation(intermediary_activation))
                model.add(tf.keras.layers.Dropout(dropout_nodes))
                # model.add(tf.keras.layers.BatchNormalization()) 
        model.add(tf.keras.layers.Dense(1))
        model.add(tf.keras.layers.Activation(final_activation))

        loss = 'mse'
        metric = ["mae", "mape"]
        opt = tf.keras.optimizers.SGD(learning_rate=1e-2)
        # opt = tf.keras.optimizers.Adam(learning_rate=1e-3)

        model.compile(loss=loss, optimizer=opt, metrics=[metric])

        return model

    model = create_model()

    history = model.fit(x=x, y=y,
                        validation_split=0.1, shuffle=False,
                        epochs=20,
                        batch_size=32,
                        verbose=1, )

    pred = model.predict(x)
    
    df = pd.DataFrame(x, columns=["x"])
    df['y'] = y
    df['pred'] = pred
    model_evaluation = model.evaluate(x, y, verbose=2)
    dict_model_evaluation = {k.name: model_evaluation[i] for i, k in enumerate(model.metrics)}
    print(dict_model_evaluation)

具体来说,在打印最终评估时,我从 运行 脚本中得到了以下结果 10 次。请注意,在其中五次迭代中,结果是相同的;当您查看其中一次迭代的每个时期时,模型会达到稳定状态并且不再改进。为什么会这样?

{'loss': 0.08206459134817123, 'mae': 0.24807175993919373, 'mape': 797.3375854492188}
{'loss': 4.3269268644507974e-05, 'mae': 0.0054251449182629585, 'mape': 33.66191101074219}
{'loss': 3.115053550573066e-05, 'mae': 0.003888161387294531, 'mape': 47.37348937988281}
{'loss': 0.08206459134817123, 'mae': 0.24807175993919373, 'mape': 797.3375854492188}
{'loss': 0.08206459134817123, 'mae': 0.24807175993919373, 'mape': 797.3375854492188}
{'loss': 0.08206459134817123, 'mae': 0.24807175993919373, 'mape': 797.3375854492188}
{'loss': 5.879357559024356e-06, 'mae': 0.0013944993261247873, 'mape': 23.40262794494629}
{'loss': 0.08206459134817123, 'mae': 0.24807175993919373, 'mape': 797.3375854492188}
{'loss': 6.495025900221663e-06, 'mae': 0.0019656901713460684, 'mape': 20.390905380249023}
{'loss': 1.061584316630615e-05, 'mae': 0.0014895511558279395, 'mape': 38.272361755371094}


Epoch 1/20
282/282 [==============================] - 1s 3ms/step - loss: 0.1051 - mae: 0.2714 - mape: 645.1287 - val_loss: 0.0807 - val_mae: 0.2468 - val_mape: 481.0587
Epoch 2/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 821.4997 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6515
Epoch 3/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1142 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 4/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 5/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 6/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 7/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 8/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 9/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 10/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 11/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 12/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 13/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 14/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 15/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 16/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 17/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 18/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 19/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568
Epoch 20/20
282/282 [==============================] - 1s 2ms/step - loss: 0.0822 - mae: 0.2483 - mape: 822.1162 - val_loss: 0.0806 - val_mae: 0.2468 - val_mape: 482.6568

当 运行 模型达到稳定状态时,您会注意到它实际上只是预测相同的数字,无论您提供什么输入。这偶尔会发生,因为激活函数导致模型归零。在模型停滞的情况下,如果您查看从第二层到最后一层的输出,您会注意到它的输出如下所示:

array([[0., 0.]], dtype=float32)

对于您传递给模型的任何数字,它看起来都是这样的,但它是如何到达这里的?好吧,如果我们看一下只有 2 个节点的层的权重,当我 运行 模型并得到稳定的结果时,它看起来像这样:

[array([[-0.20621395, -0.06383181],
    [-0.7566335 , -0.67413807],
    [ 0.89420843, -0.17675757],
    [-0.9511714 , -0.27772212]], dtype=float32),
 array([0., 0.], dtype=float32)]

你会注意到它们中的大多数是负数,两个密集节点的输出都是负数,并且由于 relu 的工作方式,任何负数都将变为零。因此,由于总是将两个零传递到最后一层,因此模型会尽力根据这些值猜测输出,但显然不会做得很好,您会注意到它会在数据点中间选择一个值,在这个接近 0.5 的情况。

那么为什么某些运行会出现这种情况而不是其他运行的原因是由于权重的 运行dom 初始化,并且在具有 2 个节点的层中有很多负数的不幸的人更有可能导致稳定效应。

至于解决这个问题,最好的办法是不要对模型造成太大的瓶颈,在每个密集层中坚持使用更高的节点数量,例如:

layer_nodes = [32, 16, 8]

那么一个层的输出全为零的可能性要低得多。 运行 使用这个新层数的模型几次,我从未经历过相同的稳定效应。也可能有一些其他方法来解决这个问题,例如更改权重初始化或使用不同的激活函数,但我认为我之前关于增加每层节点的建议更简单。

一些其他有用的代码,我如何查看图层权重:

model.get_layer(index=-4).get_weights()

如何查看仅发生 2 个节点瓶颈的倒数第二层的输出,其中 .34 只是我测试的 运行dom 值。

model2 = Model(inputs=model.input, outputs=model.get_layer(index=-2).output)
model2.predict([[.34]])