Source code for nupic.tensorflow.constraints.sparse_weights
# ----------------------------------------------------------------------
# Numenta Platform for Intelligent Computing (NuPIC)
# Copyright (C) 2019, Numenta, Inc. Unless you have an agreement
# with Numenta, Inc., for a separate license for this software code, the
# following terms and conditions apply:
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero Public License version 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero Public License for more details.
#
# You should have received a copy of the GNU Affero Public License
# along with this program. If not, see http://www.gnu.org/licenses.
#
# http://numenta.org/licenses/
# ----------------------------------------------------------------------
import tensorflow as tf
from tensorflow import keras
[docs]class SparseWeights(keras.constraints.Constraint):
"""
Sparse weights constraint.
Constrains the weights to a fixed sparsity rate where a fixed number of
weights are always zeros.
:param percent_on:
Percentage of weights that are allowed to be non-zero. Default 0.5
:type sparsity: float
"""
def __init__(self, percent_on=0.5, name=None):
assert 0.0 < percent_on < 1.0
self.percent_on = percent_on
self.name = name or "sparse_mask"
self._built = False
def _build(self, input_shape, dtype=tf.float32):
"""
Called on the first iteration once the input shape is known
:param input_shape: Input shape including batch size
"""
with tf.variable_scope(self.name, reuse=tf.AUTO_REUSE):
non_zeros = int(round(input_shape[-1].value * self.percent_on))
# Create random mask with k elements set to 1, all other elements set to 0
values = tf.random_uniform(input_shape)
top_k, _ = tf.math.top_k(input=values, k=non_zeros, sorted=False)
kth = tf.reduce_min(top_k, axis=1, keepdims=True)
mask = tf.cast(tf.greater_equal(values, kth), dtype=dtype)
self.mask = tf.get_variable(
self.name,
initializer=mask,
trainable=False,
synchronization=tf.VariableSynchronization.NONE,
)
keras.backend.track_variable(self.mask)
self._built = True
def __call__(self, w):
if not self._built:
self._build(w.shape, dtype=w.dtype)
return w * self.mask
[docs] def get_config(self):
return {"percent_on": self.percent_on, "name": self.name}