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 theinputs
and thekernel
along the last axis of theinputs
and axis 1 of thekernel
(usingtf.tensordot
).
For example, if input has dimensions(batch_size, d0, d1)
, then we
create akernel
with shape(d1, units)
, and thekernel
operates
along axis 2 of theinput
, on every sub-tensor of shape(1, 1, d1)
(there arebatch_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
Find the Item With Maximum Occurrences in a List
What Is the Simplest Way to Ssh Using Python
Printing a Multiplication Table With Nested Loops
Using Look Up Tables in Python
Numpy Array Typeerror: Only Integer Scalar Arrays Can Be Converted to a Scalar Index
Python - Having Trouble Opening a File With Spaces
Using SQL Server Stored Procedures from Python (Pyodbc)
How to Get the Column Name in Pandas Based on Row Values
How to Sort the Letters in a String Alphabetically in Python
Regular Expression to Check Whitespace in the Beginning and End of a String
How to Get Text from Span Tag in Beautifulsoup
How to Remove \N from a List Element
How to Get the Sum of a List of Numbers With Recursion
Datetime.Datetime Has No Attribute Datetime
Simple Digit Recognition Ocr in Opencv-Python
Remove Timestamp from Date String in Python
Split/Explode a Column of Dictionaries into Separate Columns With Pandas
How to Convert Data from Txt Files to Excel Files Using Python