Como criar função objetivo personalizado em Keras?

votos
9

Há muitas funções objetivo em Keras aqui.

Mas como você pode criar sua própria função objetivo, eu tentei criar uma função objetivo muito básico, mas ele dá um erro e eu não há nenhuma maneira de saber o tamanho dos parâmetros passados ​​para a função em tempo de execução.

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

Estou ficando 2 erros contraditórias,

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.

Diz custo ou perda retornado na função deve ser um escalar, mas se eu mudar a linha 2 da perda = T.vector ( 'float64')
a
perda = T.scalar ( 'float64')

ele mostra este erro

 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)>
Publicado 22/11/2015 em 18:35
fonte usuário
Em outras línguas...                            


2 respostas

votos
1

(Resposta fixa) Uma maneira simples de fazê-lo está chamando Keras backend:

import keras.backend as K

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

Então:

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

que é igual a

model.compile(loss='mean_squared_error', optimizer=sgd,metrics = ['accuracy'])
Respondeu 30/09/2016 em 09:29
fonte usuário

votos
14

Aqui é o meu pequeno trecho para escrever novas funções de perda e testá-los antes de usar:

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()

Aqui, como você pode ver eu estou testando a perda binary_crossentropy, e tem 2 derrotas separados definido, uma versão numpy (_loss_np) outra versão tensor (_loss_tensor) [Nota: se você usar apenas as funções Keras seguida, ele irá trabalhar com ambos Theano e Tensorflow ... mas se você está dependendo de um deles, você também pode fazer referência a eles por K.theano.tensor.function ou K.tf.function]

Mais tarde, eu estou comparando as formas de saída e a norma L2 das saídas (que deve ser quase igual) e a norma L2 da diferença (que deve ser na direção de 0)

Quando estiver satisfeito que a sua função de perda está funcionando corretamente, você pode usá-lo como:

model.compile(loss=_loss_tensor, optimizer=sgd)
Respondeu 15/11/2016 em 22:51
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more