ValueError: Data cardinality is ambiguous. Make sure all arrays contain the same number of samples - tensorflow

This is a regression problem, where I want to generate 5 float values from each image of size 224 x 224. So I use fully connected networks with 5 nodes in the last layer. But doing so in keras gives me the following error:
import keras, os
import numpy as np
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.applications.inception_v3 import InceptionV3
## data_list = list of four 224x224 numpy arrays
inception = InceptionV3(weights='imagenet', include_top=False)
x = inception.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(5, activation='relu')(x)
y = [np.random.random(5),np.random.random(5),np.random.random(5),np.random.random(5)]
model = Model(inputs=inception.input, outputs=predictions)
opt = Adam(lr=0.001)
model.compile(optimizer=opt, loss="mae")
model.fit(data_list, y, verbose=0, epochs=100)
Error:
ValueError: Data cardinality is ambiguous:
     x sizes: 224, 224, 224, 224
     y sizes: 5, 5, 5, 5
Make sure all arrays contain the same number of samples.
What could be going wrong?

Convert data_list and y to numpy arrays or tensors.
In your code the list is treated as four inputs while your model has one input - https://keras.io/api/models/model_training_apis/
Add these lines:
import tensorflow as tf
data_list = tf.stack(data_list)
y = tf.stack(y)

Try this
model.fit(np.array(data_list), np.array(y), verbose=0, epochs=100)

Related

How to match dimensions in CNN

I'm trying to build a CNN, where the goal is from 3 features to predict the label, but is giving an error of dimension.
Could someone help me?
updated after comments from #M.Innat
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.model_selection import train_test_split
from tensorflow.keras.layers import Dense, Conv2D, Dropout, Flatten, MaxPooling2D
from tensorflow.keras.models import Sequential, load_model
from sklearn.metrics import accuracy_score, f1_score, mean_absolute_error
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.optimizers import Adam
from sklearn import metrics
import tensorflow as tf
import random
# Create data
n = 8500
l = [2, 3, 4, 5,6]
k = int(np.ceil(n/len(l)))
labels = [item for item in l for i in range(k)]
random.shuffle(labels,random.random)
labels =np.array(labels)
label_unique = np.unique(labels)
x = np.linspace(613000, 615000, num=n) + np.random.uniform(-5, 5, size=n)
y = np.linspace(7763800, 7765800, num=n) + np.random.uniform(-5, 5, size=n)
z = np.linspace(1230, 1260, num=n) + np.random.uniform(-5, 5, size=n)
X = np.column_stack((x,y,z))
Y = labels
# Split the dataset into training and testing.
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=1234)
seq_len=len(X_train)
n_features=len(X_train[0])
droprate=0.1
exit_un=len(label_unique)
seq_len=len(X_train)
n_features=len(X_train[0])
droprate=0.1
exit_un=len(label_unique)
print('n_features: {} \n seq_len: {} \n exit_un: {}'.format(n_features,seq_len,exit_un))
X_train = X_train[..., None][None, ...] # add channel axis+batch aix
Y_train = pd.get_dummies(Y_train) # transform to one-hot encoded
drop_prob = 0.5
my_model = Sequential()
my_model.add(Conv2D(input_shape=(seq_len,n_features,1),filters=32,kernel_size=(3,3),padding='same',activation="relu")) # 1 channel of grayscale.
my_model.add(MaxPooling2D(pool_size=(2,1)))
my_model.add(Conv2D(filters=64,kernel_size=(5,5), padding='same',activation="relu"))
my_model.add(MaxPooling2D(pool_size=(2,1)))
my_model.add(Flatten())
my_model.add(Dense(units = 1024, activation="relu"))
my_model.add(Dropout(rate=drop_prob))
my_model.add(Dense(units = exit_un, activation="softmax"))
n_epochs = 100
batch_size = 10
learn_rate = 0.005
# Define the optimizer and then compile.
my_optimizer=Adam(lr=learn_rate)
my_model.compile(loss = "categorical_crossentropy", optimizer = my_optimizer, metrics=['categorical_crossentropy','accuracy'])
my_summary = my_model.fit(X_train, Y_train, epochs=n_epochs, batch_size = batch_size, verbose = 1)
The error I have is:
ValueError: Data cardinality is ambiguous:
x sizes: 1
y sizes: 5950
Make sure all arrays contain the same number of samples.
You're passing the input sample without the channel axis and also the batch axis. Also, according to your loss function, you should transform your integer label to one-hot encoded.
exit_un=len(label_unique)
drop_prob = 0.5
X_train = X_train[..., None][None, ...] # add channel axis+batch aix
X_train = np.repeat(X_train, repeats=100, axis=0) # batch-ing
Y_train = np.repeat(Y_train, repeats=100, axis=0) # batch-ing
Y_train = pd.get_dummies(Y_train) # transform to one-hot encoded
print(X_train.shape, Y_train.shape)
my_model = Sequential()
...
update
Based on the discussion, it seems like you need the conv1d operation in the modeling time and need to reshape your sample as mentioned in the comment. Here is the colab, it should work now.

