We can create a Convolution Neural Network with variable size inputs
ip = keras.layers.Input((None, None, 3))
op = keras.layers.Conv2D(3, (2, 2))(ip)
model=keras.models.Model(inputs = [ip], outputs = [op])
Is there a way to know the size of the output layer op for a specific input?
I know there is a formula to calculate the size for this simple example. Is there a way I can have the model calculate the size for me?
One way I could do that would be to run some sample data through.
x = numpy.random.random((1, 64, 64, 3))
y = model(x)
Now I can see both of their shapes 1, 64, 64, 3 and 1, 63, 63, 3.
My goal is to be able to use different cnn networks, where I don't know how to calculate the size in general, for example a Resnet101. I have different scale values for the outputs, and I want to be able to scale my ground truth data during training.
Can I get the output size, just from the model and the input data without running a sample through?
UPDATE: as @matt mentioned, just calling model
with a new Input
is sufficient. No need to create a new model for different inputs. However in this case it is required to keep the respective dimensions unspecified. So this does not work:
import keras_core as keras
ip = keras.layers.Input((10, 10, 3))
op = keras.layers.Conv2D(3, (5, 5))(ip)
model = keras.models.Model(inputs = [ip], outputs = [op])
model(keras.layers.Input((100, 100, 3)))
While this does:
import keras_core as keras
ip = keras.layers.Input((None, None, 3))
op = keras.layers.Conv2D(3, (5, 5))(ip)
model = keras.models.Model(inputs = [ip], outputs = [op])
model(keras.layers.Input((100, 100, 3)))
If you still want a fixed, but different input, you have to implement something along the lines of what I suggested below:
When you use keras.layers.Input((100, 100, 3))
it actually creates a KerasTensor
object, which seem to be a lazy / uninitialized tensor object. Passing it recursively trough the other layers via __call__
, actually modifies the output shape (without computing any flops):
import keras_core as keras
ip = keras.layers.Input((100, 100, 3))
op = keras.layers.Conv2D(3, (5, 5))(ip)
print(op)
model = keras.models.Model(inputs = [ip], outputs = [op])
Prints:
<KerasTensor shape=(None, 96, 96, 3), dtype=float32, sparse=False, name=keras_tensor_39>
The same objects is also available via model.output
. I guess the solution here is to slightly refactor your code and define a function, that creates the model for a given different input, along the lines of:
import keras_core as keras
def create_model(ip):
op = keras.layers.Conv2D(3, (5, 5))(ip)
return keras.models.Model(inputs = [ip], outputs = [op])
model_1 = create_model(keras.layers.Input((10, 10, 3)))
model_2 = create_model(keras.layers.Input((100, 100, 3)))
print(model_1.output)
print(model_2.output)
Which prints:
[<KerasTensor shape=(None, 6, 6, 3), dtype=float32, sparse=False, name=keras_tensor_54>]
[<KerasTensor shape=(None, 96, 96, 3), dtype=float32, sparse=False, name=keras_tensor_56>]
I hope this helps.