Home > Software engineering >  How to get weights from a layer subclass defined inside a layer.layers class in Tensorflow?
How to get weights from a layer subclass defined inside a layer.layers class in Tensorflow?

Time:04-15

I have the code below, where inside the convProjection class, I defined a Conv1D layer from keras. I want to get the weights of the Conv1D defined. Although since it's not initalized, getting the weights with self.Projection.get_weights() returns an empty array. I tried to initalize it manually inside call but it doesn't seem to work. How can I get the weights of the Conv1D layer in this case? I will also need to set them back after manipulating them.

kernelSize = 32
stride = 16
class convProjections(layers.Layer):
    def __init__(self, kernelSize,stride):
        super(convProjections, self).__init__()
        self.Projection = layers.Conv1D(filters = projection_dim,kernel_size = kernelSize,strides = stride)
    def call(self, inputData):
        Projections = self.Projection(inputData)
        convWeights = self.Projection.get_weights()
        ####I will do some something here with convWeights####

        return Projections

def model
    inputs = layers.Input(shape=input_shape)
    patches = convProjections(kernelSize,stride)(inputs)
    logits = layers.Dense(8,  activation='softmax')(patches )
    model = keras.Model(inputs=inputs, outputs=logits)

Preferably, I'd like to stick with Model subclassing to define my model. But is open to solutions

CodePudding user response:

You have to build your convProjections properly. You have to create the layer weights in the build(self, inputs_shape) method of your layer. Then you have to use these weights in the call method to operate convolution using tf.nn.conv1d. In the end of call you can do whatever you want with self.convWeights.

class convProjections(layers.Layer):

    def __init__(self, projection_dim, kernelSize, stride, use_bias=True):
        super(convProjections, self).__init__()
        self.projection_dim = projection_dim
        self.kernelSize = kernelSize
        self.stride = stride
        self.use_bias = use_bias

    def build(self, input_shape):
        self.convWeights = self.add_weight(
            shape=(self.kernelSize, input_shape[-1], self.projection_dim),
            initializer="random_normal",
            trainable=True,
        )
        if self.use_bias:
            self.convBias = self.add_weight(
                shape=(self.projection_dim,), initializer="random_normal", trainable=True
            )

    def call(self, inputData):

        conv = tf.nn.conv1d(
            inputData, 
            filters=self.convWeights, 
            stride=[1,self.stride,1], 
            padding='SAME',
            data_format='NWC'
        )

        if self.use_bias:
            conv = tf.nn.bias_add(conv, self.convBias)

        ### DO SOMETHING WITH self.convWeights ###

        print(self.convWeights.shape)

        return conv

Building the model:

input_shape = (24,6)
kernelSize = 32
stride = 1
projection_dim = 64

inputs = layers.Input(shape=input_shape)
patches = convProjections(projection_dim,kernelSize,stride)(inputs)
outputs = layers.Dense(8,  activation='softmax')(patches)
model = Model(inputs=inputs, outputs=outputs)
  • Related