Функция SSIM в TensorFlow 2.x

Я пытаюсь использовать tf.image.ssim () в качестве функции потерь для обучения моей модели, и я немного исследовал, как люди ее реализовали. Они здесь:

  1. Работа с функцией потерь SSIM в тензорном потоке для изображений RGB
  2. Использование функции потери SSIM с Keras

У меня пара вопросов:

  1. В обоих этих потоках динамический диапазон, предложенный для tf.image.ssim, равен 2, когда входные данные нормализованы между -1 и 1. Но я провел небольшую проверку работоспособности, чтобы увидеть, работает это или нет. Вот код:
from PIL import Image
import numpy as np
from skimage.util import random_noise
import matplotlib.pyplot as plt
import tensorflow as tf

im = Image.open('E:\\DATA\\train_image_(124).png')
im_arr = np.asarray(im) # convert PIL Image to ndarray

noise_img = random_noise(im_arr, mode='gaussian', var=0.0005) # random_noise() method will convert image in [0, 255] to [0, 1.0]
noise_img = (255*noise_img).astype(np.uint8)

img = Image.fromarray(noise_img)

#normalizing between 0 and 1 and reshaping for SSIM calculation
x = np.reshape((np.asarray(im)/255), [256, 256, 1])
y = np.reshape((np.asarray(img)/255), [256, 256, 1])

#normalizing between -1 and 1 and reshaping for SSIM calculation
x_a = np.reshape((2*(np.asarray(im)/255) - 1), [256, 256, 1])
y_a = np.reshape((2*(np.asarray(img)/255) - 1), [256, 256, 1])

print('No norm: ', str(tf.image.ssim(np.reshape(im_arr, [256, 256, 1]), np.reshape(noise_img, [256, 256, 1]), 255).numpy()))
print('Norm_01: ', str(tf.image.ssim(x, y, 1).numpy()))
print('Norm_11: ', str(tf.image.ssim(x_a, y_a, 2).numpy()))

Насколько я понимаю, все 3 оператора печати должны давать одно и то же значение SSIM, но это не так. Когда диапазон составляет от 0 до 1 и от 0 до 255, результат SSIM будет таким же, но с диапазоном от - 1 до 1 он будет другим. Чтобы дважды проверить, я также вычислил SSIM в MATLAB, и это почти согласуется с первыми двумя случаями. Итак, есть ли другой способ вычислить SSIM / использовать SSIM как функцию потерь в TF2? Я проделал тот же эксперимент с compare_ssim из skimage, но тот, похоже, дал тот же результат. Я что-то упускаю?

  1. Кроме того, когда я использую tf.reduce_mean(tf.keras.losses.mean_squared_error(target, gen_output)) в качестве функции потерь, все в порядке. Но когда я использую tf.reduce_mean(tf.image.ssim(x, y, dynamic_range) в качестве функции потерь, я получаю значения NaN. Оба упомянутых выше потока используют для обучения tenorflow 1.x или model.fit на tensorflow2.x, в то время как я использую tf.GradientTape() для вычисления градиента и обновления весов. Возможно ли, что функция GradientTape отвечает за возврат значений NaN? Если да, то почему и что может быть возможным решением?

person shaurov2253    schedule 04.12.2020    source источник