Unexpected output shape from a keras dense layer - python

I try to create a minimal non-convolutional NN image binary classifier with one hidden layer only (as a practice before more complicated models):
def make_model(input_shape):
inputs = keras.Input(shape=input_shape)
x = layers.Dense(128, activation="ReLU")(inputs)
outputs = layers.Dense(1, activation="sigmoid")(x)
return keras.Model(inputs, outputs)
model = make_model(input_shape=(256, 256, 3))
Its model.summary() shows
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 256, 256, 3)] 0
dense (Dense) (None, 256, 256, 128) 512
dense_1 (Dense) (None, 256, 256, 1) 129
=================================================================
Total params: 641
Trainable params: 641
Non-trainable params: 0
Since the dense_1 layer has one neuron only, what I expect from this layer is an output shape of (None, 1) (i,e, a single number indicating the predicted binary label) but instead the model gives (None, 256, 256, 1).
What's wrong with my model setting and how can I get it right?

You have to flatten your preposterously large tensor if you want to use the output shape (None, 1):
import tensorflow as tf
def make_model(input_shape):
inputs = tf.keras.layers.Input(shape=input_shape)
x = tf.keras.layers.Dense(128, activation="relu")(inputs)
x = tf.keras.layers.Flatten()(x)
outputs = tf.keras.layers.Dense(1, activation="sigmoid")(x)
return tf.keras.Model(inputs, outputs)
model = make_model(input_shape=(256, 256, 3))
print(model.summary())

A mistake is in your function make_model.
def make_model(input_shape):
inputs = keras.Input(shape=input_shape)
x = layers.Dense(128, activation="ReLU")(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
return keras.Model(inputs, outputs)
You probably wanted the second line to be
x = layers.Dense(128, activation="ReLU")(inputs)
and not
x = layers.Dense(128, activation="ReLU")(x)
and unfortunately, x exists in scope, so it didn't throw an error.

Related

How to resolve ValueError: Graph disconnected: cannot obtain value for tensor KerasTensor

I am trying to get the embedding for a siamese network written in keras and I keep having the issue below. Does anyone know how to solve this issue?
Here is the network:
input = layers.Input((40, 1))
x = layers.Conv1D(8, 64, activation="relu", padding='same', kernel_regularizer=regularizers.L1L2(l1=1e-5, l2=1e-4),)(input)
x = layers.Conv1D(8, 128, activation="relu", padding='same', kernel_regularizer=regularizers.L1L2(l1=1e-5, l2=1e-4),)(x)
x = layers.AveragePooling1D(pool_size= 2, padding='same')(x)
x = layers.Flatten()(x)
x = layers.Dense(100, activation="relu")(x)
embedding_network = keras.Model(input, x)
input_1 = layers.Input((40, 1))
input_2 = layers.Input((40, 1))
cnn_1 = embedding_network(input_1)
cnn_2 = embedding_network(input_2)
merge_layer_1 = layers.Lambda(euclidean_distance)([cnn_1, cnn_2])
output_layer = layers.Dense(1, activation="sigmoid")(merge_layer_1)
siamese = keras.Model(inputs=[input_1, input_2], outputs=output_layer)
Here is the what it is done to get the embedding:
get_layer_output = tf.keras.backend.function([siamese.layers[0].input],[siamese.layers[-2].output])
Here is the error:
ValueError: Graph disconnected: cannot obtain value for tensor KerasTensor(type_spec=TensorSpec(shape=(None, 40, 1), dtype=tf.float32, name='input_3'), name='input_3', description="created by layer 'input_3'") at layer "model". The following previous layers were accessed without issue: ['model']
I tried to reproduce your code as some of the components, e.g. the euclidean_distance function, were missing. The following seems to work well on my system:
import tensorflow as tf
import keras.backend as K
def euclidean_distance(x):
return tf.expand_dims(K.sqrt(K.sum(K.square(x[0] - x[1]), axis=-1)), axis=1)
model_input = tf.keras.layers.Input((40, 1))
x = tf.keras.layers.Conv1D(8, 64, activation="relu", padding='same', kernel_regularizer=tf.keras.regularizers.L1L2(l1=1e-5, l2=1e-4),)(model_input)
x = tf.keras.layers.Conv1D(8, 128, activation="relu", padding='same', kernel_regularizer=tf.keras.regularizers.L1L2(l1=1e-5, l2=1e-4),)(x)
x = tf.keras.layers.AveragePooling1D(pool_size= 2, padding='same')(x)
x = tf.keras.layers.Flatten()(x)
x = tf.keras.layers.Dense(100, activation="relu")(x)
embedding_network = tf.keras.Model(model_input, x)
input_1 = tf.keras.layers.Input((40, 1))
input_2 = tf.keras.layers.Input((40, 1))
cnn_1 = embedding_network(input_1)
cnn_2 = embedding_network(input_2)
merge_layer_1 = tf.keras.layers.Lambda(euclidean_distance)([cnn_1, cnn_2])
output_layer = tf.keras.layers.Dense(1, activation="sigmoid")(merge_layer_1)
siamese = tf.keras.Model(inputs=[input_1, input_2], outputs=output_layer)
embedding_network.summary()
Output:
Model: "model"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 40, 1)] 0
conv1d (Conv1D) (None, 40, 8) 520
conv1d_1 (Conv1D) (None, 40, 8) 8200
average_pooling1d (AverageP (None, 20, 8) 0
ooling1D)
flatten (Flatten) (None, 160) 0
dense (Dense) (None, 100) 16100
=================================================================
Total params: 24,820
Trainable params: 24,820
Non-trainable params: 0
_________________________________________________________________
And, similarly
siamese.summary()
Model: "model_1"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_2 (InputLayer) [(None, 40, 1)] 0 []
input_3 (InputLayer) [(None, 40, 1)] 0 []
model (Functional) (None, 100) 24820 ['input_2[0][0]',
'input_3[0][0]']
lambda (Lambda) (None, 1) 0 ['model[0][0]',
'model[1][0]']
dense_1 (Dense) (None, 1) 2 ['lambda[0][0]']
==================================================================================================
Total params: 24,822
Trainable params: 24,822
Non-trainable params: 0
__________________________________________________________________________________________________
And, a simple test of the model:
batch_size=5
inp1=tf.random.uniform((batch_size, 40, 1))
inp2=tf.random.uniform((batch_size, 40, 1))
siamese([inp1, inp2])
Output:
<tf.Tensor: shape=(5, 1), dtype=float32, numpy=
array([[0.5550248 ],
[0.55784535],
[0.54480696],
[0.54240334],
[0.54322207]], dtype=float32)>

