1
$\begingroup$

I have written a SRGAN implementation. In the entry point class of the Python program, I declare a function which returns a mean square using the VGG19 model:

# <!--- COST FUNCTION --->
def build_vgg19_loss_network(ground_truth_image, predicted_image):
    loss_model = Vgg19Loss.define_loss_model(high_resolution_shape)
    return mean(square(loss_model(ground_truth_image) - loss_model(predicted_image)))

import keras.losses
keras.losses.build_vgg19_loss_network = build_vgg19_loss_network
# <!--- /COST FUNCTION --->

(Vgg19Loss class shown further below)

As you can see, I have added this custom loss function in the import keras.losses. Why? Because I thought it could solve the following problem...: When I execute the command tflite_convert --output_file=srgan.tflite --keras_model_file=srgan.h5, the Python interpreter raises this error:

raise ValueError('Unknown ' + printable_module_name + ':' + object_name) ValueError: Unknown loss function:build_vgg19_loss_network

However, it didn't solve the problem. Any other solution which could work?

Here is the Vgg19Loss class:

from keras import Model
from keras.applications import VGG19


class Vgg19Loss:
    def __init__(self):
        pass

    @staticmethod
    def define_loss_model(high_resolution_shape):
        model_vgg19 = VGG19(False, 'imagenet', input_shape=high_resolution_shape)
        model_vgg19.trainable = False
        for l in model_vgg19.layers:
            l.trainable = False
        loss_model = Model(model_vgg19.input, model_vgg19.get_layer('block5_conv4').output)
        loss_model.trainable = False
        return loss_model
$\endgroup$
1
+100
$\begingroup$

I tried the code you posted the following way:

from keras import Model
from keras.applications import VGG19
import keras.backend as K


class Vgg19Loss:
    def __init__(self):
        pass

    @staticmethod
    def define_loss_model(high_resolution_shape):
        model_vgg19 = VGG19(False, 'imagenet', input_shape=high_resolution_shape)
        model_vgg19.trainable = False
        for l in model_vgg19.layers:
            l.trainable = False
        loss_model = Model(model_vgg19.input, model_vgg19.get_layer('block5_conv4').output)
        loss_model.trainable = False
        return loss_model


def build_vgg19_loss_network(ground_truth_image, predicted_image):
    loss_model = Vgg19Loss.define_loss_model(high_resolution_shape) # where is this variable coming from?
    return K.mean(K.square(loss_model(ground_truth_image) - loss_model(predicted_image)))

import keras.losses
keras.losses.build_vgg19_loss_network = build_vgg19_loss_network

print(keras.losses.build_vgg19_loss_network)  # <function build_vgg19_loss_network at 0x7f05e8e1cbf8>

I get no error messages and the function is assigned to the losses module. That means the problematic lines are probably not part of what you posted. It would be nice to know which line of code raises the error that you quoted.

However, I'm not sure where this high_resolution_shape argument on line 22 in your build_vgg_19_network function is coming from. If this is a global constant, it should be written in all uppercase letters separated by underscores to prevent confusion. If it is not defined it will throw a NameError sooner or later.

If I execute keras.losses.build_vgg19_loss_network(None, None) after running the code above, I get the following error message:

NameError: name 'high_resolution_shape' is not defined

Edit: If this error happens only during TFLite conversion, it does so because custom objects are not yet supported by the TFLiteConverter in tensorflow 1.x. However, there is a commit on the tensorflow Github repo that addresses this issue and adds support for custom objects (see also the related pull request). It should be part of the official tensorflow v2.0.0-beta1.

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ Hi @JarsOfJam-Scheduler, now I understand. Thank you for explaining that again. I edited my answer regarding this issue. $\endgroup$ – georg-un Aug 12 '19 at 10:38
  • 1
    $\begingroup$ The release can be found here. You should be able to install it with pip install https://github.com/tensorflow/tensorflow/archive/v2.0.0-beta1.zip $\endgroup$ – georg-un Aug 12 '19 at 11:19
  • 1
    $\begingroup$ @JarsOfJam-Scheduler This is an installation issue now. You can try pip install tensorflow==2.0.0-beta1 instead. Also, pip install --upgrade setuptools is always worth a try as well. Let me know if any of this helps- $\endgroup$ – georg-un Aug 12 '19 at 12:11
  • 1
    $\begingroup$ Until April, TFLite did not support custom classes. However, in April a contributor changed several lines in lite.py so that it supports custom classes. These changes were released with tensorflow v2.0.0-beta1. Earlier versions of tensorflow don't have these changes included and thereby don't support custom classes. It is this script that gets called when you run tflite_convert. That means, if you do not have v2.0.0-beta1 or above you don't have support for custom classes. $\endgroup$ – georg-un Aug 12 '19 at 12:32
  • 1
    $\begingroup$ @JarsOfJam-Scheduler Hmm, could you try to disable tensorflow 2 behaviour with import tensorflow.compat.v1 as tf and then tf.disable_v2_behavior()? It seems like there is a bug in v2.0.0-beta1 where tensorflow still ignores custom classes when v2 flags are enabled. $\endgroup$ – georg-un Aug 12 '19 at 13:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.