2015-11-04 119 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