keras 自定义损失纯 python(没有 keras 后端)

keras custom loss pure python (without keras backend)

我目前正在编写一个用于图像压缩的自动编码器。我想使用纯 python 编写的自定义损失函数,即不使用 keras 后端函数。这完全有可能吗?如果有的话怎么办? 如果可能的话,我将非常感谢一个最低限度的工作示例(MWE)。 请查看此 MWE,特别是 mse_keras 函数:

# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
import numpy as np
import keras.backend as K
from keras.datasets import mnist
from keras.models import Model, Sequential
from keras.layers import Input, Dense


def mse_keras(A,B):
    mse = K.mean(K.square(A - B), axis=-1)
    return mse


# Loads the training and test data sets (ignoring class labels)
(x_train, _), (x_test, _) = mnist.load_data()

# Scales the training and test data to range between 0 and 1.
max_value = float(x_train.max())
x_train = x_train.astype('float32') / max_value
x_test = x_test.astype('float32') / max_value


x_train.shape, x_test.shape
# ((60000, 28, 28), (10000, 28, 28))


x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:])))
x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:])))

(x_train.shape, x_test.shape)
# ((60000, 784), (10000, 784))


# input dimension = 784
input_dim = x_train.shape[1]
encoding_dim = 32

compression_factor = float(input_dim) / encoding_dim
print("Compression factor: %s" % compression_factor)

autoencoder = Sequential()
autoencoder.add(Dense(encoding_dim, input_shape=(input_dim,), activation='relu'))
autoencoder.add(Dense(input_dim, activation='sigmoid'))

autoencoder.summary()

input_img = Input(shape=(input_dim,))
encoder_layer = autoencoder.layers[0]
encoder = Model(input_img, encoder_layer(input_img))

encoder.summary()


autoencoder.compile(optimizer='adam', loss=mse_keras, metrics=['mse'])
history=autoencoder.fit(x_train, x_train,
                        epochs=3,
                        batch_size=256,
                        shuffle=True,
                        validation_data=(x_test, x_test))

num_images = 10
np.random.seed(42)
random_test_images = np.random.randint(x_test.shape[0], size=num_images)

decoded_imgs = autoencoder.predict(x_test)


#print(history.history.keys())

plt.figure()
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])

plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test', 'mse1', 'val_mse1'], loc='upper left')
plt.show()


plt.figure(figsize=(18, 4))

for i, image_idx in enumerate(random_test_images):
    # plot original image
    ax = plt.subplot(3, num_images, i + 1)
    plt.imshow(x_test[image_idx].reshape(28, 28))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # plot reconstructed image
    ax = plt.subplot(3, num_images, 2*num_images + i + 1)
    plt.imshow(decoded_imgs[image_idx].reshape(28, 28))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()

上面的代码是使用 Keras 后端的自定义损失函数的 MWE。然而,这不是我想要的!我想用这样的东西替换我代码中的 mse_keras 函数:

def my_mse(A,B):
    mse = ((A - B) ** 2).mean(axis=None)
    return mse

这又只是一个 MWE。它是纯粹的 python 和 scipy。没有 KERAS 后端! 是否可以使用纯 python 函数作为损失函数(我尝试使用 py_func,但它对我不起作用。) 我问的原因是因为最终我想使用一种已经在 python 中实现的更复杂的损失函数。而且,我不知道如何使用 keras 后端重新实现它。 (老实说,我也没有时间这样做)

(对于好奇:我想用作损失函数的函数可以在这里看到:https://github.com/aizvorski/video-quality

如有任何帮助,我们将不胜感激。后端可以是theano,tensorflow,我不在乎。如果可能,请在 python 3.X.

中向我提供 MWE

非常感谢。非常感谢您的帮助。

您不能使用纯 Python 函数作为 Keras 的损失。由于您可能在 GPU 上训练并且 python 使用 CPU 这会通过将结果 from/to 传输到 GPU 内存来产生开销。

来自 https://keras.io/losses/

You can either pass the name of an existing loss function, or pass a TensorFlow/Theano symbolic function that returns a scalar for each data-point and takes the following two arguments: y_true, y_pred

你的函数是(和原来的一样)

def my_mse(A,B):
    mse = K.mean(K.pow(A - B, 2), axis=None)
    return mse

但是,检查 Keras API,它需要每个数据点的标量,所以取平均值可能不会像这样使用 axis=None

我快速浏览了您链接的损失函数,在 Keras 中实现它们应该是可能的,而且不太困难。 Keras(或实际上是后端 Tensorflow)具有与 numpy 类似的接口。了解后端的计算图(即 tensorflow)如何实现损失可能会有用。