Reputation: 1161
I wanted to subclass a sequential model in order to be able to write a custom call()
and handle named inputs. However, I got, for me, some unexpected behavior already for very minor changes to the __init__
function. If I try to add a new member to my subclass and initialize it after calling super().__init__()
the model fails to build automatically.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Activation, MaxPooling2D, Dense, Flatten
import tensorflow as tf
class Sequential2(Sequential):
def __init__(self):
super(Sequential2, self).__init__()
self.custom_member = []
def get_my_custom_member(self):
return self.custom_member
model = Sequential2()
if tf.keras.backend.image_data_format() == 'channels_first':
input_shape = (1, 28, 28)
else:
assert tf.keras.backend.image_data_format() == 'channels_last'
input_shape = (28, 28, 1)
layers = [Conv2D(32, (3, 3), input_shape=input_shape)]
for layer in layers:
model.add(layer)
model.add(Dense(10))
model.add(Activation('relu'))
model.summary()
fails with output: ValueError: This model has not yet been built. Build the model first by calling `build()` or calling `fit()` with some data, or specify an `input_shape` argument in the first layer(s) for automatic build.
However if self.custom_member = []
is left out it works as expected.
What am I missing here? (tested with Tensorflow 1.14)
Upvotes: 1
Views: 1248
Reputation:
This issue was fixed in TF 2.2
. You can refer working code as shown below
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Activation, MaxPooling2D, Dense, Flatten
import tensorflow as tf
print(tf.__version__)
class Sequential2(Sequential):
def __init__(self):
super(Sequential2, self).__init__()
self.custom_member = []
def get_my_custom_member(self):
return self.custom_member
model = Sequential2()
if tf.keras.backend.image_data_format() == 'channels_first':
input_shape = (1, 28, 28)
else:
assert tf.keras.backend.image_data_format() == 'channels_last'
input_shape = (28, 28, 1)
layers = [Conv2D(32, (3, 3), input_shape=input_shape)]
for layer in layers:
model.add(layer)
model.add(Dense(10))
model.add(Activation('relu'))
model.summary()
Output:
2.2.0
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 26, 26, 32) 320
_________________________________________________________________
dense (Dense) (None, 26, 26, 10) 330
_________________________________________________________________
activation (Activation) (None, 26, 26, 10) 0
=================================================================
Total params: 650
Trainable params: 650
Non-trainable params: 0
_________________________________________________________________
Upvotes: 1