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

Python 如何在Keras中创建自定义目标函数?,python,keras,Python,Keras,Keras中有许多目标函数 但是如何创建自己的目标函数呢?我试图创建一个非常基本的目标函数,但它给出了一个错误,我无法知道在运行时传递给函数的参数的大小 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

Keras中有许多目标函数

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

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.
它说函数中返回的成本或损失必须是标量,但是如果我将第2行从 损失=T.vector('float64')

损耗=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)>
model.compile(loss=loss,optimizer=ada)
文件“/usr/local/lib/python2.7/dist packages/Keras-0.0.1-py2.7.egg/Keras/models.py”,第75行,编译
更新=self.optimizer.get_更新(self.params、self.regulatories、self.constraints、train_loss)
文件“/usr/local/lib/python2.7/dist packages/Keras-0.0.1-py2.7.egg/Keras/optimizers.py”,第113行,在get_更新中
梯度=自身。获取梯度(成本、参数、正则化器)
文件“/usr/local/lib/python2.7/dist packages/Keras-0.0.1-py2.7.egg/Keras/optimizers.py”,第23行,在get_梯度中
梯度=T.grad(成本,参数)
文件“/usr/local/lib/python2.7/dist-packages/theano/gradient.py”,第529行,以梯度表示
断开手柄(elem)
文件“/usr/local/lib/python2.7/dist packages/theano/gradient.py”,第516行,在句柄中
引发DisconnectedInputError(消息)
theano.gradient.DisconnectedInputError:要求grad方法计算不属于成本计算图一部分或仅由不可微运算符使用的变量的梯度:
(答案已修复)一种简单的方法是调用Keras后端:

import keras.backend as K

def custom_loss(y_true,y_pred):
    return K.mean((y_true - y_pred)**2)
然后:

那等于

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

下面是我编写新的loss函数并在使用前对其进行测试的小片段:

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()
如你所见,我正在测试二进制交叉熵损失,定义了两个独立的损失,一个是numpy版本(\u loss\u np),另一个是张量版本(\u loss\u tensor)[注:如果您只使用keras函数,那么它将同时适用于Theano和Tensorflow…但是如果您依赖其中一个函数,您也可以通过K.Theano.tensor.function或K.tf.function引用它们]

稍后我将比较输出形状和输出的L2范数(应该几乎相等)和差异的L2范数(应该接近0)

一旦您确信损失函数工作正常,您可以将其用作:

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

你的损失应该是
y_true
y_pred
的Theano函数,也就是说,它必须用这些参数的张量运算来表示。这只是通常的损失,而不是@Kev1n91的自定义损失函数,我从来没有见过一个自定义损失函数的不平凡的例子,它适用于测试驱动开发!+1没有什么比机器学习更好的了。
model.compile(loss=_loss_tensor, optimizer=sgd)