ssim 作为自动编码器中的自定义损失函数(keras or/and tensorflow)

ssim as custom loss function in autoencoder (keras or/and tensorflow)

我目前正在编写一个用于图像压缩的自动编码器。从 我现在最终确认我不能在 Keras 和 tensorflow 中使用纯 Python 函数作为损失函数。 (而且我正在慢慢开始理解为什么 ;-)

我想用 ssim as a loss function and as a metric. Now it seems I might be lucky. There is already an implementation of it in tensorflow, see: https://www.tensorflow.org/api_docs/python/tf/image/ssim

做一些实验

tf.image.ssim( img1, img2, max_val )

此外,bsautermeister 在这里提供了一个关于 Whosebug 的实现:.

我现在的问题是:如何将它用作损失函数,使用 mnist 数据集?该函数不接受张量,只接受两个图像。而且,梯度会自动计算吗?据我了解,如果该功能是在 tensorflow 或 keras 后端实现的。

我将非常感谢关于如何在 keras 或 tensorflow 中使用任何前面提到的 ssim 实现作为损失函数的最小工作示例 (MWE)。

也许我们可以将我的 MWE 用于我上一个问题提供的自动编码器:

如果无法将我的 keras 自动编码器与 ssim 实现粘合在一起,是否可以使用直接在 tensorflow 中实现的自动编码器?我也有,可以提供吗?

我正在使用 python 3.5、keras(带有 tensorflow 后端),如果需要,直接使用 tensorflow。 目前我正在使用 (带有数字的那个)。

感谢您的帮助!

(P.S.: 似乎有几个人在做类似的事情。对此 post 的回答也可能对 Keras - MS-SSIM as loss function)

有用

我不能用 Keras 服务,但在普通的 TensorFlow 中,你只需切换 L2 或使用 SSIM 结果的任何成本,如

import tensorflow as tf
import numpy as np


def fake_img_batch(*shape):
    i = np.random.randn(*shape).astype(np.float32)
    i[i < 0] = -i[i < 0]
    return tf.convert_to_tensor(np.clip(i * 255, 0, 255))


fake_img_a = tf.get_variable('a', initializer=fake_img_batch(2, 224, 224, 3))
fake_img_b = tf.get_variable('b', initializer=fake_img_batch(2, 224, 224, 3))

fake_img_a = tf.nn.sigmoid(fake_img_a)
fake_img_b = tf.nn.sigmoid(fake_img_b)

# costs = tf.losses.mean_squared_error(fake_img_a, fake_img_b, reduction=tf.losses.Reduction.MEAN)
costs = tf.image.ssim(fake_img_a, fake_img_b, 1.)
costs = tf.reduce_mean(costs)

train = tf.train.AdamOptimizer(0.01).minimize(costs)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print(sess.run(costs))
    for k in range(500):
        _, l = sess.run([train, costs])
        if k % 100 == 0:
            print('mean SSIM', l)

检查操作是否具有梯度(已实现)非常简单:

import tensorflow as tf
import numpy as np


def fake_img_batch(*shape):
    i = np.random.randn(*shape).astype(np.float32)
    i[i < 0] = -i[i < 0]
    return tf.convert_to_tensor(np.clip(i * 255, 0, 255))

x1 = tf.convert_to_tensor(fake_img_batch(2, 28, 28, 3))
x2 = tf.convert_to_tensor(fake_img_batch(2, 28, 28, 3))


y1 = tf.argmax(x1)  # not differentiable -> no gradients
y2 = tf.image.ssim(x1, x2, 255) # has gradients

with tf.Session() as sess:
    print(tf.gradients(y1, [x1]))  # will print [None] --> no gradient
    print(tf.gradients(y2, [x1, x2]))  # will print [<tf.Tensor 'gradients ...>, ...] --> has gradient