Skip to main content
 首页 » 编程设计

python之ssim 作为自动编码器中的自定义损失函数(keras 或/和 tensorflow)

2024年12月31日28dudu

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

我想用 ssim 做一些实验作为损失函数和度量。现在看来我可能是幸运的。在 tensorflow 中已经有它的实现,参见:https://www.tensorflow.org/api_docs/python/tf/image/ssim

tf.image.ssim( img1, img2, 最大值 )

此外,bsautermeister 在 stackoverflow 上提供了一个实现:SSIM / MS-SSIM for TensorFlow .

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

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

也许我们可以将我的 MWE 用于我上一个问题提供的自动编码器: keras custom loss pure python (without keras backend)

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

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

感谢您的帮助!

(附:几个人似乎在做类似的事情。这篇文章的答案可能对 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