Keras 张量有一个额外的维度并导致 net.evaluate() 的错误结果

Posted

技术标签:

【中文标题】Keras 张量有一个额外的维度并导致 net.evaluate() 的错误结果【英文标题】:Keras tensor has an additional dimension and causes wrong results for net.evaluate() 【发布时间】:2019-12-25 00:02:03 【问题描述】:

我想使用度量学习自定义损失函数在 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 维(形状 ? x ? x ? 在 TensorBoard 中)。这会导致net.evaulate()net.fit() 计算错误的结果。

为什么 tensorflow 创建 2D 而不是 1D 数组?这对net.evaluate()net.fit() 有何影响?

作为快速解决方法,我发现将 build_indicator_matrix() 替换为用于计算 L 的静态 numpy 代码,或者使用 L = K.sum(L, axis=2) 行折叠“假”维度可以解决问题。然而,在后一种情况下,K.eval(build_indicator_matrix(y)) 的输出只有(n,) 的形状而不是(n,n),所以我不明白为什么这种解决方法仍然会产生正确的结果。为什么 tensorflow 会引入额外的维度?

我的库版本是:

keras:2.2.4 张量流:1.8.0 numpy:1.15.0

【问题讨论】:

【参考方案1】:

这是因为evaluatefit 分批工作。 您在 tensorboard 中看到的第一个维度是批量维度,事先未知,因此表示为 ?。 使用自定义指标时,请记住您获得的张量(y_truey_pred)是与批次对应的张量。

有关详细信息,请向我们展示您如何调用这两个函数。

【讨论】:

以上是关于Keras 张量有一个额外的维度并导致 net.evaluate() 的错误结果的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Keras / Tensorflow 中将(无,)批量维度重新引入张量?

为啥 Keras Conv1D 层的输出张量没有输入维度?

理解keras中的数据表示形式:张量

在 Keras 中,如何任意调整一维张量的大小?

keras中一维卷积网络的输入维度

使用张量流在 keras 中对损失函数的输入进行切片