使用自定义损失函数创建Keras模型的函数只能使用一次

问题描述 投票:1回答:1

我有一个使用Keras构建的压缩自动编码器,当我尝试将代码包装到函数中时,出现了一些奇怪的错误。该函数在我第一次运行时将起作用,但是如果再次运行它将崩溃。

ae, encoder = cae(fm, lam=1e-4) # this works 
ae, encoder = cae(fm, lam=1e-5) # this second call will crash

我认为是由于内部功能,但是我不知道要修复它。

这是函数的代码:

def cae(feat_mat, hidden_size=800, lam=1e-5, batch_size=128, epochs=2000):

    input_size = feat_mat.shape[1]
    x = Input(shape=(input_size,))
    h = Dense(hidden_size, activation='relu', name='encoded')(x)
    r = Dense(input_size, activation='sigmoid')(h)

    ae= Model(inputs=x, outputs=r)

    def contractive_loss(y_pred, y_true):
        mse = K.mean(K.square(y_true - y_pred), axis=1)

        W = K.variable(value=ae.get_layer('encoded').get_weights()[0])  # N x N_hidden
        W = K.transpose(W)  # N_hidden x N
        h = ae.get_layer('encoded').output
        dh = h * (1 - h)  # N_batch x N_hidden

        # N_batch x N_hidden * N_hidden x 1 = N_batch x 1
        contractive = lam * K.sum(dh**2 * K.sum(W**2, axis=1), axis=1)

        return mse + contractive


    ae.compile(optimizer='adam', loss=contractive_loss, metrics=['accuracy'])
    history = ae.fit(feat_mat, feat_mat, batch_size=batch_size,epochs=epochs, callbacks = [early_stopping_monitor])  
    encoder = Model(x, h)


    return ae, encoder

这是错误消息:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/anaconda3/envs/tensorflow_p36/lib/python3.6/site-packages/keras/engine/base_layer.py in assert_input_compatibility(self, inputs)
    278             try:
--> 279                 K.is_keras_tensor(x)
    280             except ValueError:

~/anaconda3/envs/tensorflow_p36/lib/python3.6/site-packages/keras/backend/tensorflow_backend.py in is_keras_tensor(x)
    473         raise ValueError('Unexpectedly found an instance of type `' +
--> 474                          str(type(x)) + '`. '
    475                          'Expected a symbolic tensor instance.')

ValueError: Unexpectedly found an instance of type `<class 'numpy.ndarray'>`. Expected a symbolic tensor instance.

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
<ipython-input-17-78d0f91db066> in <module>()
----> 1 cae, c_encoder = cae(data, epochs=20, lam=1e-6)

~/anaconda3/envs/tensorflow_p36/lib/python3.6/site-packages/keras/engine/base_layer.py in __call__(self, inputs, **kwargs)
    438             # Raise exceptions in case the input is not compatible
    439             # with the input_spec set at build time.
--> 440             self.assert_input_compatibility(inputs)
    441 
    442             # Handle mask propagation.

~/anaconda3/envs/tensorflow_p36/lib/python3.6/site-packages/keras/engine/base_layer.py in assert_input_compatibility(self, inputs)
    283                                  'Received type: ' +
    284                                  str(type(x)) + '. Full input: ' +
--> 285                                  str(inputs) + '. All inputs to the layer '
    286                                  'should be tensors.')
    287 

ValueError: Layer model_5 was called with an input that isn't a symbolic tensor. Received type: <class 'numpy.ndarray'>. Full input: [array([[0.        , 0.00408104, 0.00367454, ..., 0.47897612, 0.37681195,
        0.        ],
       [0.        , 0.        , 0.03629775, ..., 0.06981143, 0.07543451,
        0.        ],
       [0.        , 0.        , 0.        , ..., 0.09040481, 0.09040481,
        0.        ],
       ...,
       [0.        , 0.        , 0.        , ..., 0.09401818, 0.09401818,
        0.11997618],
       [0.        , 0.11205364, 0.        , ..., 0.05691057, 0.05691057,
        0.07582368],
       [0.1818507 , 0.20749162, 0.18682415, ..., 0.        , 0.        ,
        0.        ]])]. All inputs to the layer should be tensors.

一种解决方法是将代码作为脚本而不是在函数内部,但我真的很想将其包装起来,并且也想知道解决问题的方法。

谢谢!

python tensorflow keras autoencoder loss-function
1个回答
0
投票

根据您的例外,这是您正在执行的函数调用:

 cae, c_encoder = cae(data, epochs=20, lam=1e-6)

这里您有一个名为cae的函数,还有一个也名为cae的变量,它将覆盖原始函数。永远不要将变量命名为与函数相同的名称,因为它将产生这种奇怪的错误。

解决方案?重命名变量或函数。

© www.soinside.com 2019 - 2024. All rights reserved.