如何在 Keras/Tensorflow 中编写使用循环/迭代并参考 numpy 代码的自定义损失函数

CMC*_*kai 3 python keras tensorflow pytorch

我看到这个问题:Implementing custom loss function in keras with condition我需要做同样的事情,但代码似乎需要循环。

我有一个自定义numpy函数,可以计算与平均向量的平均欧几里得距离。我根据论文https://arxiv.org/pdf/1801.05365.pdf写了这篇文章:

方程图

import numpy as np

def mean_euclid_distance_from_mean_vector(n_vectors):

    dists = []

    for (i, v) in enumerate(n_vectors):
        n_vectors_rest = n_vectors[np.arange(len(n_vectors)) != i]

        print("rest of vectors: ")
        print(n_vectors_rest)

        # calculate mean vector
        mean_rest = n_vectors_rest.mean(axis=0)

        print("mean rest vector")
        print(mean_rest)

        dist = v - mean_rest

        print("dist vector")
        print(dist)
        dists.append(dist)

    # dists is now a matrix of distance vectors (distance from the mean vector)
    dists = np.array(dists)

    print("distance vector matrix")
    print(dists)

    # here we matmult each vector
    # sum them up
    # and divide by the total number of elements
    result = np.sum([np.matmul(d, d) for d in dists]) / dists.size

    return result


features = np.array([
    [1,2,3,4],
    [4,3,2,1]
])

c = mean_euclid_distance_from_mean_vector(features)

print(c)
Run Code Online (Sandbox Code Playgroud)

tensorflow但是我需要这个函数才能在Keras 中工作。所以自定义 lambda https://www.tensorflow.org/api_docs/python/tf/keras/layers/Lambda

但是,我不确定如何在 Keras/Tensorflow 中实现上述内容,因为它有循环,并且论文中讨论的计算方式似乎m_i需要循环,就像我实现上面的方式一样。

作为参考,此代码的 PyTorch 版本位于: https: //github.com/PramuPerera/DeepOneClass

Índ*_*dio 5

给定一个特征图,例如:

\n\n
features = np.array([\n    [1, 2, 3, 4],\n    [2, 4, 4, 3],\n    [3, 2, 1, 4],\n], dtype=np.float64)\n
Run Code Online (Sandbox Code Playgroud)\n\n

batch_size反映了一个

\n\n
batch_size = features.shape[0]\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
k = features.shape[1]\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 Tensorflow 中实现上述公式可以通过以下方式表达(原型化):

\n\n
dim = (batch_size, features.shape[1])\ndef zero(i):\n    arr = np.ones(dim)\n    arr[i] = 0\n    return arr\n\n\nmapper = [zero(i) for i in range(batch_size)]\nelems = (features, mapper)\nm = (1 / (batch_size - 1)) * tf.map_fn(lambda x: tf.math.reduce_sum(x[0] * x[1], axis=0), elems, dtype=tf.float64)\npairs = tf.map_fn(lambda x: tf.concat(x, axis=0) , tf.stack([features, m], 1), dtype=tf.float64)\ncompactness_loss = (1 / (batch_size * k)) * tf.map_fn(lambda x: tf.math.reduce_euclidean_norm(x), pairs, dtype=tf.float64)\n\nwith tf.Session() as sess:\n    print("loss value output is: ", compactness_loss.eval())\n
Run Code Online (Sandbox Code Playgroud)\n\n

其产量:

\n\n
loss value output is:  [0.64549722 0.79056942 0.64549722]\n
Run Code Online (Sandbox Code Playgroud)\n\n

但批量需要单次测量,因此需要减少;通过所有值的总和。

\n\n

Tensorflow 所需的紧凑性损失函数 \xc3\xa0 为:

\n\n
def compactness_loss(actual, features):\n    features = Flatten()(features)\n    k = 7 * 7 * 512\n    dim = (batch_size, k)\n\n    def zero(i):\n        z = tf.zeros((1, dim[1]), dtype=tf.dtypes.float32)\n        o = tf.ones((1, dim[1]), dtype=tf.dtypes.float32)\n        arr = []\n        for k in range(dim[0]):\n            arr.append(o if k != i else z)\n        res = tf.concat(arr, axis=0)\n        return res\n\n    masks = [zero(i) for i in range(batch_size)]\n    m = (1 / (batch_size - 1)) * tf.map_fn(\n        # row-wise summation\n        lambda mask: tf.math.reduce_sum(features * mask, axis=0),\n        masks,\n        dtype=tf.float32,\n    )\n    dists = features - m\n    sqrd_dists = tf.pow(dists, 2)\n    red_dists = tf.math.reduce_sum(sqrd_dists, axis=1)\n    compact_loss = (1 / (batch_size * k)) * tf.math.reduce_sum(red_dists)\n    return compact_loss\n
Run Code Online (Sandbox Code Playgroud)\n\n

当然,Flatten()为了方便起见,可以将其移回模型中,并且k可以直接从特征图中导出;这回答了你的问题。您可能只是在找出模型的预期值时遇到一些麻烦 - 例如针对 VGG16(或任何其他架构)训练的特征图imagenet

\n\n

论文称:

\n\n
\n

在我们的公式中(如图 2 (e) 所示),从预训练的深度模型开始,我们冻结初始特征 (gs) 并学习 (gl) 和 (hc)。基于分类子网络(hc)的输出,评估两个损失:紧凑性损失和描述性损失。后续部分介绍的这两个损失用于评估学习的深度特征的质量。我们使用提供的一类数据集来计算紧凑性损失。使用外部多类参考数据集来评估描述性损失。如图3所示,在所提出的方法中,gl和hc的权重是通过复合损失的反向传播来学习的。一旦训练收敛,图 2(d) 中设置所示的系统将用于执行分类,其中生成的模型用作预训练模型。

\n
\n\n

然后看看这里的“框架”主干加上:

\n\n
\n

AlexNet 二进制和 VGG16 二进制(基线)。通过分别使用 AlexNet 和 VGG16 架构将 ImageNet 样本和一类图像样本作为两个类别来训练二值 CNN。使用 k 最近邻、一类 SVM [43]、隔离森林 [3] 和高斯混合模型 [3] 分类器进行测试。

\n
\n\n

Secondary让我想知道将建议的密集层添加到和Reference网络到单类输出(Sigmoid)或偶数和二进制类输出(使用 Softmax)并使用mean_squared_error所谓的紧凑性损失和binary_cross_entropy作为是否不合理描述性损失。

\n