Как создать собственную функцию потерь, основанную на сходстве косинусов в theano / lasagne? - PullRequest
0 голосов
/ 14 апреля 2020

Я абсолютный новичок в theano и уже несколько дней борюсь с этой проблемой. Как я могу добавить пользовательскую функцию потерь, основанную на сходстве косинусов, как определено в этой статье - код github здесь ?

def inv_correlation(y_true, y_pred):
    """ Computes 1 minus the dot product between corresponding pairs of samples in two tensors. """
    return 1. - K.sum(y_true * y_pred, axis = -1)

Я пытаюсь сделать это, скопировав код из theano nnet, но совершенно не понимаю, как это сделать правильно. По какой-то причине мой код переходит ко второму, если нет, ndim не совпадает, и я теряюсь после этого.

def cosine_similarity(coding_dist, true_dist):
    """
    H(p,q) = - \sum_x p(x) \log(q(x))
    """
    if true_dist.ndim == coding_dist.ndim: #it's not coming here
        return -T.sum(true_dist * T.log(coding_dist),
                           axis=coding_dist.ndim - 1)
    elif true_dist.ndim == coding_dist.ndim - 1: # try to modify this part but it seems to be a bit way over my head
        return cosine_similarity_1hot(coding_dist, true_dist)
    else:
        raise TypeError('rank mismatch between coding and true distributions')


class CosineSimilarity1HotGrad(gof.Op):

    __props__ = ()

    def make_node(self, g_y, coding_dist, true_one_of_n):
        return Apply(self, [g_y, coding_dist, true_one_of_n],
                     [coding_dist.type()])

    def perform(self, node, inp, out):
        g_y, coding_dist, true_one_of_n = inp
        g_coding_strg, = out
        g_coding = np.zeros_like(coding_dist)
        for i in xrange(len(g_y)):
            g_coding[i, true_one_of_n[i]] = (-g_y[i] /
                                             coding_dist[i, true_one_of_n[i]])
        g_coding_strg[0] = g_coding

    def infer_shape(self, node, in_shapes):
        return [in_shapes[1]]

cosine_similarity_1hot_grad = CosineSimilarity1HotGrad()


class CosineSimilarity1Hot(gof.Op):
    """
    Compute the cross entropy between a coding distribution and
    a true distribution of the form [0, 0, ... 0, 1, 0, ..., 0].
    .. math::
        y[i] = - \log(coding_dist[i, one_of_n[i])
    Notes
    -----
    In the case that the coding distribution is the output of a
    softmax, an application of this Op will probably be optimized
    away in favour of one with a C implementation.
    """
    __props__ = ()

    def make_node(self, coding_dist, true_one_of_n):
        """
        Parameters
        ----------
        coding_dist : dense matrix
        true_one_of_n : lvector
        Returns
        -------
        dvector
        """
        _coding_dist = tensor.as_tensor_variable(coding_dist)
        _true_one_of_n = tensor.as_tensor_variable(true_one_of_n)
        if _coding_dist.type.ndim != 2:
            raise TypeError('matrix required for argument: coding_dist')
        if _true_one_of_n.type not in (tensor.lvector, tensor.ivector):
            raise TypeError(
                'integer vector required for argument: true_one_of_n'
                '(got type: %s instead of: %s)' % (_true_one_of_n.type,
                                                   tensor.lvector))

        return Apply(self, [_coding_dist, _true_one_of_n],
                     [tensor.Tensor(dtype=_coding_dist.dtype,
                      broadcastable=[False])()])

    def perform(self, node, inp, out):
        coding, one_of_n = inp
        y_out, = out
        y = np.zeros_like(coding[:, 0])
        for i in xrange(len(y)):
            y[i] = -np.log(coding[i, one_of_n[i]])
            y[i] = 1. - T.sum(true_dist * coding_dist[0],  axis= -1)
        y_out[0] = y

    def infer_shape(self, node, in_shapes):
        return [(in_shapes[0][0],)]

    def grad(self, inp, grads):
        coding, one_of_n = inp
        g_y, = grads
        return [cosine_similarity_1hot_grad(g_y, coding, one_of_n),
                grad_not_implemented(self, 1, one_of_n)]

cosine_similarity_1hot = CosineSimilarity1Hot()

Попытка обменять функцию потерь в этой архитектуре здесь

И вышеупомянутое должно быть вызвано через эту строку

# Calculate the categorical cross entropy between the labels and the prediction
t_loss = cosine_similarity(prediction, target_var) #T.nnet.categorical_crossentropy(prediction, target_var)
...