Керас кастомная потеря чистого питона (без кераса) - PullRequest
0 голосов
/ 24 июня 2018

Я сейчас программирую авто-кодер для сжатия изображений.Я хотел бы использовать пользовательскую функцию потерь, написанную на чистом 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()

Приведенный выше код является MWE для пользовательской функции потерь с использованием бэкэнда Keras.Однако это не то, что я хочу!Я хотел бы заменить функцию mse_keras в моем коде на что-то вроде этого:

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

Это снова просто MWE.Это чистый питон и scipy.НЕТ KERAS BACKEND!Можно ли использовать чистые функции Python в качестве функций потерь (я пытался с py_func, но у меня это не сработало). Причина, по которой я спрашиваю, заключается в том, что в конечном итоге я хотел бы использовать более сложную функцию потерь, котораяуже реализовано в Python.И я не понимаю, как я мог бы переопределить это с помощью бэкэнда keras.(У меня тоже нет времени, чтобы быть честным)

(Для любопытных: функции, которые я хотел бы использовать в качестве функции потерь, можно увидеть здесь: https://github.com/aizvorski/video-quality)

Любая помощь будет принята с благодарностью. Бэкэнд может быть theano, tenorflow, мне все равно. Если это возможно, пожалуйста, предоставьте мне MWE в python 3.X.

Большое спасибо заранее. Ваша помощь очень ценится.

1 Ответ

0 голосов
/ 24 июня 2018

Вы не можете использовать чистую функцию Python как потерю для Keras.Поскольку вы, вероятно, тренируетесь на GPU, а python использует CPU, это приведет к дополнительным расходам путем передачи результатов из / в память GPU.

из https://keras.io/losses/

Вы можете либо передатьимя существующей функции потерь или передать символическую функцию TensorFlow / Theano , которая возвращает скаляр для каждой точки данных и принимает следующие два аргумента: y_true, y_pred

Yourфункция будет (такой же, как и в оригинале)

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

Однако, проверьте API Keras, он хочет скаляр для каждой точки данных, поэтому, взяв среднее, скорее всего, не будет работать с axis=None.

Я быстро взглянул на функции потери, которые вы связали, и реализация их в Keras должна быть возможной и не слишком сложной.Keras (или фактически Tensorflow бэкэнда) имеет интерфейс, похожий на numpy.Возможно, было бы полезно понять, как вычислительный граф бэкэнда (т. Е. Тензорного потока) работает для реализации потерь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...