【问题标题】:Keras Subclassing TypeError: tf__call() got multiple values for argument 'training'Keras 子类化类型错误:tf__call() 为参数“训练”获得了多个值
【发布时间】:2020-10-16 00:24:30
【问题描述】:

我似乎无法在网上找到问题的原因或类似问题。当我弄清楚这一点时,我会更新。

背景

作为一个项目,我正在使用 tensorflow 和 keras API 创建一个 python 脚本,以通过模型子类化构建自定义 U-net(例如,this keras tutorial)。我创建了自己的图层类、模型类、设置参数、加载数据等,并调用了model.fit(...)

问题

我收到以下错误和回溯:

Epoch 1/50
Traceback (most recent call last):

  File "C:\...\path\to\main\code\my_code.py", line 418, in <module>
    history = model.fit(x=train_ds, validation_data=val_ds, epochs=epochs, verbose=1)

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\keras\engine\training.py", line 108, in _method_wrapper
    return method(self, *args, **kwargs)

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\keras\engine\training.py", line 1098, in fit
    tmp_logs = train_function(iterator)

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\eager\def_function.py", line 780, in __call__
    result = self._call(*args, **kwds)

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\eager\def_function.py", line 823, in _call
    self._initialize(args, kwds, add_initializers_to=initializers)

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\eager\def_function.py", line 697, in _initialize
    *args, **kwds))

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\eager\function.py", line 2855, in _get_concrete_function_internal_garbage_collected
    graph_function, _, _ = self._maybe_define_function(args, kwargs)

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\eager\function.py", line 3213, in _maybe_define_function
    graph_function = self._create_graph_function(args, kwargs)

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\eager\function.py", line 3075, in _create_graph_function
    capture_by_value=self._capture_by_value),

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\framework\func_graph.py", line 986, in func_graph_from_py_func
    func_outputs = python_func(*func_args, **func_kwargs)

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\eager\def_function.py", line 600, in wrapped_fn
    return weak_wrapped_fn().__wrapped__(*args, **kwds)

  File "C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\framework\func_graph.py", line 973, in wrapper
    raise e.ag_error_metadata.to_exception(e)

TypeError: in user code:

    C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\keras\engine\training.py:806 train_function  *
        return step_function(self, iterator)

    TypeError: tf__call() got multiple values for argument 'training'

错误出现在keras training.py 脚本中。但是,我是面向对象编程、tensorflow 和 keras 的新手,所以我的第一个想法是,问题来自于我定义类方法的参数的方式或我使用 tensorflow 工具集的方式.以下是我的代码的简化版本,可能会有所帮助:

import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Conv2D, Layer, MaxPool2D, UpSampling2D, Input, GaussianNoise 
from tensorflow.keras.layers import Softmax, LeakyReLU, ReLU, Concatenate, BatchNormalization
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
import os
import pickle

tf.config.experimental.list_physical_devices('GPU')


# === Define layer and model classes ===

# ... define custom subclasses that inherit keras.layer.Layer
# ... example:

class sampleLayer2(Layer):
   def __init__(self, name='layer1', **kwargs):
      super().__init__()
      self.sample_layer1 = sampleLayer1(...)
      self.relu = ReLU()
      self.batch_norm = BatchNormalization()

   def call(self, layer_in, training=False):
      x = self.sample_layer1(layer_in)
      x = self.batch_norm(inputs=x)
      x = self.relu(x)
      # ...
      return x

# ...
# ... other custom subclasses similar to above example...
# ...

