vishak raj
vishak raj

Reputation: 21

Custom layer in Keras

I am trying to learn to do custom layer, I followed the steps in keras.io.

Code -

  class Linear(keras.layers.Layer):
      def __init__(self, units=32, input_dim=32):
          super(Linear, self).__init__()
          w_init = tf.random_normal_initializer()
          self.w = tf.Variable(
              initial_value=w_init(shape=(input_dim, units), dtype="float32"),
              trainable=True,
          )
          b_init = tf.zeros_initializer()
          self.b = tf.Variable(
              initial_value=b_init(shape=(units,), dtype="float32"), trainable=True
          )

      def call(self, inputs):
          print('inputs', inputs.shape)
          for index in range(inputs.shape[0]):
            ...
          return tf.matmul(inputs, self.w) + self.b

This shows the error -

TypeError: in user code:

<ipython-input-3-314addf0c624>:39 call  *
    for index in range(inputs.shape[0]):
/usr/local/lib/python3.7/dist-packages/tensorflow/python/autograph/operators/py_builtins.py:365 range_  **
    return _py_range(start_or_stop, stop, step)
/usr/local/lib/python3.7/dist-packages/tensorflow/python/autograph/operators/py_builtins.py:390 _py_range
    return range(start_or_stop)

TypeError: 'NoneType' object cannot be interpreted as an integer

when I run this Linear class separately, it works fine. But, when I run this layer as a trainable model, it shows this error.

How to solve this, thanks

Upvotes: 0

Views: 50

Answers (1)

Prefect
Prefect

Reputation: 1777

As default, shape of inputs is [batch_size,width,height,channels], and, when you create your model, batch_size is set to None.


import os
# os.environ['KERAS_BACKEND'] = 'theano'
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # suppress Tensorflow messages
import tensorflow as tf
from keras.layers import *
from keras.models import *


class CustomLinear(Layer):
  def __init__(self, batch_size,units=32, input_dim=32):
      super(CustomLinear, self).__init__()
      self.batch_size = batch_size
      w_init = tf.random_normal_initializer()
      self.w = tf.Variable(
          initial_value=w_init(shape=(input_dim, units), dtype="float32"),
          trainable=True,
      )
      b_init = tf.zeros_initializer()
      self.b = tf.Variable(
          initial_value=b_init(shape=(units,), dtype="float32"), trainable=True
      )

  def call(self, inputs):
    print('inputs', inputs.shape)
    # for index in range(self.batch_size):
        # print(index)
    return tf.matmul(inputs, self.w) + self.b


batch_size = 10

model = Sequential()
model.add(Input(shape=(2,32)))
model.add(CustomLinear(batch_size = batch_size)) # inputs (None, 2, 32)

x = tf.random.normal((batch_size,2,32)) # dummy data

model(x) # inputs (10, 2, 32)

Mostly, batch_size is not required for the calculations within the layer. But, if you still need it, you can add an argument (e.g. batch_size) to your CustomLinear, define your batch_size beforehand, and access to it inside __call__ function.

Upvotes: 1

Related Questions