Beispiel #1
0
 def setUp(self):
     self.model = keras.Sequential()
     self.params = {
         'pruning_schedule': pruning_schedule.ConstantSparsity(0.5, 0),
         'block_size': (1, 1),
         'block_pooling_type': 'AVG'
     }
    def setUp(self):
        super(PruneTest, self).setUp()

        # Layers passed in for Pruning can either be standard Keras layers provided
        # by the tf.keras API (these fall under the `keras.layers` namespace), or
        # custom layers provided by the user which inherit the base
        # `keras.layers.Layer`.
        # Standard Keras layers can either be Prunable (we know how to prune them),
        # Non-Prunable (we know these layers can't be pruned) and Unsupported (we
        # don't know how to deal with these yet.). Unsupported layers will raise an
        # error when tried to prune.
        # Custom Layers can either be Prunable (ie., they implement the
        # `PrunableLayer` interface, or Non-Prunable (they don't expose any pruning
        # behavior.)

        # TODO(pulkitb): Change naming of Prunable/Non-Prunable/Unsupported to be
        # clearer.
        self.keras_prunable_layer = layers.Dense(10)  # Supports pruning
        self.keras_non_prunable_layer = layers.Dropout(
            0.4)  # Pruning not applicable
        self.keras_unsupported_layer = layers.ConvLSTM2D(2,
                                                         (5, 5))  # Unsupported
        self.custom_prunable_layer = CustomPrunableLayer(10)
        self.custom_non_prunable_layer = CustomNonPrunableLayer(10)

        self.model = keras.Sequential()
        self.params = {
            'pruning_schedule': pruning_schedule.ConstantSparsity(0.5, 0),
            'block_size': (1, 1),
            'block_pooling_type': 'AVG'
        }
    def setUp(self):
        super(PruningTest, self).setUp()
        self.block_size = (1, 1)
        self.block_pooling_type = "AVG"

        self.constant_sparsity = pruning_schedule.ConstantSparsity(
            0.5, 0, 100, 1)
Beispiel #4
0
 def setUp(self):
   super(PruneDistributedTest, self).setUp()
   self.params = {
       'pruning_schedule': pruning_schedule.ConstantSparsity(0.5, 0, -1, 1),
       'block_size': (1, 1),
       'block_pooling_type': 'AVG'
   }
    def testExtremelySparseMask(self):
        weight = tf.Variable(np.linspace(1.0, 100.0, 100), name="weights")
        weight_dtype = weight.dtype.base_dtype
        mask = tf.Variable(tf.ones(weight.get_shape(), dtype=weight_dtype),
                           name="mask",
                           dtype=weight_dtype)
        threshold = tf.Variable(tf.zeros([], dtype=weight_dtype),
                                name="threshold",
                                dtype=weight_dtype)
        self.initialize()

        extreme_sparsity = pruning_schedule.ConstantSparsity(0.9999, 0, 100, 1)
        p = pruning_impl.Pruning(pruning_vars=[(weight, mask, threshold)],
                                 training_step_fn=self.training_step_fn,
                                 pruning_schedule=extreme_sparsity,
                                 block_size=self.block_size,
                                 block_pooling_type=self.block_pooling_type)

        mask_before_pruning = K.get_value(mask)
        self.assertAllEqual(np.count_nonzero(mask_before_pruning), 100)

        if tf.executing_eagerly():
            p.conditional_mask_update()
        else:
            K.get_session().run(p.conditional_mask_update())

        # We should always have a single connection remaining.
        mask_after_pruning = K.get_value(mask)
        self.assertAllEqual(np.count_nonzero(mask_after_pruning), 1)
Beispiel #6
0
  def testPrunesModel_CustomTrainingLoop_ReachesTargetSparsity(self):
    pruned_model = prune.prune_low_magnitude(
        keras_test_utils.build_simple_dense_model(),
        pruning_schedule=pruning_schedule.ConstantSparsity(
            target_sparsity=0.5, begin_step=0, frequency=1))

    batch_size = 20
    x_train = np.random.rand(20, 10)
    y_train = keras.utils.to_categorical(
        np.random.randint(5, size=(batch_size, 1)), 5)

    loss = keras.losses.categorical_crossentropy
    optimizer = keras.optimizers.SGD()

    unused_arg = -1

    step_callback = pruning_callbacks.UpdatePruningStep()
    step_callback.set_model(pruned_model)
    pruned_model.optimizer = optimizer

    step_callback.on_train_begin()
    # 2 epochs
    for _ in range(2):
      step_callback.on_train_batch_begin(batch=unused_arg)
      inp = np.reshape(x_train, [batch_size, 10])  # original shape: from [10].
      with tf.GradientTape() as tape:
        logits = pruned_model(inp, training=True)
        loss_value = loss(y_train, logits)
        grads = tape.gradient(loss_value, pruned_model.trainable_variables)
        optimizer.apply_gradients(zip(grads, pruned_model.trainable_variables))
      step_callback.on_epoch_end(batch=unused_arg)

    test_utils.assert_model_sparsity(self, 0.5, pruned_model)
