最小化余弦距离theano
Minimize cosine distance 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 中的均方误差函数有何不同。我在这里想念什么?
不同之处在于,在您的 mse
函数中计算 T.mean
时未指定轴,因此给出张量中所有条目的平均值,无论张量可能是什么形状。相比之下,您的第一个 cos
函数根本不会聚合,因此 return 值将具有与 T.dot(y,self.y_pred)
相同的形状,即不是标量。您在生成所需标量的 cos
函数的第二个版本中求和,但这可能无法计算您希望它计算的内容,具体取决于输入形状的语义。
第二个错误可能是由于您的 cos
函数中的错误:您不想在分子中执行点积,即 T.dot(y,self.y_pred)
,而是希望按元素计算乘法,例如y * self.y_pred
这是我在 Theano 中执行各种距离的代码。请注意,_magnitude
和 cosine
函数包括有助于避免 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)
我在 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 中的均方误差函数有何不同。我在这里想念什么?
不同之处在于,在您的 mse
函数中计算 T.mean
时未指定轴,因此给出张量中所有条目的平均值,无论张量可能是什么形状。相比之下,您的第一个 cos
函数根本不会聚合,因此 return 值将具有与 T.dot(y,self.y_pred)
相同的形状,即不是标量。您在生成所需标量的 cos
函数的第二个版本中求和,但这可能无法计算您希望它计算的内容,具体取决于输入形状的语义。
第二个错误可能是由于您的 cos
函数中的错误:您不想在分子中执行点积,即 T.dot(y,self.y_pred)
,而是希望按元素计算乘法,例如y * self.y_pred
这是我在 Theano 中执行各种距离的代码。请注意,_magnitude
和 cosine
函数包括有助于避免 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)