Different Loss functions on different segments of a DNN

Is it possible to have different loss-functions defined on different "segments" of a deep network (in the following sense):
Suppose that I have some input-output pairs (x_n,y_n) and (x_n,z_n) and I want to train a deep network of the from f_k∘...∘f_1 (each f_i is a feed-forward layer) such that
MSE(f_k∘...∘f_1(x_n) - y_n) is minimized
MSE(f_k∘f_k-1(x_n) - z_n) is also minimized.
Analogy/ Example/ Intuition/ Motivation:
Suppose I want the output of my network to approximately be like x^2 then f_k∘f_k-1(x_n)~~ x_n^2 and z_n:= x_n^2. Then f_k∘...∘f_1(x_n) a feed-forward network whose output layer is approximately the function x^2.
How can you do this in TensorFlow/Keras?
You can achieve that by defining a two output model.
It essentially minimizes the weighted average of the two losses.
A restriction is that the input shape of the first and (n-1)-th layers must be same, since both receives the same input x.
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, Input
input_shape = (1,)
model1 = Sequential([
Dense(5, activation="relu", input_shape=input_shape),
Dense(8, activation="relu"),
Dense(input_shape[0])
])
model2 = Sequential([
Dense(15, activation="relu", input_shape=input_shape),
Dense(1)
])
x = Input(input_shape)
y = model2(model1(x))
z = model2(x)
model = Model(inputs=x, outputs=[y, z])
model.compile("adam", "mean_squared_error", loss_weight=[0.5, 0.5])
import numpy as np
n = 1000
x = np.random.normal(size=n * input_shape[0]).reshape((n, input_shape[0]))
y = x**2
z = x**2
history = model.fit(x, [y, z], epochs=100)
Visualization:
import matplotlib.pyplot as plt
plt.plot(history.history["loss"])
yhat, zhat = model.predict(x)
plt.scatter(x, yhat)
plt.scatter(x, zhat)

ValueError: Input 0 is incompatible with layer conv1d_1: expected ndim=3, found ndim=2

When I try to give Elmo embedding layer output to conv1d layer input it giving the error
ValueError: Input 0 is incompatible with layer conv1d_1: expected ndim=3, found ndim=2
I want to add a convolution layer from the output of the Elmo embedding layer
import tensorflow as tf
import tensorflow_hub as hub
import keras.backend as K
from keras import Model
from keras.layers import Input, Lambda, Conv1D, Flatten, Dense
from keras.utils import to_categorical
from sklearn.preprocessing import LabelEncoder
import pandas as pd
from sklearn.model_selection import train_test_split
df = pd.read_csv("/home/raju/Desktop/spam.csv", encoding='latin-1')
X = df['v2']
Y = df['v1']
le = LabelEncoder()
le.fit(Y)
Y = le.transform(Y)
Y = to_categorical(Y)
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.25)
elmo = hub.Module('/home/raju/models/elmo')
def embeddings(x):
return elmo(tf.squeeze(tf.cast(x, dtype=tf.string)), signature='default', as_dict=True)['default']
input_layer = Input(shape=(1,), dtype=tf.string)
embed_layer = Lambda(embeddings, output_shape=(1024,))(input_layer)
conv_layer = Conv1D(4, 2, activation='relu')(embed_layer)
fcc_layer = Flatten()(conv_layer)
output_layer = Dense(2, activation='softmax')(fcc_layer)
model = Model(inputs=[input_layer], outputs=output_layer)
A Conv1D layer expects input of the shape (batch, steps, channels). The channels dimension is missing in your case, and you need to include it even if it is equal to 1. So the output shape of your elmo module should be (1024, 1) (this does not include the batch size). You can add a dimension to the output of the elmo module with tf.expand_dims(x, axis=-1).

Categorical crossentropy and label encoding

