subclassing API: expected 'trainable' argument to be a boolean TF2
Question:
I am following a tutorial for TensorFlow subclassing API: https://www.youtube.com/watch?v=WcZ_1IAH_nM&ab_channel=AladdinPersson
When executing the code, I receive the following error:
TypeError: Expected `trainable` argument to be a boolean, but got: [32, 32, 64]
Which from what I gather comes from the ResBlock
(as if trying to use it in a tf.keras.Sequential([ResBlock([32, 32, 64]), ...])
) generates the same error.
I have tried introducing **kwargs
but it did not solve the problem.
This is the code:
import tensorflow as tf
from tensorflow.keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(-1, 28, 28, 1).astype("float32")/255.0 # divided by 255 to normalize the data
x_test = x_test.reshape(-1, 28, 28, 1).astype("float32")/255.0
# %%
# CNN -> BatchNorm -> ReLU (Common structure)
# same but 10 times
class CNNBlock(tf.keras.layers.Layer):
"""We input layers.Layer for backpropagation and everything """
def __init__(self, out_channels, kernel_size=3):
super(CNNBlock, self).__init__()
print("INIT OF CNNBlock")
self.conv = tf.keras.layers.Conv2D(out_channels, kernel_size, padding="same")
self.bn = tf.keras.layers.BatchNormalization() # works differently for training or evaluation
def call(self, input_tensor, training=False):
x = self.conv(input_tensor)
# print(x.shape)
x = self.bn(x, training=training)
x = tf.nn.relu(x)
return x
class ResBlock(tf.keras.layers.Layer):
def __init___(self, channels):
print('start resnet block inside init')
print(f'channels of resnet block, {channels}')
super(ResBlock, self).__init__()
print("INIT OF ResBlock")
# Each CNN Block is a convolution a batch norm and a relu
self.cnn1 = CNNBlock(channels[0])
self.cnn2 = CNNBlock(channels[1])
self.cnn3 = CNNBlock(channels[2])
self.pooling = tf.keras.layers.MaxPooling2D() # to have input size, height and width
# Identity mapping: same number of channels
# same convolution = height and width do not change but channels might
self.identity_mapping = tf.keras.layers.Conv2D(channels[1], kernel_size=1, padding="same")
def call(self, input_tensor, training=False):
x = self.cnn1(input_tensor, training=training)
x = self.cnn2(x, training=training)
x = self.cnn3(
x+self.identity_mapping(input_tensor), training=training
)
x = self.pooling(x)
return x
class ResNet_Like(tf.keras.Model):
def __init__(self, num_classes=10):
super(ResNet_Like, self).__init__()
print("INIT OF ResNet_Like")
self.block1 = ResBlock([32, 32, 64])
print('passed block1')
self.block2 = ResBlock([128, 128, 256])
self.block3 = ResBlock([128, 256, 512])
self.pool = tf.keras.layers.GlobalAveragePooling2D()
self.classifier = tf.keras.layers.Dense(num_classes)
def call(self, input_tensor, training=False):
x = self.block1(input_tensor, training=training)
x = self.block2(x, training=training)
x = self.block3(x, training=training)
x = self.pool(x)
return self.classifier(x)
def model(self):
"""Overwrite the function call in tf.Model"""
x = tf.keras.Input(shape=(28, 28, 1)) # input_tensor shape
return tf.keras.Model(inputs=[x], outputs=self.call(x))
# %%
#
# model0 = tf.keras.Sequential(
# [
# CNNBlock(32),
# CNNBlock(64),
# CNNBlock(128),
# tf.keras.layers.Flatten(),
# tf.keras.layers.Dense(10)
# ]
# )
#
# model0.compile(
# optimizer=tf.keras.optimizers.Adam(),
# loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
# metrics=["accuracy"],
# )
#
# model0.fit(x_train, y_train, batch_size=64, epochs=1, verbose=2)
#
# print(model0.summary()) # multiple --> due to subclassing
# print('finished')
# %%
channels_test = [100, 32, 64]
model = tf.keras.Sequential(
[
ResBlock(channels_test),
ResBlock([32, 32, 64]),
ResBlock([32, 32, 64]),
ResBlock([32, 32, 64]),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(10)
]
)
model.compile(
optimizer=tf.keras.optimizers.Adam(),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=["accuracy"],
)
model.fit(x_train, y_train, batch_size=64, epochs=1, verbose=2)
print(model.summary()) # multiple --> due to subclassing
print('finished')
Answers:
You have a typo in class ResBlock
, you don’t have an init function.
Change
def __init___(self, channels):
to
def __init__(self, channels):
Just 2 underscores not 3
I am following a tutorial for TensorFlow subclassing API: https://www.youtube.com/watch?v=WcZ_1IAH_nM&ab_channel=AladdinPersson
When executing the code, I receive the following error:
TypeError: Expected `trainable` argument to be a boolean, but got: [32, 32, 64]
Which from what I gather comes from the ResBlock
(as if trying to use it in a tf.keras.Sequential([ResBlock([32, 32, 64]), ...])
) generates the same error.
I have tried introducing **kwargs
but it did not solve the problem.
This is the code:
import tensorflow as tf
from tensorflow.keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(-1, 28, 28, 1).astype("float32")/255.0 # divided by 255 to normalize the data
x_test = x_test.reshape(-1, 28, 28, 1).astype("float32")/255.0
# %%
# CNN -> BatchNorm -> ReLU (Common structure)
# same but 10 times
class CNNBlock(tf.keras.layers.Layer):
"""We input layers.Layer for backpropagation and everything """
def __init__(self, out_channels, kernel_size=3):
super(CNNBlock, self).__init__()
print("INIT OF CNNBlock")
self.conv = tf.keras.layers.Conv2D(out_channels, kernel_size, padding="same")
self.bn = tf.keras.layers.BatchNormalization() # works differently for training or evaluation
def call(self, input_tensor, training=False):
x = self.conv(input_tensor)
# print(x.shape)
x = self.bn(x, training=training)
x = tf.nn.relu(x)
return x
class ResBlock(tf.keras.layers.Layer):
def __init___(self, channels):
print('start resnet block inside init')
print(f'channels of resnet block, {channels}')
super(ResBlock, self).__init__()
print("INIT OF ResBlock")
# Each CNN Block is a convolution a batch norm and a relu
self.cnn1 = CNNBlock(channels[0])
self.cnn2 = CNNBlock(channels[1])
self.cnn3 = CNNBlock(channels[2])
self.pooling = tf.keras.layers.MaxPooling2D() # to have input size, height and width
# Identity mapping: same number of channels
# same convolution = height and width do not change but channels might
self.identity_mapping = tf.keras.layers.Conv2D(channels[1], kernel_size=1, padding="same")
def call(self, input_tensor, training=False):
x = self.cnn1(input_tensor, training=training)
x = self.cnn2(x, training=training)
x = self.cnn3(
x+self.identity_mapping(input_tensor), training=training
)
x = self.pooling(x)
return x
class ResNet_Like(tf.keras.Model):
def __init__(self, num_classes=10):
super(ResNet_Like, self).__init__()
print("INIT OF ResNet_Like")
self.block1 = ResBlock([32, 32, 64])
print('passed block1')
self.block2 = ResBlock([128, 128, 256])
self.block3 = ResBlock([128, 256, 512])
self.pool = tf.keras.layers.GlobalAveragePooling2D()
self.classifier = tf.keras.layers.Dense(num_classes)
def call(self, input_tensor, training=False):
x = self.block1(input_tensor, training=training)
x = self.block2(x, training=training)
x = self.block3(x, training=training)
x = self.pool(x)
return self.classifier(x)
def model(self):
"""Overwrite the function call in tf.Model"""
x = tf.keras.Input(shape=(28, 28, 1)) # input_tensor shape
return tf.keras.Model(inputs=[x], outputs=self.call(x))
# %%
#
# model0 = tf.keras.Sequential(
# [
# CNNBlock(32),
# CNNBlock(64),
# CNNBlock(128),
# tf.keras.layers.Flatten(),
# tf.keras.layers.Dense(10)
# ]
# )
#
# model0.compile(
# optimizer=tf.keras.optimizers.Adam(),
# loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
# metrics=["accuracy"],
# )
#
# model0.fit(x_train, y_train, batch_size=64, epochs=1, verbose=2)
#
# print(model0.summary()) # multiple --> due to subclassing
# print('finished')
# %%
channels_test = [100, 32, 64]
model = tf.keras.Sequential(
[
ResBlock(channels_test),
ResBlock([32, 32, 64]),
ResBlock([32, 32, 64]),
ResBlock([32, 32, 64]),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(10)
]
)
model.compile(
optimizer=tf.keras.optimizers.Adam(),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=["accuracy"],
)
model.fit(x_train, y_train, batch_size=64, epochs=1, verbose=2)
print(model.summary()) # multiple --> due to subclassing
print('finished')
You have a typo in class ResBlock
, you don’t have an init function.
Change
def __init___(self, channels):
to
def __init__(self, channels):
Just 2 underscores not 3