How to fix ValueError: Input 0 is incompatible with layer CNN: expected shape=(None, 35), found shape=(None, 31)

I am using Convolutional Neural Network to train a text classification task, using Keras, Conv1D. When I run the model below to my multi class text classification task, I get error such as following. I put time to undrestand the error but I don't know how to fix it. can anyone help me please?
The data set and evaluation set shape is such as following:
df_train shape: (7198,)
df_val shape: (1800,)
np.random.seed(42)
#You needs to reshape your input data according to Conv1D layer input format - (batch_size, steps, input_dim). Try
# set parameters of matrices and convolution
embedding_dim = 300
nb_filter = 64
filter_length = 5
hidden_dims = 32
stride_length = 1
from keras.layers import Embedding
embedding_layer = Embedding(len(tokenizer.word_index) + 1,
embedding_dim,
input_length=35,
name="Embedding")
inp = Input(shape=(35,), dtype='int32')
embeddings = embedding_layer(inp)
conv1 = Conv1D(filters=32, # Number of filters to use
kernel_size=filter_length, # n-gram range of each filter.
padding='same', #valid: don't go off edge; same: use padding before applying filter
activation='relu',
name="CONV1",
kernel_regularizer=regularizers.l2(l=0.0367))(embeddings)
conv2 = Conv1D(filters=32, # Number of filters to use
kernel_size=filter_length, # n-gram range of each filter.
padding='same', #valid: don't go off edge; same: use padding before applying filter
activation='relu',
name="CONV2",kernel_regularizer=regularizers.l2(l=0.02))(embeddings)
conv3 = Conv1D(filters=32, # Number of filters to use
kernel_size=filter_length, # n-gram range of each filter.
padding='same', #valid: don't go off edge; same: use padding before applying filter
activation='relu',
name="CONV2",kernel_regularizer=regularizers.l2(l=0.01))(embeddings)
max1 = MaxPool1D(10, strides=1,name="MaxPool1D1")(conv1)
max2 = MaxPool1D(10, strides=1,name="MaxPool1D2")(conv2)
max3 = MaxPool1D(10, strides=1,name="MaxPool1D2")(conv3)
conc = concatenate([max1, max2,max3])
flat = Flatten(name="FLATTEN")(max1)
....
Error is like following:
ValueError: Input 0 is incompatible with layer CNN: expected shape=(None, 35), found shape=(None, 31)
The model :
Model: "CNN"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
input_19 (InputLayer) [(None, 35)] 0
_________________________________________________________________
Embedding (Embedding) (None, 35, 300) 4094700
_________________________________________________________________
CONV1 (Conv1D) (None, 35, 32) 48032
_________________________________________________________________
MaxPool1D1 (MaxPooling1D) (None, 26, 32) 0
_________________________________________________________________
FLATTEN (Flatten) (None, 832) 0
_________________________________________________________________
Dropout (Dropout) (None, 832) 0
_________________________________________________________________
Dense (Dense) (None, 3) 2499
=================================================================
Total params: 4,145,231
Trainable params: 4,145,231
Non-trainable params: 0
_________________________________________________________________
Epoch 1/100
That error comes when you have not matched the network's input layer shape and the dataset's shape. If are you receiving an error like this, then you should try:
Set the network input shape at (None, 31) so that it matches the Dataset's shape.
Check that the dataset's shape is equal to (num_of_examples, 35).(Preferable)
If all of this informations are correct and there is no problem with the Dataset, it might be an error of the net itself, where the shapes af two adjcent layers don't match.

