最小化余弦距离theano

时间:2015-11-04 14:03:52

标签: python python-2.7 theano

我在Theano中有一个简单且有效的多层感知器,有1个隐藏层和1个回归层,有2个输出。在回归层中,定义均方误差函数,其用作成本函数。然而,在学习期间我现在想要最小化两个向量之间的余弦距离,所以我想使用余弦距离作为成本函数。下面是我当前实现的一些相关部分。

import theano
import theano.tensor as T

class RegressionLayer(object):
    def __init__(self, input, n_in, n_out, W=None, b=None):
        # rest of __init__ left out for brevity

    def mse(self, y):
        return T.mean(T.sqr(y - self.y_pred))

    def cos(self, y):
        return 1. - (T.dot(y,self.y_pred) / (T.sqrt(T.sum(T.sqr(y)) * T.sum(T.sqr(self.y_pred)))))

如果我将费用函数从mse(y)更改为cos(y),我会收到以下错误:

TypeError: cost must be a scalar.

我不明白为什么费用(函数)不会是标量。只是为了测试我试过:

def cos(self, y):
    T.sum(1. - (T.dot(y,self.y_pred) / (T.sqrt(T.sum(T.sqr(y)) * T.sum(T.sqr(self.y_pred))))))

然后该模型构建,但在训练期间我得到尺寸不匹配。

ValueError: dimension mismatch in args to gemm (1,2)x(1,2)->(1,2)

我认为问题在于我没有看到我的余弦距离函数与Theano中的均方误差函数有何不同。我在这里想念什么?

1 个答案:

答案 0 :(得分:3)

不同之处在于,mse函数在不指定轴的情况下计算T.mean,因此给出张量中所有条目的均值,无论张量可能是什么形状。相比之下,您的第一个cos函数根本不会聚合,因此返回值将具有与T.dot(y,self.y_pred)相同的形状,即不是标量。您在cos函数的第二个版本中求和,它生成所需的标量,但这可能无法计算您想要计算的内容,具体取决于输入形状的语义。

第二个错误可能是由于cos函数中的错误:您不想在分子中执行点积,即T.dot(y,self.y_pred),而是希望逐元素乘法,例如y * self.y_pred

这是我在Theano中做各种距离的代码。请注意,_magnitudecosine功能包括有助于避免NaN或超出范围值的调整。这些问题可能发生在正向传递或反向传递(渐变)中。

import numpy
import theano.tensor as tt


def _squared_magnitude(x):
    return tt.sqr(x).sum(axis=-1)


def _magnitude(x):
    return tt.sqrt(tt.maximum(_squared_magnitude(x), numpy.finfo(x.dtype).tiny))


def cosine(x, y):
    return tt.clip((1 - (x * y).sum(axis=-1) / (_magnitude(x) * _magnitude(y))) / 2, 0, 1)


def euclidean(x, y):
    return _magnitude(x - y)


def squared_euclidean(x, y):
    return _squared_magnitude(x - y)