Shape mismatch, 2D Input & 2D Labels - python

I want to create a neural network, that -easy speaking- creates an image out of an image (greyscale)
I have successfully created a dataset of 3200 examples of input and output (label) images.
(I know the dataset should be larger but that is not the problem right now)
The input [Xin] has the size (3200, 50, 30), since it is 50*30 pixels
The output [yout] has the size of (3200, 30, 20) since it is 30*20 pixels
I want to try out a fully connected network (later on a CNN)
The built of the fully connected model looks like that:
# 5 Create Model
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(256, activation=tf.nn.relu))
model.add(tf.keras.layers.Dense(30*20, activation=tf.nn.relu))
#compile the model
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 6 Train the model
model.fit(Xin, yout, epochs=1) #train the model
After that I get the following error:
ValueError: Shape mismatch: The shape of labels (received (19200,)) should equal the shape of logits except for the last dimension (received (32, 600)).
I already tried to flatten yout:
youtflat = yout.transpose(1,0,2).reshape(-1,yout.shape[1]*yout.shape[2])
but this resulted in the same error

It appears you're flattening your labels (yout) completely, i.e., you're losing batch dimension. If your original yout has a shape of (3200, 30, 20) you should reshape it to have a shape of (3200, 30*20) which equals (3200, 600):
yout = numpy.reshape((3200, 600))
Then it should work
NOTE
The suggested fix however only removes the error. I see many problems with your method though. For the task you're trying to perform (getting an image as output), you cannot use sparse_categorical_crossentropy as loss and accuracy as metrics. You should use 'mse' or 'mae' instead.

Related

Predicting a single PNG image using a trained TensorFlow model

import tensorflow as tf
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape = (28,28)),
tf.keras.layers.Dense(128, activation = 'relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10)
])
This is the code for the model, which I have trained using the mnist dataset. What I want to do is to then pass a 28x28 png image to the predict() method, which is not working. The code for the prediction is:
img = imageio.imread('image_0.png')
prediction = model.predict(img, batch_size = 1)
which produces the error
ValueError: Error when checking input: expected flatten_input to have shape (28, 28) but got array with shape (28, 3)
I have been stuck on this problem for a few days, but I can't find the correct way to pass an image into the predict method. Any help?
Predict function makes predictions over a batch of image. You should include batch dimension (first dimension) to your img, even to predict a single example.
You need something like this:
img = imageio.imread('image_0.png')
img = np.expand_dims(img, axis=0)
prediction = model.predict(img)
As #desertnaut says, seems you are using a RGB image, so your first layer should use input_shape = (28,28,3). Therefore, img parameter of predict function should have (1,28,28,3) shape.
In your case, img parameter of predict function has (28,28,3) shape, thus predict function took the first dimension as number of images, and could not match the other two dimensions to the input_shape of the first layer.

TensorFlow Keras dimension error for input layer

