首页 > 解决方案 > Keras 中的自定义层

问题描述

我正在尝试学习做自定义层,我按照 keras.io 中的步骤进行操作。

代码 -

  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

这显示了错误 -

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

当我单独运行这个线性类时,它工作正常。但是,当我将此层作为可训练模型运行时,它会显示此错误。

这个怎么解决,谢谢

标签: pythonkeras

解决方案


默认情况下,输入的形状为 [batch_size,width,height,channels],并且当您创建模型时,batch_size 设置为 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)

大多数情况下,层内的计算不需要 batch_size。但是,如果你仍然需要它,你可以在你的 中添加一个参数(例如 batch_size) ,预先定义你的 batch_size,然后在函数中CustomLinear访问它。__call__


推荐阅读