I'm trying to code multiclass output and classes are ['A','B','C','D','E','F','G'].
Could someone elaborate more next error message:
"ValueError: You are passing a target array of shape (79, 1) while using as loss categorical_crossentropy. categorical_crossentropy expects targets to be binary matrices (1s and 0s) of shape (samples, classes). If your targets are integer classes, you can convert them to the expected format via:
from keras.utils.np_utils import to_categorical
y_binary = to_categorical(y_int)
Alternatively, you can use the loss function sparse_categorical_crossentropy instead, which does expect integer targets."
My code:
# Part 1 - Data Preprocessing
# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# Importing the dataset
dataa = pd.read_csv('test_out.csv')
XX = dataa.iloc[:, 0:4].values
yy = dataa.iloc[:, 4].values
# Encoding categorical data
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_Y_1 = LabelEncoder()
yy = labelencoder_Y_1.fit_transform(yy)
# Splitting the dataset into the Training set and Test set
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(XX, yy, test_size = 0.2,
random_state = 0)
# Feature Scaling
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
# Part 2 - Now let's make the ANN!
# Importing the Keras libraries and packages
import keras
from keras.models import Sequential
from keras.layers import Dense
# Initialising the ANN
classifier = Sequential()
# Adding the input layer and the first hidden layer
classifier.add(Dense(output_dim = 6, init = 'uniform', activation = 'relu',
input_dim = 4))
# Adding the second hidden layer
classifier.add(Dense(output_dim = 6, init = 'uniform', activation = 'relu'))
# Adding the output layer
classifier.add(Dense(output_dim = 1, init = 'uniform', activation =
'softmax'))
# Compiling the ANN
classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy',
metrics = ['accuracy'])
# Fitting the ANN to the Training set
classifier.fit(X_train, y_train, batch_size = 10, nb_epoch = 50)
# Part 3 - Making the predictions and evaluating the model
# Predicting the Test set results
y_pred = classifier.predict(X_test)
y_pred = (y_pred > 0.5)
# Making the Confusion Matrix
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
The problem lies in this portion of your code,
# Encoding categorical data
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_Y_1 = LabelEncoder()
yy = labelencoder_Y_1.fit_transform(yy)
You forgot to one-hot encode the yy, please take note that LabelEncoder only transforms your categorical data to numerical one, i.e. [A, B, C, D, E, F, G] to [1, 2, 3, 4, 5, 6, 7]. You have to one-hot encode it since you want to use softmax activation, and categorical_crossentropy (I'm over-simplifying, but it's the gist).
So, it should have been like this,
# Encoding categorical data
from keras.utils import to_categorical
from sklearn.preprocessing import LabelEncoder
labelencoder_Y_1 = LabelEncoder()
yy = labelencoder_Y_1.fit_transform(yy)
yy = to_categorical(yy)
I assume your target class that you are going to predict is binary i.e there are only 2 possible values that could occur
If your target is binary then, the last layer of the model should be activated with sigmoid activation function. Also, the model should be compiled with binary_crossentropy or sparse_categorical_crossentropy.
If the target is multi-class i.e more than 2 possible values, you must convert the target to categorical with the help of to_categorical from keras. Then you should compile your model with categorical_crossentropy and the last layer in the model should be activated with softmax activation function.!!

Wrong Number of LSTM Dimensions in Keras

I am trying to classify texts using Recurrent Neural Networks and am facing issue while implementing the following Python Code (backend is on TensorFlow):
from keras.models import Sequential
from keras.layers import LSTM
from keras.layers import Dense
from keras.layers import Embedding
import numpy
import pandas as pd
seed = 7
numpy.random.seed(seed)
raw_data = pd.read_excel('Data.xlsx',sep=',')
df = raw_data.iloc[:,0:2]
df['Input']=df['Input'].astype(str)
X = df['Input'].values
X = pd.get_dummies(X).as_matrix() # Convert Dataframe to Nd-Araay
Y = df['Output'].values
Y = pd.get_dummies(Y).as_matrix() # Convert Dataframe to Nd-Araay
model = Sequential()
model.add(LSTM(450, input_shape =(X.shape[0], X.shape[1])))
model.add(Dense(Y.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(X, Y, nb_epoch=100, batch_size=100,verbose=0)
loss, accuracy = model.evaluate(X, Y)
print("\nLoss: %.2f, Accuracy: %.2f%%" % (loss, accuracy*100))
My input ie X is an Nd Array consisting of 411 rows & 407 columns while Y consists of 411 rows & 7 columns and following is the error I am getting:
expected lstm_input_43 to have 3 dimensions, but got array with shape (411, 407)