# define model:
class UNet(Model):
   def __init__(self, input_shape, name='unet', **kwargs):
      super().__init__()
      self.inputs = Input(input_shape)
      self.sample_layera = sampleLayerA()
      self.sample_layerb = sampleLayerB()
      self.sample_layerc = sampleLayerC()
      self.sample_layerd = sampleLayerD()
      self.sample_layere = sampleLayerE()
      # ... other layers that adjust depth ...
      self.gaussian = GaussianNoise(.12)
      self.pool = MaxPool2D(pool_size=(2, 2), strides=(2, 2)) # reduce feature dimensions
      self.upsample = UpSampling2D(size=(2, 2)) # increase feature dimensions
      self.batch_norm = BatchNormalization()
      self.concat = Concatenate()
      self.softmax = Softmax()
      
   def call(self, training=False):
      a = self.inputs
      a = self.gaussian(a) 
      a = self.sample_layera(a) # begin encoder
      b = self.pool(a)
      b = self.sample_layerb(b)
      c = self.pool(b)
      c = self.sample_layerc(c)
      d = self.pool(c)
      d = self.sample_layerd(d)
      e = self.pool(d)
      e = self.sample_layere(e)
      e_up = self.upsample(e)
      # ... layer adjusting depth ...
      d = self.concat([e_up, d])
      d = self.sample_layerd(d)
      d_up = self.upsample(d)
      # ... layer adjusting depth ...
      c = self.concat([d_up, c])
      c = self.sample_layerc(c)
      c_up = self.upsample(c)
      # ... layer adjusting depth ...
      b = self.concat([c_up, b])
      b = self.sample_layerb(b)
      b_up = self.upsample(b)
      # ... layer adjusting depth ...
      a = self.concat([b_up, a])
      a = self.sample_layera(a)
      # ... layer adjusting depth ...
      # ... layer adjusting depth ...
      a = self.batch_norm(inputs=a)
      final_layer = self.softmax(a)
      
      model = Model(inputs=self.inputs, outputs=final_layer)
      
      return model


# === Define Parameters ===

np.random.seed(27)
tf.random.set_seed(27)

img_height = ## some number
img_width = ##
input_depth = ##
epochs = 50
learning_rate = 5e-4 
batch_size_train = 32 
batch_size_val = 128 
opt = Adam(lr=learning_rate, beta_1=.9, beta_2=.999, epsilon=1e-8)


# === Set up Datasets ===

# ...
# ... define data directories
# ...

# ...
# ... define generators that ingest and process input and output data
# ...

# ...
# ... Using generators, create tf.data.Dataset objects for training and validation set ...
# ... result is train_ds_in, train_ds_out, val_ds_in, val_ds_out ...  

train_ds = tf.data.Dataset.zip((train_ds_in, train_ds_out)) # combine input-output pairs in new dataset
train_ds = train_ds.shuffle(100).batch(batch_size_train) # set batches and shuffling of the dataset

# ...same for validation data ...
val_ds = tf.data.Dataset.zip((val_ds_in, val_ds_out))
val_ds = val_ds.shuffle(100).batch(batch_size_val)


# === Compile and fit the model ===

input_size = (None, img_height, img_width, input_depth)

model = UNet(input_size)  

model.compile(optimizer=opt, loss='mae', metrics=['accuracy'])
      
# we already have batches and shuffling
history = model.fit(x=train_ds, validation_data=val_ds, epochs=epochs, verbose=1)

我的解决方法

我尝试将*args**kwargs 作为模型和层、__init__call 方法的参数插入,但没有任何变化。对于调用BatchNormalization() 的所有实例,我插入了trainable=training 并且没有更改。最后,我从 UNet call 方法中删除了 training=None 参数,得到了一个稍微不同的错误:

TypeError: in user code:

    C:\...\anaconda3\envs\my_env\lib\site-packages\tensorflow\python\keras\engine\training.py:806 train_function  *
        return step_function(self, iterator)

    TypeError: tf__call() takes 1 positional argument but 2 were given

似乎问题出在 UNet 类中的 call 方法中。作为参考,我使用 python 版本 3.7.7,tensorflow 版本 2.3.1,tf.keras 版本 2.4.0 ...

我的方法是否存在明显的问题导致此问题?任何有用的提示表示赞赏。谢谢。

【问题讨论】:

    标签: python tensorflow keras deep-learning


    【解决方案1】:

    我在my_env 中卸载然后重新安装tensorflow,我不再收到错误。

    tensorflow-gpu 之前已安装,而 tensorflow 已存在于 my_env 中,可能导致模块不兼容或相互竞争。

    【讨论】:

      猜你喜欢
      • 2020-10-19
      • 2022-01-24
      • 2019-12-24
      • 2019-05-28
      • 1970-01-01
      • 2021-08-17
      • 1970-01-01
      • 2020-01-30
      • 1970-01-01
      相关资源
      最近更新 更多