我想用Python和Keras训练一个神经网络,使用一个度量学习自定义损失函数。这种损耗使相似输入的输出距离最小,而使不同输入之间的距离最大。考虑类似输入的部分是:
# function to create a pairwise similarity matrix, i.e
# L[i,j] == 1 for similar samples i, j and 0 otherwise
def build_indicator_matrix(y_, thr=0.1):
# y_: contains the labels of the samples,
# samples are similar in case of same label
# prevent checking equality of floats --> check if absolute
# differences are below threshold
lbls_diff = K.expand_dims(y_, axis=0) - K.expand_dims(y_, axis=1)
lbls_thr = K.less(K.abs(lbls_diff), thr)
# cast bool tensor back to float32
L = K.cast(lbls_thr, 'float32')
# POSSIBLE WORKAROUND
#L = K.sum(L, axis=2)
return L
# function to compute the (squared) Euclidean distances between all pairs
# of samples, store in DIST[i,j] the distance between output y_pred[i,:] and y_pred[j,:]
def compute_pairwise_distances(y_pred):
DIFF = K.expand_dims(y_pred, axis=0) - K.expand_dims(y_pred, axis=1)
DIST = K.sum(K.square(DIFF), axis=-1)
return DIST
# function to compute the average distance between all similar samples
def my_loss(y_true, y_pred):
# y_true: contains true labels of the samples
# y_pred: contains network outputs
L = build_indicator_matrix(y_true)
DIST = compute_pairwise_distances(y_pred)
return K.mean(DIST * L, axis=1)
为了训练,我将一个形状为(n,)
的numpy数组y
作为目标变量传递给my_loss
。但是,我发现(使用TensorBoard中的计算图)tensorflow后端在y
(显示的形状? x ?
)之外创建了一个2D变量,因此build_indicator_matrix
中的L
不是2维的,而是3维的(TensorBoard中的形状? x ? x ?
)。这会导致net.evaulate()
和net.fit()
计算错误的结果。你知道吗
为什么tensorflow创建的是二维数组而不是一维数组?这对net.evaluate()
和net.fit()
有何影响?你知道吗
作为快速的解决方法,我发现要么用静态numpy代码替换build_indicator_matrix()
来计算L
,要么用L = K.sum(L, axis=2)
行折叠“伪”维度就解决了问题。然而,在后一种情况下,K.eval(build_indicator_matrix(y))
的输出只是形状(n,)
而不是(n,n)
,所以我不明白为什么这种解决方法仍然产生正确的结果。为什么张量流引入了一个额外的维度?你知道吗
我的库版本是:
这是因为
evaluate
和fit
分批工作。 您在tensorboard中看到的第一个维度是批处理维度,它事先未知,因此表示为?
。 使用自定义度量时,请记住所得到的张量(y_true
和y_pred
)是与批处理对应的张量。你知道吗有关更多信息,请演示如何调用这两个函数。你知道吗
相关问题 更多 >
编程相关推荐