Beispiel #7
0
 def setUp(self):
   super(PruneIntegrationTest, self).setUp()
   self.params = {
       'pruning_schedule': pruning_schedule.ConstantSparsity(0.5, 0, -1, 1),
       # TODO(pulkitb): Add tests for block sparsity.
       'block_size': (1, 1),
       'block_pooling_type': 'AVG'
   }
Beispiel #8
0
 def testSparsityValueIsValid(self, schedule_type):
   if schedule_type == 'constant_sparsity':
     # pylint: disable=unnecessary-lambda
     self._validate_sparsity(lambda s: pruning_schedule.ConstantSparsity(s, 0))
   elif schedule_type == 'polynomial_decay':
     self._validate_sparsity(
         lambda s: pruning_schedule.PolynomialDecay(s, 0.8, 0, 10))
     self._validate_sparsity(
         lambda s: pruning_schedule.PolynomialDecay(0.2, s, 0, 10))
Beispiel #9
0
 def _construct_pruning_schedule(
     schedule_type, begin_step, end_step, frequency=10):
   # Uses default values for sparsity. We're only testing begin_step, end_step
   # and frequency here.
   if schedule_type == 'constant_sparsity':
     return pruning_schedule.ConstantSparsity(
         0.5, begin_step, end_step, frequency)
   elif schedule_type == 'polynomial_decay':
     return pruning_schedule.PolynomialDecay(
         0.2, 0.8, begin_step, end_step, 3, frequency)
    def testPruneWithHighSparsity_Fails(self):
        params = self.params
        params['pruning_schedule'] = pruning_schedule.ConstantSparsity(
            target_sparsity=0.99, begin_step=0, frequency=1)

        model = prune.prune_low_magnitude(
            keras_test_utils.build_simple_dense_model(), **params)

        with self.assertRaises(tf.errors.InvalidArgumentError):
            self._train_model(model, epochs=1)
Beispiel #11
0
    def testPrunesWithConstantSparsity(self):
        sparsity = pruning_schedule.ConstantSparsity(0.5, 100, 200, 10)

        step_100 = tf.Variable(100)
        step_110 = tf.Variable(110)
        step_200 = tf.Variable(200)
        compat.initialize_variables(self)

        self.assertAllClose(0.5, self.evaluate(sparsity(step_100))[1])
        self.assertAllClose(0.5, self.evaluate(sparsity(step_110))[1])
        self.assertAllClose(0.5, self.evaluate(sparsity(step_200))[1])
Beispiel #12
0
    def testPrunesWithConstantSparsity(self):
        sparsity = pruning_schedule.ConstantSparsity(0.5, 100, 200, 10)

        step_100 = variables.Variable(100)
        step_110 = variables.Variable(110)
        step_200 = variables.Variable(200)
        self.evaluate(variables.global_variables_initializer())

        self.assertAllClose(0.5, self.evaluate(sparsity(step_100))[1])
        self.assertAllClose(0.5, self.evaluate(sparsity(step_110))[1])
        self.assertAllClose(0.5, self.evaluate(sparsity(step_200))[1])
    def setUp(self):
        super(PruningTest, self).setUp()
        self.global_step = K.zeros([], dtype=dtypes.int32)
        self.block_size = (1, 1)
        self.block_pooling_type = "AVG"

        def training_step_fn():
            return self.global_step

        self.constant_sparsity = pruning_schedule.ConstantSparsity(
            0.5, 0, 100, 1)
        self.training_step_fn = training_step_fn
Beispiel #14
0
def GetPrunedModel(model,
                   target_sparsity=0.75,
                   begin_step=2000,
                   frequency=100):
    pruning_params = {
        "pruning_schedule":
        pruning_schedule.ConstantSparsity(target_sparsity,
                                          begin_step=begin_step,
                                          frequency=frequency)
    }
    pmodel = prune.prune_low_magnitude(model, **pruning_params)
    return pmodel
Beispiel #15
0
    def testPrunesForeverIfEndStepIsNegativeOne(self):
        sparsity = pruning_schedule.ConstantSparsity(0.5, 0, -1, 10)

        step_10000 = tf.Variable(10000)
        step_100000000 = tf.Variable(100000000)
        compat.initialize_variables(self)

        self.assertTrue(self.evaluate(sparsity(step_10000))[0])
        self.assertTrue(self.evaluate(sparsity(step_100000000))[0])

        self.assertAllClose(0.5, self.evaluate(sparsity(step_10000))[1])
        self.assertAllClose(0.5, self.evaluate(sparsity(step_100000000))[1])
Beispiel #16
0
    def testSerializeDeserialize(self):
        sparsity = pruning_schedule.ConstantSparsity(0.7, 10, 20, 10)

        config = sparsity.get_config()
        sparsity_deserialized = tf.keras.utils.deserialize_keras_object(
            config,
            custom_objects={
                'ConstantSparsity': pruning_schedule.ConstantSparsity,
                'PolynomialDecay': pruning_schedule.PolynomialDecay
            })

        self.assertEqual(sparsity.__dict__, sparsity_deserialized.__dict__)
