我想定义一个损失函数,它表示隐藏层输出点之间的距离。首先,我写的是没有喀拉斯语的
import numpy as np
import itertools
pts = np.array([
[10,10,10],
[10,11,20],
[20,11,30],
[20,10,10],
[10,10,20],
])
diff = list(itertools.combinations(pts, 2))
ptdiff = lambda (p1,p2): (np.sqrt(np.sum((p1 - p2) ** 2)))
diffs = map(ptdiff, diff)
np.mean(diffs)
我得到结果。我尝试在keras中使用此损失函数,z
是隐藏层的输出,它是矩阵
def vae_loss(z):
z_diff = list(itertools.combinations(z,2))
ptdiff = lambda (p1,p2): (np.sqrt(np.sum((p1 - p2) ** 2)))
z_diffs = map(ptdiff, z_diff)
loss = K.mean(z_diffs)
return loss
但是它显示了TypeError: 'Tensor' object is not iterable.
,我只是想知道如何解决此问题。
答案 0 :(得分:0)
基于非常有用的问题this,您可以利用Keras的广播属性。我假设您在TensorFlow后端上运行Keras。来自TF docs的广播:
在每种情况下都会出现一种特殊情况,并且这种情况也得到支持 数组在不同的索引处具有退化的维。在这种情况下, 结果是“外部操作”。
以下是您的numpy代码的可复制示例:
import numpy as np
import itertools
# Generate 100 random points in a 5-D space
n_dim = 5
matrix = np.random.rand(1000, 5)
# List all possible combinations
combinations = list(itertools.combinations(matrix.tolist(), 2))
def mse(tup):
"""MSE between first and second element of a tuple of lists"""
return np.mean((np.array(tup[0]) - np.array(tup[1]))**2)
avg_mse = np.mean([mse(c) for c in combinations])
print('Average mse: {:.3f}'.format(avg_mse))
对于我来说,这返回Average mse: 0.162
基于上面提到的问题,您可以按以下方式构造损失函数:
import keras.backend as K
# Wrap our random matrix into a tensor
tensor = K.constant(value=matrix)
def loss_function(x):
x_ = K.expand_dims(tensor, axis=0)
x__ = K.expand_dims(tensor, axis=1)
# Compute mse for all combinations, making use of broadcasting
z = K.mean(K.square(x_ - x__), axis=-1)
# Return average mse
return(K.mean(z))
with K.get_session() as sess:
print('Average mse: {:.3f}'.format(loss_function(tensor).eval()))
Average mse: 0.162
为我回来的人。
请注意,此实现不能完全复制您的numpy示例中的行为。不同之处在于,还考虑了行本身的所有组合(itertools.combinations
则不这样),并且组合被考虑了两次:mse((row1, row2))
和mse((row2, row1))
都将被计算,这再次不被考虑。您的itertools
代码的情况。如我的示例所示,对于具有大量行的矩阵,这不应有太大的区别。