I've searched through all the solutions related to this, and I still can't figure out how to shape my training data so Tensorflow accepts it.
My training data is a numpy array of shape (21005, 48, 48), where the 21005 is number of elements and the 48,48 is a 48x48 grayscale image.
model.add(tf.keras.layers.Conv2D(64, kernel_size=3,activation='relu',input_shape=(48,48,1)))
model.add(tf.keras.layers.Conv2D(32, kernel_size=3,activation='relu'))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(7, activation='softmax'))
model.compile(optimizer='adam',
loss = 'sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(image_train, emotion_train,batch_size=BATCH_SIZE,epochs=EPOCHS, verbose=1)
When I run the fit function, however, it returns an error stating:
ValueError: Error when checking input: expected conv2d_input to have 4 dimensions, but got array with shape (21005, 48, 48)
This leads me to think I'm formatting the input data incorrectly, or missing something regarding how Keras and TF actually pass the input image into the input layer. I've tried adding the extra dimension to the input shape to allow for a channel in a 2d Conv layer, as well as reshaping the images themselves to no avail. Any advice?
Reshape your training data to have 4-dimensions before calling model.fit() such as:
image_train = np.reshape(image_train, (21005, 48, 48, 1))
This is needed because the first Conv2D layer expects an image to have an input_shape of (48,48,1)
When you made your preprocessing, you might have read the image in grayscale mode with a library OpenCV/PIL.
When you read them, your library considers a grayscale image of size (48,48), not a (48,48,1), hence the issue that you have.
Solve the issue as soon as possible, not before feeding to your model; in your code, wherever you read those images, before appending to your list/arrays, ensure the right shape of the array is picked. You can see down below an OpenCV example:
image = cv2.imread(filepath, 0)
#Before this np_expand_dims, image has shape (48,48)
image = np.expand_dims(image , axis=2)
#After this step, image has shape (48,48,1)

Bi-directional LSTM for entity recognition

Following a paper, I'm using word embeddings as a feature vector for entity recognition.
I've attempted to architect the network using Keras but have run into a dimensionality problem I cannot seem to resolve.
Take the following example sentence:
["I went to the shop"]
The sentence has 5 words, and after computing the feature matrix, I am left with a matrix of dimension: (1, 120, 1000) == (#examples, sequence_length, embedding).
Note that sequence_length appends 0. padding when not complete. In this example, the actual sequence_length would be 5.
My network architecture is as follows:
enc = encode()
claims_input = Input(shape=(120, 1000), dtype='float32', name='claims')
x = Masking(mask_value=0., input_shape=(120, 1000))(claims_input)
x = Bidirectional(LSTM(units=512, return_sequences=True, recurrent_dropout=0.2, dropout=0.2))(x)
x = Bidirectional(LSTM(units=512, return_sequences=True, recurrent_dropout=0.2, dropout=0.2))(x)
out = TimeDistributed(Dense(8, activation="softmax"))(x)
model = Model(inputs=claims_input, output=out)
model.compile(loss="sparse_categorical_crossentropy", optimizer='adam', metrics=["accuracy"])
model.fit(enc, y)
The architecture is straight forward, I mask specific time steps, run two bidirectional LSTMs, followed by a softmax output. My y variable in this case, is a (9,8) one-hot-encoded matrix corresponding to the gold label of each word.
When trying to fit() this model, I am running into a dimensionality problem relating to the TimeDistributed() layer and I'm unsure how to resolve, or even begin to debug this.
Error: ValueError: Error when checking target: expected time_distributed_1 to have 3 dimensions, but got array with shape (9, 8)
Any help would be appreciated.
You are doing entity recognition. So each element in your input sequence will be assigned an entity (probably some of them as null). If your model takes an input sample of shape (120, n_features), then the output must also be a sequence of length of 120, i.e. one entity for each element. Therefore, the labels, i.e. y, you provide to the model must have a shape of (n_samples, 120, n_entities) (or (n_samples, 120, 1) if you are using sparse labeling).
Side note: There is no difference between TimeDistributed(Dense(...)) and Dense(...), as the Dense layer is applied on the last axis.

Dataset shape mismatch Conv1D input layer

Trying to set up a Conv1D layer to be the input layer in keras.
The dataset is 1000 timesteps, and each timestep has 1 feature.
After reading a bunch of answers I reshaped my dataset to be in the following format of (n_samples, timesteps, features), which corresponds to the following in my case:
train_data = (78968, 1000, 1)
test_data = (19742, 1000, 1)
train_target = (78968,)
test_target = (19742,)
I later create and compile the code using the following lines
model = Sequential()
model.add(Conv1D(64, (4), input_shape = (1000,1) ))
model.add(MaxPooling1D(pool_size=2))
model.add(Dense(1))
optimizer = opt = Adam(decay = 1.000-0.999)
model.compile(optimizer=optimizer,
loss='mean_squared_error',
metrics=['mean_absolute_error','mean_squared_error'])
Then I try to fit, note, train_target and test_target are pandas series so i'm calling DataFrame.values to convert to numpy array, i suspect there might be an issue there?
training = model.fit(train_data,
train_target.values,
validation_data=(test_data, test_target.values),
epochs=epochs,
verbose=1)
The model compiles but I get an error when I try to fit
Error when checking target: expected dense_4 to have 3 dimensions,
but got array with shape (78968, 1)
I've tried every combination of reshaping the data and can't get this to work.
I've used keras with dense layers only before for a different project where the input_dimension was specificied instead of the input_shape, so I'm not sure what I'm doing wrong here. I've read almost every stack overflow question about data shape issues and I'm afraid the problem is elsewhere, any help is appreciated, thank you.
Under the line model.add(MaxPooling1D(pool_size=2)), add one line model.add(Flatten()), your problem will be solved. Flatten function will help you convert your data into correct shape, please see this site for more information https://www.tensorflow.org/api_docs/python/tf/keras/layers/Flatten

Error when checking input in first layer of Keras Conv1D

I'm trying to assign one of two classes (positive/nagative) to audio using CNN with Keras. My model should accept varied lengths of input (frames) in which each frame contains 41 features but I struggle with the input size. Bear in mind that I haven't acquired full dataset so I just mocked some meaningless data just to check if network works at all.
According to documentation https://keras.io/layers/convolutional/ and my best understanding Conv1D can tackle varied lengths if first element of input_shape tuple is None. Shape of variable containing input data X_train.shape is (4, 497, 41).
data = pd.read_csv('output_file.csv', sep=';')
featureCount = data.values.shape[1]
#mocks because full data is not available yet
Y_train = np.asarray([1, 0, 1, 0])
X_train = np.asarray(
[np.array(data.values, copy=True), np.array(data.values, copy=True), np.array(data.values, copy=True),
np.array(data.values, copy=True)])
# variable length with 41 features
model = keras.models.Sequential()
model.add(keras.layers.Conv1D(100, 5, activation='relu', input_shape=(None, featureCount)))
model.add(keras.layers.GlobalMaxPooling1D())
model.add(keras.layers.Dense(10, activation='relu'))
model.add(keras.layers.Dense(1, activation='sigmoid'))
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
model.summary()
model.fit(X_train, Y_train, epochs=10, verbose=False, validation_data=(np.array(data.values, copy=True), [1]))
This code produces error
ValueError: Error when checking input: expected conv1d_input to have 3 dimensions, but got array with shape (497, 41). So it appears like the first dimension was cut out as it contains training samples (it seems correct to me) what bothered me is the required dimensionality, why is it 3?
After searching for the answer I stumbled onto Dimension of shape in conv1D and followed it by adding last dimension (using X_train = np.expand_dims(X_train, axis=3)) that contains only single digit but I ended up with another, similar error:
ValueError: Error when checking input: expected conv1d_input to have 3 dimensions, but got array with shape (4, 497, 41, 1) now it seems that first dimension that previously was treated as sample "list" is now part of actual data.
I also tried fiddling with input_shape parameter but to no avail and using Reshape layer but ended up fighting with size the
What should I do to satisfy required shape? How to prepare data for processing?

Categories