def _prune_model(original_model):
    """Apply the pruning wrapper, compile and train the model."""
    prune_epoch = 1
    pruning_params = {
        'pruning_schedule':
        pruning_schedule.ConstantSparsity(0.50, begin_step=0, frequency=10)
    }
    pruning_model = prune.prune_low_magnitude(original_model, **pruning_params)
    callbacks = [pruning_callbacks.UpdatePruningStep()]
    pruning_model = _train_model(pruning_model, callbacks, prune_epoch)
    pruning_model_stripped = prune.strip_pruning(pruning_model)

    return pruning_model, pruning_model_stripped
Beispiel #18
0
  def testPruneWithHighSparsity(self):
    params = self.params
    params['pruning_schedule'] = pruning_schedule.ConstantSparsity(
        target_sparsity=0.99, begin_step=0, frequency=1)

    model = prune.prune_low_magnitude(
        keras_test_utils.build_simple_dense_model(), **params)
    self._train_model(model, epochs=1)
    for layer in model.layers:
      if isinstance(layer, pruning_wrapper.PruneLowMagnitude):
        for weight in layer.layer.get_prunable_weights():
          self.assertEqual(1,
                           np.count_nonzero(tf.keras.backend.get_value(weight)))
Beispiel #19
0
  def testPrunesZeroSparsity_IsNoOp(self):
    model = keras_test_utils.build_simple_dense_model()

    model2 = keras_test_utils.build_simple_dense_model()
    model2.set_weights(model.get_weights())

    params = self.params
    params['pruning_schedule'] = pruning_schedule.ConstantSparsity(
        target_sparsity=0, begin_step=0, frequency=1)
    pruned_model = prune.prune_low_magnitude(model2, **params)

    x_train = np.random.rand(20, 10),
    y_train = keras.utils.to_categorical(np.random.randint(5, size=(20, 1)), 5)

    self._train_model(model, epochs=1, x_train=x_train, y_train=y_train)
    self._train_model(pruned_model, epochs=1, x_train=x_train, y_train=y_train)

    self._assert_weights_different_objects(model, pruned_model)
    self._assert_weights_same_values(model, pruned_model)
Beispiel #20
0
def get_pruning_params(mode='prune',
                       initial_sparsity=0.0,
                       final_sparsity=0.8,
                       begin_step=2000,
                       end_step=4000,
                       frequency=200):
  """Gets pruning hyper-parameters."""
  p_params = {}
  if mode == 'prune':
    p_params['pruning_schedule'] = pruning_schedule.PolynomialDecay(
        initial_sparsity=initial_sparsity,
        final_sparsity=final_sparsity,
        begin_step=begin_step,
        end_step=end_step,
        frequency=frequency)
  elif mode == 'constant':
    p_params['pruning_schedule'] = pruning_schedule.ConstantSparsity(
        target_sparsity=final_sparsity, begin_step=begin_step)
  else:
    raise ValueError('Mode: %s, is not valid' % mode)
  return p_params
def main():
    # input image dimensions
    img_rows, img_cols = 28, 28

    # the data, shuffled and split between train and test sets
    (x_train, y_train), (x_test, y_test) = mnist.load_data()

    if K.image_data_format() == "channels_first":
      x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
      x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
      input_shape = (1, img_rows, img_cols)
    else:
      x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
      x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
      input_shape = (img_rows, img_cols, 1)

    x_train = x_train.astype("float32")
    x_test = x_test.astype("float32")
    x_train /= 255
    x_test /= 255
    print("x_train shape:", x_train.shape)
    print(x_train.shape[0], "train samples")
    print(x_test.shape[0], "test samples")

    # convert class vectors to binary class matrices
    y_train = to_categorical(y_train, num_classes)
    y_test = to_categorical(y_test, num_classes)

    pruning_params = {
        "pruning_schedule":
            pruning_schedule.ConstantSparsity(0.75, begin_step=2000, frequency=100)
    }
    
    if prune_whole_model:
        model = build_model(input_shape)
        model = prune.prune_low_magnitude(model, **pruning_params)
    else:
        model = build_layerwise_model(input_shape, **pruning_params)

    train_and_save(model, x_train, y_train, x_test, y_test)
def prune_model(original_model, train_images, train_labels):
  batch_size = 256
  epochs = 5

  pruning_params = {
      'pruning_schedule':
      pruning_schedule.ConstantSparsity(0.75, begin_step=0, frequency=100)
  }
  pruning_model = prune.prune_low_magnitude(original_model, **pruning_params)
  pruning_model.summary()

  callbacks = [pruning_callbacks.UpdatePruningStep()]
  fit_kwargs = {
      'batch_size': batch_size,
      'epochs': epochs,
      'callbacks': callbacks,
  }
  compile_and_fit(pruning_model,
                  train_images,
                  train_labels,
                  compile_kwargs={},
                  fit_kwargs=fit_kwargs)

  return pruning_model
