class_docstr: BoltOn episilon-delta model.
  
  Uses 4 key steps to achieve privacy guarantees:
  1. Adds noise to weights after training (output perturbation).
  2. Projects weights to R after each batch
  3. Limits learning rate
  4. Use a strongly convex loss function (see compile)
  
  For more details on the strong convexity requirements, see:
  Bolt-on Differential Privacy for Scalable Stochastic Gradient
  Descent-based Analytics by Xi Wu et. al.
class_docstr_tok: ["BoltOn","episilon-delta","model",".","Uses","4","key","steps","to","achieve","privacy","guarantees",":","1",".","Adds","noise","to","weights","after","training","(","output","perturbation",")",".","2",".","Projects","weights","to","R","after","each","batch","3",".","Limits","learning","rate","4",".","Use","a","strongly","convex","loss","function","(","see","compile",")","For","more","details","on","the","strong","convexity","requirements",",","see",":","Bolt-on","Differential","Privacy","for","Scalable","Stochastic","Gradient","Descent-based","Analytics","by","Xi","Wu","et",".","al","."]
docstr: Constructor.
  
  Args:
    n_outputs: number of output neurons
    input_shape:
    init_value:
docstr_tok: ["Constructor",".","Args",":","n_outputs",":","number","of","output","neurons","input_shape",":","init_value",":"]
code: def __init__(self, n_outputs=2, input_shape=(16,), init_value=2):
      """Constructor.
  
      Args:
        n_outputs: number of output neurons
        input_shape:
        init_value:
      """
      super().__init__(name="bolton", dynamic=False)
      self.n_outputs = n_outputs
      self.layer_input_shape = input_shape
      self.output_layer = tf.keras.layers.Dense(
          self.n_outputs,
          input_shape=self.layer_input_shape,
          kernel_regularizer=L1L2(l2=1),
          kernel_initializer=constant(init_value),
      )
  
imports: import unittest
  from absl.testing import parameterized
  import tensorflow.compat.v1
  from tensorflow.compat.v1.python import ops
  from tensorflow.compat.v1.python.framework import test_util
  from tensorflow.compat.v1.python.keras import keras_parameterized
  from tensorflow.compat.v1.python.keras import losses
  from tensorflow.compat.v1.python.keras.initializers import constant
  from tensorflow.compat.v1.python.keras.models import Model
  from tensorflow.compat.v1.python.keras.optimizer_v2.optimizer_v2 import OptimizerV2
  from tensorflow.compat.v1.python.keras.regularizers import L1L2
  from tensorflow.compat.v1.python.platform import test
  from tensorflow_privacy.privacy.bolt_on import optimizers
  from tensorflow_privacy.privacy.bolt_on.losses import StrongConvexMixin
label_desc: Use image node_id 1 to create a new TestModel object from inherited base classes: Model with example: obj = TestModel(n_outputs, input_shape, init_value)