Home > OS >  Add new nodes to one of the output layers in a Keras model
Add new nodes to one of the output layers in a Keras model

Time:03-14

I have a custom ResNet model that I define through the Keras Functional API. Also my model has multiple outputs. The last element of the output array is the fully connected dense layer with num_class nodes. I want to be able to increment the number of nodes of this layer. This is the relevant code for the creation of my network:

from tensorflow.keras import layers, models, Input, regularizers

res = []
inputs = Input(shape=(height, width, channels), name='data')
x = MyLayer()(inputs)
# ... other layers
x = MyLayer()(x)
res.append(x)
# ... other layers
x = layers.Dense(num_class, name='fc1', use_bias=True)(x)
res.append(x)
model = models.Model(inputs=inputs, outputs=[res[-2], res[-3], res[-4], res[-1]])

At the question Adding new nodes to output layer in Keras I found an answer similar to what I'm searching for that I'm adding here below:

def add_outputs(self, n_new_outputs):
    #Increment the number of outputs
    self.n_outputs  = n_new_outputs
    weights = self.model.get_layer('fc8').get_weights()
    #Adding new weights, weights will be 0 and the connections random
    shape = weights[0].shape[0]
    weights[1] = np.concatenate((weights[1], np.zeros(n_new_outputs)), axis=0)
    weights[0] = np.concatenate((weights[0], -0.0001 * np.random.random_sample((shape, n_new_outputs))   0.0001), axis=1)
    #Deleting the old output layer
    self.model.layers.pop()
    last_layer = self.model.get_layer('batchnormalization_1').output
    #New output layer
    out = Dense(self.n_outputs, activation='softmax', name='fc8')(last_layer)
    self.model = Model(input=self.model.input, output=out)
    #set weights to the layer
    self.model.get_layer('fc8').set_weights(weights)
    print(weights[0])

However in this question there was only one layer as output and I'm not sure how to replicate the same with my architecture.

CodePudding user response:

This is the solution I've come up with. I assigned the layers that I wanted to keep as output to variables:

from tensorflow.keras import layers, models, Input, regularizers

inputs = Input(shape=(height, width, channels), name='data')
x = MyLayer()(inputs)
# ... other layers
a = MyLayer(name="a")(x)
b = MyLayer(name="b")(a)
c = MyLayer(name="c")(b)
x = layers.Dense(num_class, name='fc1', use_bias=True)(c)
model = models.Model(inputs=inputs, outputs=[c, b, a, x])

And then in order to increase the number of nodes in the last layer just call the function increment_classes. The total number of nodes will be the sum of old_num_class and num_class.

def increment_classes(model, old_num_class, num_class):
    weights = model.get_layer("fc1").get_weights() 
    new_num_class = old_num_class   num_class

    # Adding new weights, weights will be 0 and the connections random
    shape = weights[0].shape[0]
    weights[1] = np.concatenate((weights[1], np.zeros(num_class)), axis=0)
    weights[0] = np.concatenate((weights[0], -0.0001 * np.random.random_sample((shape, num_class))   0.0001), axis=1)

    # Deleting the old dense output layer
    model.layers.pop()

    # get the output layers
    a = model.get_layer("a").output
    b = model.get_layer("b").output
    c = model.get_layer('c').output

    # Replace dense output layer (x)
    out = layers.Dense(new_num_class, name='fc1', use_bias=True)(c)

    model = models.Model(inputs=model.input, outputs=[c, b, a, out]) 

    # set weights to the layer
    model.get_layer('fc1').set_weights(weights)
    return model
  • Related