Beispiel #23
0
    def __init__(self,
                 layer,
                 pruning_schedule=pruning_sched.ConstantSparsity(0.5, 0),
                 block_size=(1, 1),
                 block_pooling_type='AVG',
                 **kwargs):
        """Create a pruning wrapper for a keras layer.

    #TODO(pulkitb): Consider if begin_step should be 0 by default.

    Args:
      layer: The keras layer to be pruned.
      pruning_schedule: A `PruningSchedule` object that controls pruning rate
        throughout training.
      block_size: (optional) The dimensions (height, weight) for the block
        sparse pattern in rank-2 weight tensors.
      block_pooling_type: (optional) The function to use to pool weights in the
        block. Must be 'AVG' or 'MAX'.
      **kwargs: Additional keyword arguments to be passed to the keras layer.
    """
        self.pruning_schedule = pruning_schedule
        self.block_size = block_size
        self.block_pooling_type = block_pooling_type

        # An instance of the Pruning class. This class contains the logic to prune
        # the weights of this layer.
        self.pruning_obj = None

        # A list of all (weight,mask,threshold) tuples for this layer
        self.pruning_vars = []

        if block_pooling_type not in ['AVG', 'MAX']:
            raise ValueError(
                'Unsupported pooling type \'{}\'. Should be \'AVG\' or \'MAX\'.'
                .format(block_pooling_type))

        if not isinstance(layer, tf.keras.layers.Layer):
            raise ValueError(
                'Please initialize `Prune` layer with a '
                '`Layer` instance. You passed: {input}'.format(input=layer))

        # TODO(pulkitb): This should be pushed up to the wrappers.py
        # Name the layer using the wrapper and underlying layer name.
        # Prune(Dense) becomes prune_dense_1
        kwargs.update({
            'name':
            '{}_{}'.format(
                generic_utils.to_snake_case(self.__class__.__name__),
                layer.name)
        })

        if isinstance(layer, prunable_layer.PrunableLayer) or hasattr(
                layer, 'get_prunable_weights'):
            # Custom layer in client code which supports pruning.
            super(PruneLowMagnitude, self).__init__(layer, **kwargs)
        elif prune_registry.PruneRegistry.supports(layer):
            # Built-in keras layers which support pruning.
            super(PruneLowMagnitude, self).__init__(
                prune_registry.PruneRegistry.make_prunable(layer), **kwargs)
        else:
            raise ValueError(
                'Please initialize `Prune` with a supported layer. Layers should '
                'either be supported by the PruneRegistry (built-in keras layers) or '
                'should be a `PrunableLayer` instance, or should has a customer '
                'defined `get_prunable_weights` method. You passed: '
                '{input}'.format(input=layer.__class__))

        self._track_trackable(layer, name='layer')

        # TODO(yunluli): Work-around to handle the first layer of Sequential model
        # properly. Can remove this when it is implemented in the Wrapper base
        # class.
        #
        # Enables end-user to prune the first layer in Sequential models, while
        # passing the input shape to the original layer.
        #
        # tf.keras.Sequential(
        #   prune_low_magnitude(tf.keras.layers.Dense(2, input_shape=(3,)))
        # )
        #
        # as opposed to
        #
        # tf.keras.Sequential(
        #   prune_low_magnitude(tf.keras.layers.Dense(2), input_shape=(3,))
        # )
        #
        # Without this code, the pruning wrapper doesn't have an input
        # shape and being the first layer, this causes the model to not be
        # built. Being not built is confusing since the end-user has passed an
        # input shape.
        if not hasattr(self, '_batch_input_shape') and hasattr(
                layer, '_batch_input_shape'):
            self._batch_input_shape = self.layer._batch_input_shape
        metrics.MonitorBoolGauge('prune_low_magnitude_wrapper_usage').set(
            layer.__class__.__name__)
Beispiel #24
0
           kernel_regularizer=l1(0.0001)))
model.add(QActivation(activation=quantized_relu(6), name='relu1'))
model.add(
    QDense(5,
           name='output',
           kernel_quantizer=quantized_bits(6, 0, alpha=1),
           bias_quantizer=quantized_bits(6, 0, alpha=1),
           kernel_initializer='lecun_uniform',
           kernel_regularizer=l1(0.0001)))
model.add(Activation(activation='softmax', name='softmax'))

from tensorflow_model_optimization.python.core.sparsity.keras import prune, pruning_callbacks, pruning_schedule
from tensorflow_model_optimization.sparsity.keras import strip_pruning
pruning_params = {
    "pruning_schedule":
    pruning_schedule.ConstantSparsity(0.75, begin_step=2000, frequency=100)
}
model = prune.prune_low_magnitude(model, **pruning_params)

