我目前正在为图像压缩编写自动编码器。我想使用以纯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。
非常感谢。非常感谢您的帮助。
答案 0 :(得分:2)
不能将纯Python函数用作Keras的损失。当您可能在GPU上训练并且python使用CPU时,这会通过从GPU内存传输结果到GPU内存而产生开销。
您可以传递现有损失函数的名称,也可以传递TensorFlow / Theano 符号函数,该函数为每个数据点返回标量,并采用以下两个参数:y_true,y_pred < / p>
您的功能将是(与原始功能相同)
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类似的接口。了解后端的计算图(即张量流)如何实现损失可能很有用。