title: Save/load a Keras model with (constant) parameters
body: <p>My case similar to, but a little different from, <a href="https://stackoverflow.com/questions/52413371/save-load-a-keras-model-with-constants">"Save/load a keras model with constants"</a></p>
  
  <p>I'm creating an object detection model (based on <a href="https://pjreddie.com/darknet/yolo/" rel="nofollow noreferrer">YOLO</a>) in <code>tf.keras</code> (TFv1.12, yes I know) whose raw outputs need to be post-processed into bounding boxes.</p>
  
  <p>This involves a few parameters which are constant for the purposes of the model, but <em>parameters to the script that builds the model</em>: E.g. the number of classes, and the matrix of "anchor" locations to generate boxes relative to.</p>
  
  <p>My model will be loaded into a TFServing container, so I'm trying to make sure:</p>
  
  <ol>
  <li>The transformation is encapsulated within the model, rather than making users do it or splitting out post-processing logic</li>
  <li>The saved model artifacts (e.g. Keras h5, or TF pb+params) are sufficient to load and serve the model </li>
  </ol>
  
  <p>What's the right way to do this?</p>
  
  <p>As far as I've been able to tell, the following <strong>don't</strong> work:</p>
  
  <pre class="lang-py prettyprint-override"><code>import numpy as np
  import tensorflow as tf
  from tensorflow import keras
  from tensorflow.keras import backend as K
  from tensorflow.keras.layers import Lambda, Layer
  
  # Lambda layer using closure scope triggers error when trying to load the model:
  # seems like `param` is defined but some weird object
  def make_output_lambda(param):
      def mylambda(raw_output):
          return raw_output + param
      return Lambda(mylambda)
  
  # Even if the custom layer type is added to `custom_objects` on
  # `tf.keras.models.load_model()` - it seems to get called without the positional
  # arguments:
  class MyCustomLayer(Layer):
      def __init__(self, param, **kwargs):
          super(YOLOHeadLayer, self).__init__(**kwargs)
          self.param = param  # or K.constant(param) - same overall problem
  
      def call(self, inputs):
          return inputs + self.param
  
  # Keras throws an error when creating a `Model` that depends on a constant
  # tensor which isn't an `Input` (and who wants a constant "Input"?)
  def lambdatwo(inputs):
      return inputs[0] + inputs[1]
  param_tensor = K.constant(param)
  y = Lambda(lambdatwo)((raw_output, param_tensor))
  </code></pre>