train = not os.path.exists('model_1/KERAS_check_best_model.h5')
if train:
    adam = Adam(lr=0.0001)
    model.compile(optimizer=adam,
                  loss=['categorical_crossentropy'],
                  metrics=['accuracy'])
    callbacks = all_callbacks(stop_patience=1000,
                              lr_factor=0.5,
                              lr_patience=10,
                              lr_epsilon=0.000001,
                              lr_cooldown=2,
                              lr_minimum=0.0000001,
Beispiel #25
0
def Q_baseline_model(size, epochs, optimizer, X_training, y_training,
                     X_validation, y_validation, output_name):
    '''
    NN Model constructor with loss and accuracy plots.

    Parameters
    ----------
    size : int
        Batch size used in the training process.
    epochs : int
        Number of epochs the model will be trained.
    optimizer : keras.optimizer
        Optimizer function.
    X_training : Numpy array
        Training data set.
    y_training : Numpy array
        True labels for the training set.
    X_validation : Numpy array
        Validation data set.
    y_validation : Numpy array
        True labels for the validation set.
    output_name : str
        Name used for saved plots.

    Returns
    -------
    model : qkeras.sequential
        QKeras model.
    w : numpy array
        Array of final weights used in the model for later inference.

    '''
    pruning = False
    # create model
    name = "RMSE validation"
    name2 = "RMSE training"
    history = History()
    model = Sequential()
    model.add(
        QDense(60,
               input_shape=(27, ),
               kernel_quantizer=quantized_bits(16, 1),
               bias_quantizer=quantized_bits(16, 1),
               kernel_initializer='random_normal'))
    model.add(QActivation(activation=quantized_relu(16, 1), name='relu1'))
    model.add(
        QDense(50,
               kernel_quantizer=quantized_bits(16, 1),
               bias_quantizer=quantized_bits(16, 1)))
    model.add(QActivation(activation=quantized_relu(16, 1), name='relu2'))
    # model.add(Dropout(rate=0.2))
    model.add(
        QDense(30,
               kernel_quantizer=quantized_bits(16, 1),
               bias_quantizer=quantized_bits(16, 1)))
    model.add(QActivation(activation=quantized_relu(16, 1), name='relu3'))
    model.add(
        QDense(40,
               kernel_quantizer=quantized_bits(16, 1),
               bias_quantizer=quantized_bits(16, 1)))
    model.add(QActivation(activation=quantized_relu(16, 1), name='relu4'))
    model.add(
        QDense(15,
               kernel_quantizer=quantized_bits(16, 1),
               bias_quantizer=quantized_bits(16, 1)))
    model.add(QActivation(activation=quantized_relu(16, 1), name='relu5'))

    # model.add(QDense(80,  input_shape=(27,),kernel_quantizer=quantized_bits(16,1),bias_quantizer=quantized_bits(16,1), kernel_initializer='random_normal'))
    # model.add(QActivation(activation=quantized_relu(16,1), name='relu1'))
    # model.add(QDense(50,kernel_quantizer=quantized_bits(16,1),bias_quantizer=quantized_bits(16,1)))
    # model.add(QActivation(activation=quantized_relu(16,1), name='relu2'))
    # model.add(QDense(35,kernel_quantizer=quantized_bits(16,1),bias_quantizer=quantized_bits(16,1)))
    # model.add(QActivation(activation=quantized_relu(16,1), name='relu3'))
    # # # model.add(Dropout(rate=0.2))
    model.add(QDense(1, kernel_quantizer=quantized_bits(16, 1)))
    model.add(QActivation(activation=quantized_relu(16, 1), name='relu6'))
    #model.add(Activation("sigmoid"))
    # model.add(QActivation(activation=quantized_tanh(16,1),name='tanh'))
    if pruning == True:
        print("////////////////////////Training Model with pruning")
        pruning_params = {
            "pruning_schedule":
            pruning_schedule.ConstantSparsity(0.75,
                                              begin_step=2000,
                                              frequency=100)
        }
        model = prune.prune_low_magnitude(model, **pruning_params)
        model.compile(loss='mean_squared_error', optimizer=optimizer)
        model.fit(X_training,
                  y_training,
                  batch_size=size,
                  epochs=epochs,
                  verbose=1,
                  validation_data=(X_validation, y_validation),
                  callbacks=[history,
                             pruning_callbacks.UpdatePruningStep()])

        model = strip_pruning(model)
        w = model.layers[0].weights[0].numpy()
        h, b = np.histogram(w, bins=100)
        plt.figure(figsize=(7, 7))
        plt.bar(b[:-1], h, width=b[1] - b[0])
        plt.semilogy()
        plt.savefig("Zeros' distribution", format='png')
        print('% of zeros = {}'.format(np.sum(w == 0) / np.size(w)))
    else:
        print("////////////////////////Training Model WITHOUT pruning")
        model.compile(loss='mean_squared_error', optimizer=optimizer)
        model.fit(X_training,
                  y_training,
                  batch_size=size,
                  epochs=epochs,
                  verbose=1,
                  validation_data=(X_validation, y_validation),
                  callbacks=[history])
    # Compile model
    # model.compile(loss='mean_squared_error', optimizer=optimizer)
    # model.fit(X_training, y_training,
    #       batch_size=size,
    #       epochs=epochs,
    #       verbose=1,
    #       validation_data=(X_validation, y_validation),callbacks=[history])

    w = []
    for layer in model.layers:
        print(layer)
        w.append(layer.get_weights())

    #print(w)
    train_predictions = model.predict(X_training)
    predictions = model.predict(X_validation)
    lin_mse = mean_squared_error(y_validation, predictions)
    lin_rmse = np.sqrt(lin_mse)
    lin_mse2 = mean_squared_error(y_training, train_predictions)
    lin_rmse2 = np.sqrt(lin_mse2)
    msg = "%s: %f" % (name, lin_rmse)
    msg2 = "%s: %f" % (name2, lin_rmse2)
    print(msg)
    print(msg2)
    fig, ax = plt.subplots()
    # xy=np.vstack([y_validation, predictions])
    #z=gaussian_kde(xy)
    ax.scatter(y_validation, predictions, edgecolors=(0, 0, 0))
    ax.set_title('Regression model predictions (validation set)')
    ax.set_xlabel('Measured $p_T$ (GeV/c)')
    ax.set_ylabel('Predicted $p_T$ (GeV/c)')
    ax.plot([Y.min(), Y.max()], [Y.min(), Y.max()], 'k--', lw=4)
    plt.rc('font', size=20)
    plt.rc('axes', titlesize=18)
    plt.rc('axes', labelsize=18)
    plt.rc('xtick', labelsize=18)
    plt.rc('ytick', labelsize=18)
    plt.rc('legend', fontsize=18)
    plt.rc('figure', titlesize=18)
    plt.tight_layout()
    plt.savefig(outrootname + '/' + '1' + output_name, format='png', dpi=800)
    fig2, ax2 = plt.subplots()
    ax2.plot(history.history['loss'], label='loss')
    ax2.plot(history.history['val_loss'], label='val_loss')
    ax2.set_title('Training and Validation loss per epoch')
    ax2.set_xlabel('# Epoch')
    ax2.set_ylabel('loss')
    plt.legend()
    plt.tight_layout()
    plt.savefig(outrootname + '/' + '2' + output_name, format='png', dpi=800)
    #plt.show()
    del ax, ax2

    return model, w
Beispiel #26
0
    def __init__(self,
                 layer,
                 pruning_schedule=pruning_sched.ConstantSparsity(0.5, 0),
                 block_size=(1, 1),
                 block_pooling_type='AVG',
                 **kwargs):
        """Create a pruning wrapper for a keras layer.

    #TODO(pulkitb): Consider if begin_step should be 0 by default.

    Args:
      layer: The keras layer to be pruned.
      pruning_schedule: A `PruningSchedule` object that controls pruning rate
        throughout training.
      block_size: (optional) The dimensions (height, weight) for the block
        sparse pattern in rank-2 weight tensors.
      block_pooling_type: (optional) The function to use to pool weights in the
        block. Must be 'AVG' or 'MAX'.
      **kwargs: Additional keyword arguments to be passed to the keras layer.
    """
        self.pruning_schedule = pruning_schedule
        self.block_size = block_size
        self.block_pooling_type = block_pooling_type

        # An instance of the Pruning class. This class contains the logic to prune
        # the weights of this layer.
        self.pruning_obj = None

        # A list of all (weight,mask,threshold) tuples for this layer
        self.pruning_vars = []

        if block_pooling_type not in ['AVG', 'MAX']:
            raise ValueError(
                'Unsupported pooling type \'{}\'. Should be \'AVG\' or \'MAX\'.'
                .format(block_pooling_type))

        if not isinstance(layer, Layer):
            raise ValueError(
                'Please initialize `Prune` layer with a '
                '`Layer` instance. You passed: {input}'.format(input=layer))

        # TODO(pulkitb): This should be pushed up to the wrappers.py
        # Name the layer using the wrapper and underlying layer name.
        # Prune(Dense) becomes prune_dense_1
        kwargs.update({
            'name':
            '{}_{}'.format(
                generic_utils.to_snake_case(self.__class__.__name__),
                layer.name)
        })

        if isinstance(layer, prunable_layer.PrunableLayer):
            # Custom layer in client code which supports pruning.
            super(PruneLowMagnitude, self).__init__(layer, **kwargs)
        elif prune_registry.PruneRegistry.supports(layer):
            # Built-in keras layers which support pruning.
            super(PruneLowMagnitude, self).__init__(
                prune_registry.PruneRegistry.make_prunable(layer), **kwargs)
        else:
            raise ValueError(
                'Please initialize `Prune` with a supported layer. Layers should '
                'either be a `PrunableLayer` instance, or should be supported by the '
                'PruneRegistry. You passed: {input}'.format(
                    input=layer.__class__))

        self._track_trackable(layer, name='layer')

        # TODO(yunluli): Work-around to handle the first layer of Sequential model
        # properly. Can remove this when it is implemented in the Wrapper base
        # class.
        # The _batch_input_shape attribute in the first layer makes a Sequential
        # model to be built. This change makes sure that when we apply the wrapper
        # to the whole model, this attribute is pulled into the wrapper to preserve
        # the 'built' state of the model.
        if not hasattr(self, '_batch_input_shape') and hasattr(
                layer, '_batch_input_shape'):
            self._batch_input_shape = self.layer._batch_input_shape
Beispiel #27
0
def prune_low_magnitude(to_prune,
                        pruning_schedule=pruning_sched.ConstantSparsity(
                            0.5, 0),
                        block_size=(1, 1),
                        block_pooling_type='AVG',
                        pruning_policy=None,
                        **kwargs):
    """Modify a tf.keras layer or model to be pruned during training.

  This function wraps a tf.keras model or layer with pruning functionality which
  sparsifies the layer's weights during training. For example, using this with
  50% sparsity will ensure that 50% of the layer's weights are zero.

  The function accepts either a single keras layer
  (subclass of `tf.keras.layers.Layer`), list of keras layers or a Sequential
  or Functional tf.keras model and handles them appropriately.

  If it encounters a layer it does not know how to handle, it will throw an
  error. While pruning an entire model, even a single unknown layer would lead
  to an error.

  Prune a model:

  ```python
  pruning_params = {
      'pruning_schedule': ConstantSparsity(0.5, 0),
      'block_size': (1, 1),
      'block_pooling_type': 'AVG'
  }

  model = prune_low_magnitude(
      keras.Sequential([
          layers.Dense(10, activation='relu', input_shape=(100,)),
          layers.Dense(2, activation='sigmoid')
      ]), **pruning_params)
  ```

  Prune a layer:

  ```python
  pruning_params = {
      'pruning_schedule': PolynomialDecay(initial_sparsity=0.2,
          final_sparsity=0.8, begin_step=1000, end_step=2000),
      'block_size': (2, 3),
      'block_pooling_type': 'MAX'
  }

  model = keras.Sequential([
      layers.Dense(10, activation='relu', input_shape=(100,)),
      prune_low_magnitude(layers.Dense(2, activation='tanh'), **pruning_params)
  ])
  ```

  Pretrained models: you must first load the weights and then apply the
  prune API:

  ```python
  model.load_weights(...)
  model = prune_low_magnitude(model)
  ```

  Optimizer: this function removes the optimizer. The user is expected to
  compile the model
  again. It's easiest to rely on the default (step starts at 0) and then
  use that to determine the desired begin_step for the pruning_schedules.

  Checkpointing: checkpointing should include the optimizer, not just the
  weights. Pruning supports
  checkpointing though
  upon inspection, the weights of checkpoints are not sparse
  (https://github.com/tensorflow/model-optimization/issues/206).

  Arguments:
      to_prune: A single keras layer, list of keras layers, or a
        `tf.keras.Model` instance.
      pruning_schedule: A `PruningSchedule` object that controls pruning rate
        throughout training.
      block_size: (optional) The dimensions (height, weight) for the block
        sparse pattern in rank-2 weight tensors.
      block_pooling_type: (optional) The function to use to pool weights in the
        block. Must be 'AVG' or 'MAX'.
      pruning_policy: (optional) The object that controls to which layers
        `PruneLowMagnitude` wrapper will be applied. This API is experimental
        and is subject to change.
      **kwargs: Additional keyword arguments to be passed to the keras layer.
        Ignored when to_prune is not a keras layer.

  Returns:
    Layer or model modified with pruning wrappers. Optimizer is removed.

  Raises:
    ValueError: if the keras layer is unsupported, or the keras model contains
    an unsupported layer.
  """
    def _prune_list(layers, **params):
        wrapped_layers = []

        for layer in layers:
            # Allow layer that is already wrapped by the pruning wrapper
            # to be used as is.
            # No need to wrap the input layer either.
            if isinstance(layer, pruning_wrapper.PruneLowMagnitude):
                wrapped_layers.append(layer)
            elif isinstance(layer, keras.layers.InputLayer):
                # TODO(yunluli): Replace with a clone function in keras.
                wrapped_layers.append(
                    layer.__class__.from_config(layer.get_config()))
            else:
                wrapped_layers.append(
                    pruning_wrapper.PruneLowMagnitude(layer, **params))

        return wrapped_layers

    def _add_pruning_wrapper(layer):
        if isinstance(layer, keras.Model):
            # Check whether the model is a subclass model.
            if (not layer._is_graph_network
                    and not isinstance(layer, keras.models.Sequential)):
                raise ValueError(
                    'Subclassed models are not supported currently.')

            return keras.models.clone_model(
                layer, input_tensors=None, clone_function=_add_pruning_wrapper)
        if isinstance(layer, pruning_wrapper.PruneLowMagnitude):
            return layer
        if pruning_policy and not pruning_policy.allow_pruning(layer):
            return layer
        else:
            return pruning_wrapper.PruneLowMagnitude(layer, **params)

    params = {
        'pruning_schedule': pruning_schedule,
        'block_size': block_size,
        'block_pooling_type': block_pooling_type
    }

    is_sequential_or_functional = isinstance(
        to_prune, keras.Model) and (isinstance(to_prune, keras.Sequential)
                                    or to_prune._is_graph_network)

    # A subclassed model is also a subclass of keras.layers.Layer.
    is_keras_layer = isinstance(
        to_prune,
        keras.layers.Layer) and not isinstance(to_prune, keras.Model)

    if isinstance(to_prune, list):
        return _prune_list(to_prune, **params)
    elif is_sequential_or_functional:
        if pruning_policy:
            pruning_policy.ensure_model_supports_pruning(to_prune)
        return _add_pruning_wrapper(to_prune)
    elif is_keras_layer:
        params.update(kwargs)
        return pruning_wrapper.PruneLowMagnitude(to_prune, **params)
    else:
        raise ValueError(
            '`prune_low_magnitude` can only prune an object of the following '
            'types: tf.keras.models.Sequential, tf.keras functional model, '
            'tf.keras.layers.Layer, list of tf.keras.layers.Layer. You passed '
            'an object of type: {input}.'.format(
                input=to_prune.__class__.__name__))
Beispiel #28
0
def prune_low_magnitude(to_prune,
                        pruning_schedule=pruning_sched.ConstantSparsity(
                            0.5, 0),
                        block_size=(1, 1),
                        block_pooling_type='AVG',
                        **kwargs):
    """Modify a keras layer or model to be pruned during training.

  This function wraps a tf.keras model or layer with pruning functionality which
  sparsifies the layer's weights during training. For example, using this with
  50% sparsity will ensure that 50% of the layer's weights are zero.

  The function accepts either a single keras layer
  (subclass of `tf.keras.layers.Layer`), list of keras layers or a Sequential
  or Functional keras model and handles them appropriately.

  If it encounters a layer it does not know how to handle, it will throw an
  error. While pruning an entire model, even a single unknown layer would lead
  to an error.

  Prune a model:

  ```python
  pruning_params = {
      'pruning_schedule': ConstantSparsity(0.5, 0),
      'block_size': (1, 1),
      'block_pooling_type': 'AVG'
  }

  model = prune_low_magnitude(
      keras.Sequential([
          layers.Dense(10, activation='relu', input_shape=(100,)),
          layers.Dense(2, activation='sigmoid')
      ]), **pruning_params)
  ```

  Prune a layer:

  ```python
  pruning_params = {
      'pruning_schedule': PolynomialDecay(initial_sparsity=0.2,
          final_sparsity=0.8, begin_step=1000, end_step=2000),
      'block_size': (2, 3),
      'block_pooling_type': 'MAX'
  }

  model = keras.Sequential([
      layers.Dense(10, activation='relu', input_shape=(100,)),
      prune_low_magnitude(layers.Dense(2, activation='tanh'), **pruning_params)
  ])
  ```

  Arguments:
      to_prune: A single keras layer, list of keras layers, or a
        `tf.keras.Model` instance.
      pruning_schedule: A `PruningSchedule` object that controls pruning rate
        throughout training.
      block_size: (optional) The dimensions (height, weight) for the block
        sparse pattern in rank-2 weight tensors.
      block_pooling_type: (optional) The function to use to pool weights in the
        block. Must be 'AVG' or 'MAX'.
      **kwargs: Additional keyword arguments to be passed to the keras layer.
        Ignored when to_prune is not a keras layer.

  Returns:
    Layer or model modified with pruning wrappers.

  Raises:
    ValueError: if the keras layer is unsupported, or the keras model contains
    an unsupported layer.
  """
    def _prune_list(layers, **params):
        wrapped_layers = []

        for layer in layers:
            # Allow layer that is already wrapped by the pruning wrapper
            # to be used as is.
            # No need to wrap the input layer either.
            if isinstance(layer, pruning_wrapper.PruneLowMagnitude):
                wrapped_layers.append(layer)
            elif isinstance(layer, InputLayer):
                # TODO(yunluli): Replace with a clone function in keras.
                wrapped_layers.append(
                    layer.__class__.from_config(layer.get_config()))
            else:
                wrapped_layers.append(
                    pruning_wrapper.PruneLowMagnitude(layer, **params))

        return wrapped_layers

    def _add_pruning_wrapper(layer):
        if isinstance(layer, pruning_wrapper.PruneLowMagnitude):
            return layer
        return pruning_wrapper.PruneLowMagnitude(layer, **params)

    params = {
        'pruning_schedule': pruning_schedule,
        'block_size': block_size,
        'block_pooling_type': block_pooling_type
    }
    is_sequential_or_functional = isinstance(
        to_prune, keras.Model) and (isinstance(to_prune, keras.Sequential)
                                    or to_prune._is_graph_network)

    # A subclassed model is also a subclass of keras.layers.Layer.
    is_keras_layer = isinstance(
        to_prune,
        keras.layers.Layer) and not isinstance(to_prune, keras.Model)

    if isinstance(to_prune, list):
        return _prune_list(to_prune, **params)
    elif is_sequential_or_functional:
        return keras.models.clone_model(to_prune,
                                        input_tensors=None,
                                        clone_function=_add_pruning_wrapper)
    elif is_keras_layer:
        params.update(kwargs)
        return pruning_wrapper.PruneLowMagnitude(to_prune, **params)
    else:
        raise ValueError(
            '`prune_low_magnitude` can only prune an object of the following '
            'types: tf.keras.models.Sequential, tf.keras functional model, '
            'tf.keras.layers.Layer, list of tf.keras.layers.Layer. You passed '
            'an object of type: {input}.'.format(
                input=to_prune.__class__.__name__))
Beispiel #29
0
def apply_pruning_to_conv2D(layer):
  if isinstance(layer, tf.keras.layers.Conv2D):
    return tfmot.sparsity.keras.prune_low_magnitude(layer,pruning_schedule=pruning_sched.ConstantSparsity(0.8,0))
  return layer

projection_simplex_sort(np.array([1, 0.1]), 3)

#%%pixie_debugger

# l1 parameters
l1coeff = 0

# for reconstructor
#l2coeff = 0

# for keras sparsity
sparsity = 0.3
pruning_params = {
    'pruning_schedule': pruning_sched.ConstantSparsity(0.9, 0),
    #'pruning_schedule': pruning_sched.PolynomialDecay(0, 0.3, 0, 100),
    'block_size': (1, 1),
    'block_pooling_type': 'AVG'
}


def component_diff_normalized(v):
    """How much the vector is close to (1,0) or (0,1)."""
    v = np.abs(v)
    v = np.sort(v)[::-1]
    maxv = v[0]
    smaxv = v[1]
    return 1. - (maxv - smaxv) / maxv