ValueError: Shape mismatch: The shape of labels (received (1,)) should equal the shape of logits except for the last dimension (received (10, 30))

i'm fairly new to tensorflow and would appreciate answers a lot.
i'm trying to use a transformer model as an embedding layer and feed the data to a custom model.
from transformers import TFAutoModel
from tensorflow.keras import layers
def build_model():
transformer_model = TFAutoModel.from_pretrained(MODEL_NAME, config=config)
input_ids_in = layers.Input(shape=(MAX_LEN,), name='input_ids', dtype='int32')
input_masks_in = layers.Input(shape=(MAX_LEN,), name='attention_mask', dtype='int32')
embedding_layer = transformer_model(input_ids_in, attention_mask=input_masks_in)[0]
X = layers.Bidirectional(tf.keras.layers.LSTM(50, return_sequences=True, dropout=0.1, recurrent_dropout=0.1))(embedding_layer)
X = layers.GlobalMaxPool1D()(X)
X = layers.Dense(64, activation='relu')(X)
X = layers.Dropout(0.2)(X)
X = layers.Dense(30, activation='softmax')(X)
model = tf.keras.Model(inputs=[input_ids_in, input_masks_in], outputs = X)
for layer in model.layers[:3]:
layer.trainable = False
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
return model
model = build_model()
model.summary()
r = model.fit(
train_ds,
steps_per_epoch=train_steps,
epochs=EPOCHS,
verbose=3)
I have 30 classes and the labels are not one-hot encoded so im using sparse_categorical_crossentropy as my loss function but i keep getting the following error
ValueError: Shape mismatch: The shape of labels (received (1,)) should equal the shape of logits except for the last dimension (received (10, 30)).
how can i solve this?
and why is the (10, 30) shape required? i know 30 is because of the last Dense layer with 30 units but why the 10? is it because of the MAX_LENGTH which is 10?
my model summary:
Model: "model_16"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_ids (InputLayer) [(None, 10)] 0
__________________________________________________________________________________________________
attention_mask (InputLayer) [(None, 10)] 0
__________________________________________________________________________________________________
tf_bert_model_21 (TFBertModel) TFBaseModelOutputWit 162841344 input_ids[0][0]
attention_mask[0][0]
__________________________________________________________________________________________________
bidirectional_17 (Bidirectional (None, 10, 100) 327600 tf_bert_model_21[0][0]
__________________________________________________________________________________________________
global_max_pooling1d_15 (Global (None, 100) 0 bidirectional_17[0][0]
__________________________________________________________________________________________________
dense_32 (Dense) (None, 64) 6464 global_max_pooling1d_15[0][0]
__________________________________________________________________________________________________
dropout_867 (Dropout) (None, 64) 0 dense_32[0][0]
__________________________________________________________________________________________________
dense_33 (Dense) (None, 30) 1950 dropout_867[0][0]
==================================================================================================
Total params: 163,177,358
Trainable params: 336,014
Non-trainable params: 162,841,344
10 is a number of sequences in one batch. I suspect that it is a number of sequences in your dataset.
Your model acting as a sequence classifier. So you should have one label for every sequence.

TensorFlow input shape error at Dense output layer is contradictory to what model.summary() says

I am playing around with an NLP problem (sentence classification) and decided to use HuggingFace's TFBertModel along with Conv1D, Flatten, and Dense layers. I am using the functional API and my model compiles. However, during model.fit(), I get a shape error at the output Dense layer.
Model definition:
# Build model with a max length of 50 words in a sentence
max_len = 50
def build_model():
bert_encoder = TFBertModel.from_pretrained(model_name)
input_word_ids = tf.keras.Input(shape=(max_len,), dtype=tf.int32, name="input_word_ids")
input_mask = tf.keras.Input(shape=(max_len,), dtype=tf.int32, name="input_mask")
input_type_ids = tf.keras.Input(shape=(max_len,), dtype=tf.int32, name="input_type_ids")
# Create a conv1d model. The model may not really be useful or make sense, but that's OK (for now).
embedding = bert_encoder([input_word_ids, input_mask, input_type_ids])[0]
conv_layer = tf.keras.layers.Conv1D(32, 3, activation='relu')(embedding)
dense_layer = tf.keras.layers.Dense(24, activation='relu')(conv_layer)
flatten_layer = tf.keras.layers.Flatten()(dense_layer)
output_layer = tf.keras.layers.Dense(3, activation='softmax')(flatten_layer)
model = tf.keras.Model(inputs=[input_word_ids, input_mask, input_type_ids], outputs=output_layer)
model.compile(tf.keras.optimizers.Adam(lr=1e-5), loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
# View model architecture
model = build_model()
model.summary()
Model: "model"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_word_ids (InputLayer) [(None, 50)] 0
__________________________________________________________________________________________________
input_mask (InputLayer) [(None, 50)] 0
__________________________________________________________________________________________________
input_type_ids (InputLayer) [(None, 50)] 0
__________________________________________________________________________________________________
tf_bert_model (TFBertModel) ((None, 50, 768), (N 177853440 input_word_ids[0][0]
input_mask[0][0]
input_type_ids[0][0]
__________________________________________________________________________________________________
conv1d (Conv1D) (None, 48, 32) 73760 tf_bert_model[0][0]
__________________________________________________________________________________________________
dense (Dense) (None, 48, 24) 792 conv1d[0][0]
__________________________________________________________________________________________________
flatten (Flatten) (None, 1152) 0 dense[0][0]
__________________________________________________________________________________________________
dense_1 (Dense) (None, 3) 3459 flatten[0][0]
==================================================================================================
Total params: 177,931,451
Trainable params: 177,931,451
Non-trainable params: 0
__________________________________________________________________________________________________
# Fit model on input data
model.fit(train_input, train['label'].values, epochs = 3, verbose = 1, batch_size = 16,
validation_split = 0.2)
And this is the error message:
ValueError: Input 0 of layer dense_1 is incompatible with the layer: expected axis -1 of input shape to have value 1152 but received
input with shape [16, 6168]
I am unable to understand how the input shape to layer dense_1 (the output dense layer) can be 6168? As per the model summary, it should always be 1152.
The shape of your input is likely not as you expect. Check the shape of train_input.

How can I insert a scalar value and a binary value to a layer (last layer) in keras?

I am trying to modify the network which is implemented here. This network uses chest x ray images as input and classifies it into 14 categories (13 types of diseases and no finding). The network does not take the patient age and gender as an input. So I want to provide the network with that information too. In short At the last 3 layers of the network is like the following:
bn (BatchNormalization) (None, 7, 7, 1024) 4096 conv5_block16_concat[0][0]
__________________________________________________________________________________________________
avg_pool (GlobalAveragePooling2 (None, 1024) 0 bn[0][0]
__________________________________________________________________________________________________
predictions (Dense) (None, 14) 14350 avg_pool[0][0]
So what I have done so far is the following:
I simply pop the last dense layer using model_vgg16.layers.pop().
Then as expexted the network turns into:
bn (BatchNormalization) (None, 7, 7, 1024) 4096 conv5_block16_concat[0][0]
__________________________________________________________________________________________________
avg_pool (GlobalAveragePooling2 (None, 1024) 0 bn[0][0]
I know that I can add a layer using:
new_layer = Dense(14, activation='softmax', name='my_dense')
inp = model.input
out = new_layer(model.layers[-1].output)
model2 = Model(inp, out)
But I do not know how to add a layer that takes the inputs from previous layer together with 1 scalar value (age [0:100]), and one binary value gender [0:1].
So How can I add a last layer that takes inputs from previous layer together with 1 scalar value and 1 binary value?
Edit: The base model I am using is DenseNet121. The some final layers looks like this:
EDIT
The way I load the model is the following:
cp = ConfigParser()
cp.read(config_file)
# default config
output_dir = cp["DEFAULT"].get("output_dir")
base_model_name = cp["DEFAULT"].get("base_model_name")
class_names = cp["DEFAULT"].get("class_names").split(",")
image_source_dir = cp["DEFAULT"].get("image_source_dir")
image_dimension = cp["TRAIN"].getint("image_dimension")
output_weights_name = cp["TRAIN"].get("output_weights_name")
weights_path = os.path.join(output_dir, output_weights_name)
best_weights_path = os.path.join(output_dir, f"best_{output_weights_name}")
model_weights_path = best_weights_path
model_factory = ModelFactory()
model = model_factory.get_model(
class_names,
model_name=base_model_name,
use_base_weights=False,
weights_path=model_weights_path)
Now the model is in variable model.
Then as suggested I do
x = model.output
flat1 = Flatten()(x)
and get this error:
ValueError: Input 0 is incompatible with layer flatten_27: expected min_ndim=3, found ndim=2
When I repeat the same thing after removing the last layer using model.layers.pop()
I still get the same error? Even though I have spent couple of hours cannot overcome that problem. So how can this be done?
try this
from keras.applications.densenet import DenseNet121
from keras.layers import Dense, GlobalAveragePooling2D,concatenate
input_image = Input(shape=(224, 224, 3))
# normalize age
input_age_and_gender = Input(shape=(2,))
base_model = DenseNet121(input_tensor=input_image, weights='imagenet', include_top=False)
x = base_model.output
encoded_image = GlobalAveragePooling2D()(x)
out = concatenate([encoded_image,input_age_and_gender])
output = Dense(14, activation='softmax')(out)
model = Model([input_image,input_age_and_gender],output)
You can have a multi input model.
So instead of just using this:
img_input = Input(shape=input_shape)
base_model = base_model_class(
include_top=False,
input_tensor=img_input,
input_shape=input_shape,
weights=base_weights,
pooling="avg")
x = base_model.output
predictions = Dense(len(class_names), activation="sigmoid", name="predictions")(x)
model = Model(inputs=img_input, outputs=predictions)
I am not sure what your base_model looks like there. BUT for the sake of it check the following, where the first input is imaginary and the shape of the second input should be the shape of your age_gender_df.values:
input1 = Input(shape=(64,64,1))
conv11 = Conv2D(32, kernel_size=4, activation='relu')(input1)
pool11 = MaxPooling2D(pool_size=(2, 2))(conv11)
conv12 = Conv2D(16, kernel_size=4, activation='relu')(pool11)
pool12 = MaxPooling2D(pool_size=(2, 2))(conv12)
flat1 = Flatten()(pool12)
# INSTEAD OF THE ABOVE INPUT I WROTE YOU CAN USE YOUR BASE MODEL
input2 = Input(shape=(2,2)) # HERE THIS SHOULD BE THE SHAPE OF YOUR AGE/GENDER DF
layer = Dense(10, activation='relu')(input2)
flat2 = Flatten()(layer)
merge = concatenate([flat1, flat2])
# interpretation model
hidden1 = Dense(10, activation='relu')(merge)
hidden2 = Dense(10, activation='relu')(hidden1)
output = Dense(14, activation='linear')(hidden2)
model = Model(inputs=[input1, input2], outputs=output)
Summary
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_30 (InputLayer) (None, 64, 64, 1) 0
__________________________________________________________________________________________________
conv2d_23 (Conv2D) (None, 61, 61, 32) 544 input_30[0][0]
__________________________________________________________________________________________________
max_pooling2d_23 (MaxPooling2D) (None, 30, 30, 32) 0 conv2d_23[0][0]
__________________________________________________________________________________________________
conv2d_24 (Conv2D) (None, 27, 27, 16) 8208 max_pooling2d_23[0][0]
__________________________________________________________________________________________________
input_31 (InputLayer) (None, 2, 2) 0
__________________________________________________________________________________________________
max_pooling2d_24 (MaxPooling2D) (None, 13, 13, 16) 0 conv2d_24[0][0]
__________________________________________________________________________________________________
dense_38 (Dense) (None, 2, 10) 30 input_31[0][0]
__________________________________________________________________________________________________
flatten_23 (Flatten) (None, 2704) 0 max_pooling2d_24[0][0]
__________________________________________________________________________________________________
flatten_24 (Flatten) (None, 20) 0 dense_38[0][0]
__________________________________________________________________________________________________
concatenate_9 (Concatenate) (None, 2724) 0 flatten_23[0][0]
flatten_24[0][0]
__________________________________________________________________________________________________
dense_39 (Dense) (None, 10) 27250 concatenate_9[0][0]
__________________________________________________________________________________________________
dense_40 (Dense) (None, 10) 110 dense_39[0][0]
__________________________________________________________________________________________________
dense_41 (Dense) (None, 14) 154 dense_40[0][0]
==================================================================================================
Total params: 36,296
Trainable params: 36,296
Non-trainable params: 0
Visualisation:
EDIT:
In your case I suppose the model should look like the following:
img_input = Input(shape=input_shape)
base_model = base_model_class(
include_top=False,
input_tensor=img_input,
input_shape=input_shape,
weights=base_weights,
pooling="avg")
x = base_model.output
flat1 = Flatten()(x)
input2 = Input(shape=(2,2)) # HERE THIS SHOULD BE THE SHAPE OF YOUR AGE/GENDER DF
layer = Dense(10, activation='relu')(input2)
flat2 = Flatten()(layer)
merge = concatenate([flat1, flat2])
# interpretation model
hidden1 = Dense(10, activation='relu')(merge)
hidden2 = Dense(10, activation='relu')(hidden1)
output = Dense(14, activation='linear')(hidden2)
model = Model(inputs=[img_input, input2], outputs=output)
Issue is solved by first removing the last layer (prediction layer) by
model_original.layers.pop()
Then defining another model which is the replica of the original model except the last layer
model2 = keras.Model(model_original.input, model_original.layers[-1].output)
after that the input, which includes the age is defined
age = layers.Input(shape=(1,))
Next, age input and the last layer of the previously defined network is concatenated using
x = model2.output
concatenated = layers.concatenate([x, age])
In th final step, a prediction layer is added after the concatenation to complete the network
output = Dense(14, activation='linear')(concatenated)
model3 = keras.Model(inputs=[model_original.input, age], outputs=output)
So the final layers of the design looks like that:

Categories