首页 文章

如何在Keras中创建自定义目标函数?

提问于
浏览
12

Keras有许多目标函数here.

但是你如何创建自己的目标函数,我试图创建一个非常基本的目标函数,但它给出了一个错误,我无法知道在运行时传递给函数的参数的大小 .

def loss(y_true,y_pred):
    loss = T.vector('float64')
    for i in range(1):
        flag = True
        for j in range(y_true.ndim):
            if(y_true[i][j] == y_pred[i][j]):
                flag = False
        if(flag):
            loss = loss + 1.0
    loss /= y_true.shape[0]
    print loss.type
    print y_true.shape[0]
    return loss

我有两个矛盾的错误,

model.compile(loss=loss, optimizer=ada)
  File "/usr/local/lib/python2.7/dist-packages/Keras-0.0.1-py2.7.egg/keras/models.py", line 75, in compile
    updates = self.optimizer.get_updates(self.params, self.regularizers, self.constraints, train_loss)
  File "/usr/local/lib/python2.7/dist-packages/Keras-0.0.1-py2.7.egg/keras/optimizers.py", line 113, in get_updates
    grads = self.get_gradients(cost, params, regularizers)
  File "/usr/local/lib/python2.7/dist-packages/Keras-0.0.1-py2.7.egg/keras/optimizers.py", line 23, in get_gradients
    grads = T.grad(cost, params)
  File "/usr/local/lib/python2.7/dist-packages/theano/gradient.py", line 432, in grad
    raise TypeError("cost must be a scalar.")
TypeError: cost must be a scalar.

它表示函数中返回的成本或损失必须是标量,但是如果我从loss = T.vector('float64')更改第2行

损失= T.scalar('float64')

它显示了这个错误

model.compile(loss=loss, optimizer=ada)
  File "/usr/local/lib/python2.7/dist-packages/Keras-0.0.1-py2.7.egg/keras/models.py", line 75, in compile
    updates = self.optimizer.get_updates(self.params, self.regularizers, self.constraints, train_loss)
  File "/usr/local/lib/python2.7/dist-packages/Keras-0.0.1-py2.7.egg/keras/optimizers.py", line 113, in get_updates
    grads = self.get_gradients(cost, params, regularizers)
  File "/usr/local/lib/python2.7/dist-packages/Keras-0.0.1-py2.7.egg/keras/optimizers.py", line 23, in get_gradients
    grads = T.grad(cost, params)
  File "/usr/local/lib/python2.7/dist-packages/theano/gradient.py", line 529, in grad
    handle_disconnected(elem)
  File "/usr/local/lib/python2.7/dist-packages/theano/gradient.py", line 516, in handle_disconnected
    raise DisconnectedInputError(message)
theano.gradient.DisconnectedInputError: grad method was asked to compute the gradient with respect to a variable that is not part of the computational graph of the cost, or is used only by a non-differentiable operator: <TensorType(float64, matrix)>

2 回答

  • 17

    这是我的小片段,用于编写新的损失函数并在使用之前测试它们:

    import numpy as np
    
    from keras import backend as K
    
    _EPSILON = K.epsilon()
    
    def _loss_tensor(y_true, y_pred):
        y_pred = K.clip(y_pred, _EPSILON, 1.0-_EPSILON)
        out = -(y_true * K.log(y_pred) + (1.0 - y_true) * K.log(1.0 - y_pred))
        return K.mean(out, axis=-1)
    
    def _loss_np(y_true, y_pred):
        y_pred = np.clip(y_pred, _EPSILON, 1.0-_EPSILON)
        out = -(y_true * np.log(y_pred) + (1.0 - y_true) * np.log(1.0 - y_pred))
        return np.mean(out, axis=-1)
    
    def check_loss(_shape):
        if _shape == '2d':
            shape = (6, 7)
        elif _shape == '3d':
            shape = (5, 6, 7)
        elif _shape == '4d':
            shape = (8, 5, 6, 7)
        elif _shape == '5d':
            shape = (9, 8, 5, 6, 7)
    
        y_a = np.random.random(shape)
        y_b = np.random.random(shape)
    
        out1 = K.eval(_loss_tensor(K.variable(y_a), K.variable(y_b)))
        out2 = _loss_np(y_a, y_b)
    
        assert out1.shape == out2.shape
        assert out1.shape == shape[:-1]
        print np.linalg.norm(out1)
        print np.linalg.norm(out2)
        print np.linalg.norm(out1-out2)
    
    
    def test_loss():
        shape_list = ['2d', '3d', '4d', '5d']
        for _shape in shape_list:
            check_loss(_shape)
            print '======================'
    
    if __name__ == '__main__':
        test_loss()
    

    在这里你可以看到我正在测试binary_crossentropy损失,并且定义了2个单独的损失,一个numpy版本(_loss_np)另一个张量版本(_loss_tensor)[注意:如果你只是使用keras函数那么它将适用于Theano和Tensorflow ...但如果您依赖其中一个,您也可以通过K.theano.tensor.function或K.tf.function引用它们]

    后来我比较输出形状和输出的L2范数(应该几乎相等)和差分的L2范数(应该朝向0)

    一旦您对损失功能正常工作感到满意,您可以将其用作:

    model.compile(loss=_loss_tensor, optimizer=sgd)
    
  • 3

    (答案已修复)一个简单的方法是调用Keras后端:

    import keras.backend as K
    
    def custom_loss(y_true,y_pred):
        return K.mean((y_true - y_pred)**2)
    

    然后:

    model.compile(loss=custom_loss, optimizer=sgd,metrics = ['accuracy'])
    

    等于

    model.compile(loss='mean_squared_error', optimizer=sgd,metrics = ['accuracy'])
    

相关问题