【问题标题】:Why does my Keras Custom Layer only gets called once?为什么我的 Keras 自定义层只被调用一次?
【发布时间】:2021-01-22 09:42:19
【问题描述】:

我必须使用 tensorflow 1.15 并且需要一个自定义层。一个非常简单的层可以如下所示:

class Dummy(keras.layers.Layer):
    def __init__(self, units=32, input_dim=32):
        super(Dummy, self).__init__()
        self.cnt = 1
    def call(self, inputs):
        self.cnt += 1
        return inputs  

如果我在任何架构中使用这个虚拟层,变量 cnt 只设置为两个。我错过了什么?

这是一个非常简单的虚拟脚本来展示我的问题:

import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Conv2D, Activation
from tensorflow import set_random_seed
from numpy.random import seed

seed(312991)
set_random_seed(3121991)

class Dummy(keras.layers.Layer):
    def __init__(self, units=32, input_dim=32):
        super(Dummy, self).__init__()
        self.cnt = 1
    def call(self, inputs):
        self.cnt += 1
        return inputs  

# creating the input image
input_img = np.ones(shape=(8,8,3))

#adjust range
input_img_adjusted = input_img / 255
target = input_img_adjusted[:,:,0:2]

model = Sequential()
model.add(Conv2D(2, (3, 3),input_shape=input_img.shape, padding='same'))
model.add(Dummy())
model.add(Activation('sigmoid'))

opt = keras.optimizers.Adam(0.001)
model.compile(optimizer=opt,
              loss="mean_absolute_error")

hist = model.fit(np.array(2048*[input_img_adjusted]),np.array(2048*[target]),epochs=100,batch_size=32)

print("called the Dummy Layer:", model.layers[-2].cnt)

我的假设是它类似于 32,32*100 或类似的东西。

【问题讨论】:

  • 变量“cnt”代表什么?
  • 它只是虚拟层中的一个简单计数器,用于计算调用函数被调用的频率
  • 函数调用应该被多次调用,对吧? keras.io/guides/making_new_layers_and_models_via_subclassing这里调用函数实现了计算,所以应该更频繁地调用它
  • 不幸的是,您的假设是错误的,这不是 TensorFlow 的工作方式,该层在每个阶段(训练或测试)调用一次并用于构建实际用于计算的计算图,这就是为什么你会看到这种行为。

标签: python tensorflow keras tensorflow1.15


【解决方案1】:

必须使用tf.Variableassign_add进行初始化和添加

class Dummy(keras.layers.Layer):
    def __init__(self, units=32, input_dim=32):
        super(Dummy, self).__init__()
        self.cnt = tf.Variable(1, trainable=False)

    def call(self, inputs):
        self.cnt = self.cnt.assign_add(1)
        return inputs

【讨论】:

  • 谢谢,当我用 model.layers[-2].cnt.eval(session=sess) 打印出它的值时,它仍然是 2
  • 不要在call 中重新分配self.cnt,它会起作用。即,删除call中的self.cnt =
猜你喜欢
  • 2011-12-31
  • 1970-01-01
  • 2020-01-20
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
  • 1970-01-01
  • 2017-12-03
相关资源
最近更新 更多