The simplest way to do this is using kernel_initializer='zeros' with a custom kernel_constraint in the last Dense.
Here is my proposal for the custom kernel_constraint. my_constraints is a matrix of 0/1 built outside that must be passed as argument.
class MyConstraint(tf.keras.constraints.Constraint):
def __init__(self, my_constraints):
self.my_constraints = my_constraints
def __call__(self, w):
assert tf.shape(w).shape == tf.shape(self.my_constraints).shape
return w * tf.cast(self.my_constraints, dtype=tf.float32)
def get_config(self):
return {'my_constraints': self.my_constraints}
Below is how to build and run the model with some dummy data:
my_constraints = tf.constant([[1,0,1,0],[0,1,0,1],[1,0,1,0],[0,1,0,1]], dtype=tf.float32)
X = np.random.uniform(-10,10, (100,1))
y = np.random.uniform(-10,10, (100,4))
input = Input(shape=(1,))
l1 = Dense(units=4, activation='relu', name='layer1', use_bias=False)(input)
out = Dense(units=4, activation=None , name='layer2', use_bias=False,
kernel_constraint=MyConstraint(my_constraints), kernel_initializer='zeros')(l1)
model = Model(inputs=input, outputs=out)
model.compile('adam','mse')
model.fit(X,y, epochs=100)
To inspect the results:
>>> print(model.get_weights()[-1] == 0)
[[False True False True]
[ True False True False]
[False True False True]
[ True False True False]]
>>> print(model.get_weights()[-1])
[[-0.00230937 -0. -0.01893261 0. ]
[-0. -0.07535305 -0. -0.01603868]
[-0.16068968 0. 0.23261748 -0. ]
[-0. -0.07739028 -0. -0.01623872]]