2015-11-04 117 views
1

我在Theano中有一个简单的工作多层感知器,具有1个隐藏层和1个回退层以及2个输出。在回归层中,定义了一个均方误差函数,用作成本函数。然而,在学习期间,我现在想要最小化两个向量之间的余弦距离,所以我想将余弦距离用作代价函数。在我目前实施的一些相关部分下面。最小化余弦距离theano

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中的均方误差函数有什么不同。我在这里错过什么?

回答

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) 
+0

谢谢!我认为我的错误来自误解T.dot(),显然T.dot(x,y)与T.sum(x * y)不同。 – Semi