为了账号安全,请及时绑定邮箱和手机立即绑定

自定义损失函数,Keras \\ ValueError:无梯度

自定义损失函数,Keras \\ ValueError:无梯度

慕桂英4014372 2023-07-18 15:13:35
我正在尝试将我的 Keras 神经网络包装在一个class对象中。我已经在类设置之外实现了以下内容,但我想让它更加对象友好。总而言之,我的model调用函数sequential_model创建了一个sequential模型。在这compile一步中,我定义了自己的损失函数weighted_categorical_crossentropy,我希望顺序模型实现它。但是,当我运行下面的代码时,出现以下错误:ValueError: No gradients provided for any variable:我怀疑问题在于我如何定义该weighted_categorical_crossentropy函数以供sequential.再次,我能够以非面向对象的方式完成这项工作。任何帮助都感激不尽。from tensorflow.keras import Sequential, backend as Kclass MyNetwork():             def __init__(self, file, n_output=4, n_hidden=20, epochs=3,                 dropout=0.10, batch_size=64, metrics = ['categorical_accuracy'],                 optimizer = 'rmsprop', activation = 'softmax'):    [...] //Other Class attributes     def model(self):        self.model = self.sequential_model(False)        self.model.summary()    def sequential_model(self, val):        K.clear_session()        if val == False:            self.epochs = 3        regressor = Sequential()        #regressor.run_eagerly = True        regressor.add(LSTM(units = self.n_hidden, dropout=self.dropout, return_sequences = True, input_shape = (self.X.shape[1], self.X.shape[2])))        regressor.add(LSTM(units = self.n_hidden, dropout=self.dropout, return_sequences = True))        regressor.add(Dense(units = self.n_output, activation=self.activation))            self.weights = np.array([0.025,0.225,0.78,0.020])        regressor.compile(optimizer = self.optimizer, loss = self.weighted_categorical_crossentropy(self.weights), metrics = [self.metrics])        regressor.fit(self.X, self.Y*1.0,batch_size=self.batch_size, epochs=self.epochs, verbose=1, validation_data=(self.Xval, self.Yval*1.0))        return regressor
查看完整描述

1 回答

?
白衣染霜花

TA贡献1796条经验 获得超10个赞

上面的代码有几个问题,但最值得注意的一个是你没有返回lossfrom weighted_categorical_crossentropy。它应该看起来更像:


    def weighted_categorical_crossentropy(self, weights):

        weights = K.variable(weights)

        def loss(y_true, y_pred):

            y_pred /= K.sum(y_pred, axis=-1, keepdims=True)

            y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon())

            loss = y_true * K.log(y_pred) * weights

            loss = -K.sum(loss, -1)

            return loss

        return loss # Return the callable function!

错误是ValueError: No gradients provided for any variable因为loss方法不返回任何东西,它返回None!如果您尝试使用 拟合方法loss=None,模型将无法计算梯度,因此会抛出相同的错误。


接下来是您return_sequences = True在非循环层之前的层中使用的 。这会导致Dense在形状错误的数据上调用该层,这仅适用于循环层。不要那样使用它。

如果您有充分的理由使用return_sequences = True,那么您必须添加Dense如下层:


model.add(keras.layers.TimeDistributed(keras.layers.Dense(...)))

这将导致该层在每个时间步上分别Dense作用于输出序列。这也意味着您的体形必须合适。y_true


您定义的自定义损失函数可能存在其他问题,但我无法推断出输入/输出形状,因此您必须运行它并添加看看它是否有效。可能会存在矩阵乘法形状不匹配的情况。


最后但并非最不重要的一点是,考虑使用子类 API。它能让你的操作更容易编写吗?

查看完整回答
反对 回复 2023-07-18
  • 1 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信