Tensorflow - Valueerror: Failed to Convert a Numpy Array to a Tensor (Unsupported Object Type Float)

Tensorflow - ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type float)

TL;DR Several possible errors, most fixed with x = np.asarray(x).astype('float32').

Others may be faulty data preprocessing; ensure everything is properly formatted (categoricals, nans, strings, etc). Below shows what the model expects:

[print(i.shape, i.dtype) for i in model.inputs]
[print(o.shape, o.dtype) for o in model.outputs]
[print(l.name, l.input_shape, l.dtype) for l in model.layers]

The problem's rooted in using lists as inputs, as opposed to Numpy arrays; Keras/TF doesn't support former. A simple conversion is: x_array = np.asarray(x_list).

The next step's to ensure data is fed in expected format; for LSTM, that'd be a 3D tensor with dimensions (batch_size, timesteps, features) - or equivalently, (num_samples, timesteps, channels). Lastly, as a debug pro-tip, print ALL the shapes for your data. Code accomplishing all of the above, below:

Sequences = np.asarray(Sequences)
Targets = np.asarray(Targets)
show_shapes()

Sequences = np.expand_dims(Sequences, -1)
Targets = np.expand_dims(Targets, -1)
show_shapes()
# OUTPUTS
Expected: (num_samples, timesteps, channels)
Sequences: (200, 1000)
Targets: (200,)

Expected: (num_samples, timesteps, channels)
Sequences: (200, 1000, 1)
Targets: (200, 1)

As a bonus tip, I notice you're running via main(), so your IDE probably lacks a Jupyter-like cell-based execution; I strongly recommend the Spyder IDE. It's as simple as adding # In[], and pressing Ctrl + Enter below:



Function used:

def show_shapes(): # can make yours to take inputs; this'll use local variable values
print("Expected: (num_samples, timesteps, channels)")
print("Sequences: {}".format(Sequences.shape))
print("Targets: {}".format(Targets.shape))

Failed to convert a NumPy array to a Tensor (Unsupported object type numpy.ndarray) - Already have converted the data to numpy array

There are three problems


problem1

This is your main problem, which directly caused the error.

something's wrong with how you initialize/convert your x_train (and I think it is a bug, or you used some unusual way to construct your data), now your x_train is in fact an array of array, instead of a multi-dimensional array. So TensorFlow "thought" you have a 1D array according to its shape, which is not what you want.
the solution is to reconstruct the array before sending to fit():

x_train = np.array([np.array(val) for val in x_train])

problem2

Dense layer expects your input to have shape (batch_size, ..., input_dim), which means your last dimension of x_train must equal to input_dim, but you have 300, which is different from 400.

According to your description, your input dimension, which is the word vector dimension is 300, so you should change input_dim to 300:

model.add(Dense(20, input_dim=300, kernel_initializer='he_uniform', activation='relu'))

or equivalently, directly provide input_shape instead

model.add(Dense(20, input_shape=(400, 300), kernel_initializer='he_uniform', activation='relu'))

problem3

because dense, aka linear layer, is meant for "linear" input, so it expects each of its data to be a vector of one dimensional, so input is usually like (batch_size, vector_length). When dense receive an input of dimension > 2 (you got 3 dimensions), it will perform Dense operation on the last dimension. quote from TensorFlow official documentation:

Note: If the input to the layer has a rank greater than 2, then
Dense computes the dot product between the inputs and the
kernel along the last axis of the inputs and axis 1 of the
kernel (using tf.tensordot).
For example, if input has dimensions (batch_size, d0, d1), then we
create a kernel with shape (d1, units), and the kernel operates
along axis 2 of the input, on every sub-tensor of shape (1, 1, d1)
(there are batch_size * d0 such sub-tensors). The output in this
case will have shape (batch_size, d0, units).

This means your y should have shape (462, 400, 9) instead. which is most likely not what you are looking for (if this is indeed what you are looking for, code in problem1&2 should have solved your problem).

if you are looking for performing dense on the whole 400x300 matrix, you need to first flatten to a one-dimensional vector, like this:

x_train = np.array([np.array(val) for val in x_train])  # reconstruct
model= Sequential()
model.add(Flatten(input_shape=(400, 300)))
model.add(Dense(20, kernel_initializer='he_uniform', activation='relu'))
model.add(Dense(9, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam')

model.fit(x_train, y_train, verbose=0, epochs=100)

now the output will be (462, 9)

ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type list) in Keras/Tensorflow Python

You need to vectorize the sequences. To answer quickly I reduced the dimension to 10.000, you can set the value whatever you like.

(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=10000)

We will start with vector_seq function.

def vector_seq(sequences, dimension=10000):
results = zeros((len(sequences), dimension))
for i, sequence in enumerate(sequences):
results[i, sequence] = 1.
return results

vector_seq function make x_train, x_test as a tuple dimension. The reason you got the error is because of the dimension. You are feeding the dimension (25.000,) but keras needs (25.000, 10.000). Of course, you can change the 10.000 to whatever you like.

We will continue with the formatting our data

x_train = vector_seq(x_train)
x_test = vector_seq(x_test)
y_train = asarray(y_train).astype('float32')
y_test = asarray(y_test).astype('float32')

and now we are ready to compile our model.

Below is the full code:

from keras.datasets import imdb
from keras import Sequential, layers
from numpy import asarray, zeros


def vector_seq(sequences, dimension=10000):
results = zeros((len(sequences), dimension))
for i, sequence in enumerate(sequences):
results[i, sequence] = 1.
return results


(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=10000)

dictionary = imdb.get_word_index()
dictionary = {k: (v+3) for k, v in dictionary.items()}
dictionary['<PAD>'] = 0
dictionary['<START>'] = 1
dictionary['<UNKNOWN>'] = 2
dictionary['<UNUSED>'] = 3

dictionary = dict([(v, k) for (k, v) in dictionary.items()])

model = Sequential([
layers.Embedding(10000, 16),
layers.GlobalAveragePooling1D(),
layers.Dense(16, activation='relu'),
layers.Dense(1, activation='sigmoid')
])

model.compile(
optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy']
)

print(model.summary())

x_train = vector_seq(x_train)
x_test = vector_seq(x_test)
y_train = asarray(y_train).astype('float32')
y_test = asarray(y_test).astype('float32')

history = model.fit(x_train, y_train, epochs=50, batch_size=32, verbose=1)

prediction = model.predict(x_test)
print(prediction)

Failed to convert a NumPy array to a Tensor (Unsupported object type numpy.ndarray) which is different from the answers I've seen

The shape of the numpy array won't show up, because the shape of each image isn't fixed.

Add tf.image.resize, let the shape of image fixed.

train_img_arr = tf.keras.preprocessing.image.img_to_array(train_img)
train_img_arr = tf.image.resize(train_img_arr, (size1, size2))

If you want your input data have different shape, you can check this link.

Failed to convert a NumPy array to a Tensor (Unsupported object type numpy.ndarray) on ImageDataGenerator in Keras

I have succeeded in reproducing the error.

The error appears when the line np.array([cv2.imread(file_name).astype(np.int) for file_name in batch_x]) in My_Custom_Generator.__getitem__ does not create a multi-dimensional array, but instead it creates an array with dtype=np.object that is just a list of arrays.

That happens when the shapes of the arrays in the list (i.e. the shapes of the images) are not identical, as you can see from the example below.

np.array([np.zeros((4, 4, 3)), np.zeros((5, 5, 3))])
>>> array([array([[[0., 0., 0.], ..., [0., 0., 0.]]]),
array([[[0., 0., 0.], ..., [0., 0., 0.]]])], dtype=object)

Running the code in the example the following deprecation warning is visualized: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
np.array([np.zeros((4, 4, 3)), np.zeros((5, 5, 3))])
.

In general is not a good practice to stack arrays in a list through the function np.array, it is recommended to use np.stack that allows to catch this type of errors in advance.

Replacing np.array([cv2.imread(file_name).astype(np.int) for file_name in batch_x]) with np.stack([cv2.imread(file_name).astype(np.int) for file_name in batch_x], axis=0), you should see a much more meaningful error stack trace.

To conclude, to solve the problem you should check the shapes of your images to find the image that breaks your code.



Related Topics



Leave a reply



Submit