Reputation: 259
I am using the subclassing API in keras and I am getting the following error when I try to build the model, and I cannot find anything about the issue on github. As a note I set training to false cause I plan to just upload weights I already have saved.
class VggBlock(Model):
def __init__(self):
super(VggBlock,self).__init__()
self.conv1=Conv2D(filters=64,kernel_size=(3,3),padding='same')
self.conv2=Conv2D(filters=128,kernel_size=(3,3),padding='same')
self.conv3=Conv2D(filters=256,kernel_size=(3,3),padding='same')
self.conv4=Conv2D(filters=512,kernel_size=(3,3),padding='same')
self.relu=Activation('relu')
self.pool=MaxPooling2D((2,2),strides=(2,2))
def call(self,inputs,training=False):
x=self.conv1(inputs)
x=self.relu(x)
x=self.conv1(x)
x=self.relu(x)
x=self.pool(x)
x=self.conv2(x)
x=self.relu(x)
x=self.conv2(x)
x=self.relu(x)
x=self.pool(x)
x=self.conv3(x)
x=self.relu(x)
x=self.conv3(x)
x=self.relu(x)
x=self.conv3(x)
x=self.relu(x)
x=self.conv3(x)
x=self.relu(x)
x=self.pool(x)
x=self.conv4(x)
x=self.relu(x)
x=self.conv4(x)
x=self.relu(x)
x=self.conv3(x)
x=self.relu(x)
x=self.conv2(x)
x=self.relu(x)
return x
model = VggBlock()
model.build((1,224,224,3))
model.summary()
When I try to call model.summary() I get the following error:
RuntimeError: You tried to call
count_params
on conv2d_22, but the layer isn't built. You can build it manually via:conv2d_22.build(batch_input_shape)
.
Upvotes: 0
Views: 975
Reputation: 701
import keras
from keras import Model
from keras.layers import Conv2D,Activation,MaxPooling2D
class VggBlock:
def __init__(self,inp_shape=(224,224,3),trainable=False):
#super(VggBlock,self).__init__()
# write whatever you want here...
# also no need to write these layers too, just use the functions get_CONV...
# you can just store parameters here you would want for each layer...according to you
self.conv1=Conv2D(filters=64,kernel_size=(3,3),padding='same',input_shape=inp_shape,trainable=trainable)
self.conv1_dup = Conv2D(filters=64,kernel_size=(3,3),padding='same',trainable=trainable)
self.conv2=Conv2D(filters=128,kernel_size=(3,3),padding='same',trainable=trainable)
self.conv3=Conv2D(filters=256,kernel_size=(3,3),padding='same',trainable=trainable)
self.conv4=Conv2D(filters=512,kernel_size=(3,3),padding='same',trainable=trainable)
self.relu=Activation('relu')
self.pool=MaxPooling2D((2,2),strides=(2,2))
def get_CONV(self,layer,name):
return Conv2D(filters=layer.filters,kernel_size=layer.kernel_size,padding=layer.padding,trainable=False,
name=name)
def get_model(self,inputs,training=False):
x=self.conv1(inputs)
x=self.relu(x)
x=self.get_CONV(self.conv1,name='conv1_duplicate')(x) #self.conv1(x)
x=self.relu(x)
x=self.pool(x)
.
.
.
#same as before
return keras.Model(inputs,x) #this is a keras Model object and it has all the functions you need.
vggClass = VggBlock(inp_shape=(224,224,32))
inp = keras.Input(shape=(224,224,32))
m = vggClass.get_model(inp)
m.summary() #works
Upvotes: 1
Reputation: 701
okay so I did some changes.
import keras
from keras import Model
from keras.layers import Conv2D,Activation,MaxPooling2D
class VggBlock(Model):
def __init__(self,inp_shape=(224,224,3)):
super(VggBlock,self).__init__()
self.conv1=Conv2D(filters=64,kernel_size=(3,3),padding='same',input_shape=inp_shape)
self.conv2=Conv2D(filters=128,kernel_size=(3,3),padding='same')
self.conv3=Conv2D(filters=256,kernel_size=(3,3),padding='same')
self.conv4=Conv2D(filters=512,kernel_size=(3,3),padding='same')
self.relu=Activation('relu')
self.pool=MaxPooling2D((2,2),strides=(2,2))
def get_new_layer(self,layer):
return Conv2D(filters=layer.filters,kernel_size=layer.kernel_size,padding=layer.padding)
def call(self,inputs,training=False):
x=self.conv1(inputs)
x=self.relu(x)
x=self.get_new_layer(self.conv1)(x) #self.conv1(x)
x=self.relu(x)
x=self.pool(x)
x=self.conv2(x)
x=self.relu(x)
x=self.get_new_layer(self.conv2)(x) #self.conv2(x)
x=self.relu(x)
x=self.pool(x)
x=self.conv3(x)
x=self.relu(x)
x=self.get_new_layer(self.conv3)(x) #self.conv3(x)
x=self.relu(x)
x=self.get_new_layer(self.conv3)(x)#self.conv3(x)
x=self.relu(x)
x=self.get_new_layer(self.conv3)(x)#self.conv3(x)
x=self.relu(x)
x=self.pool(x)
x=self.conv4(x)
x=self.relu(x)
x=self.get_new_layer(self.conv4)(x)#self.conv4(x)
x=self.relu(x)
x=self.get_new_layer(self.conv3)(x)#self.conv3(x)
x=self.relu(x)
x=self.get_new_layer(self.conv2)(x)#self.conv2(x)
x=self.relu(x)
print(x.shape)
return x
def compute_output_shape(self, input_shape):
return (None,None,128)
model = VggBlock(inp_shape=(224,224,32))
inp = keras.Input(shape=(224,224,32))
out = model(inp)
model.summary() #works
Check the model for other functions like train,save,compile etc. And that error you mentioned in the comment, is because you need to write your own function to compute_output_shape
when subclassing models.
Upvotes: 1
Reputation: 86650
Warning: this model will not work because the input channels you are giving to the same convolution layer are different
It seems a bug in the framework. You build the model, all layers should be automatically built, but this is not happening.
So, I suggest you pass an input to the model (and then you will see the problem I mentioned before):
inputs = Input((224,224,3))
outputs = model(inputs)
model.summary()
#but it's better to do this with actual tensors, not with this dummy input
Upvotes: 1