CNTK python API: How to get predictions from the trained model? - python

I have a trained model which I am loading using CNTK.load_model() function. I was looking at the MNIST Tutorial on the CNTK git repo as reference for model evaluation code. I have created a data reader (which is a MinibatchSource object) and trying to run model.eval(mb) where mb = minibatch_source.next_minibatch(...) (Similar to this answer)
But, I'm getting the following error message
Traceback (most recent call last):
File "LID_test.py", line 162, in <module>
test_and_evaluate()
File "LID_test.py", line 159, in test_and_evaluate
predictions = model.eval(mb)
File "/home/t-asbahe/anaconda3/envs/cntk-py35/lib/python3.5/site-packages/cntk/ops/functions.py", line 228, in eval
_, output_map = self.forward(arguments, self.outputs, device=device, as_numpy=as_numpy)
File "/home/t-asbahe/anaconda3/envs/cntk-py35/lib/python3.5/site-packages/cntk/utils/swig_helper.py", line 62, in wrapper
result = f(*args, **kwds)
File "/home/t-asbahe/anaconda3/envs/cntk-py35/lib/python3.5/site-packages/cntk/ops/functions.py", line 354, in forward
None, device)
File "/home/t-asbahe/anaconda3/envs/cntk-py35/lib/python3.5/site-packages/cntk/utils/__init__.py", line 393, in sanitize_var_map
if len(arguments) < len(op_arguments):
TypeError: object of type 'Variable' has no len()
I have no input_variable named 'Variable' in my model and I don't see any reason to get this error.
P.S.: My inputs are sparse inputs (one-hots)

You have a few options:
Pass a set of data as numpy array (instance in CNTK 202 tutorial) where onehot data is passed in as a numpy array.
pred = model.eval({model.arguments[0]:[onehot]})
Read the minibatch data and pass it to the eval function
eval_input_map = { input : reader_eval.streams.features }
eval_data = reader_eval.next_minibatch(eval_minibatch_size,
input_map = eval_input_map)
mydata = eval_data[input].value
predicted= model.eval(mydata)

Related

What is the ideal way, in tensorflow, of feeding the output of a model back into itself, for predicting data that changes over time?

I am working on a model that trains on simulation data, which should ideally be able to predict N timesteps forward from a given state in a simulation. I have attempted to model this by feeding the output of the model back into itself N times, where N is a hyperparameter of the model. I have done this in the call function of the tensorflow.keras.Model() class.
The relevant code:
def call(self, inputs):
x = inputs[0]
outputs = tf.TensorArray(
dtype=tf.float32, size=0, dynamic_size=True, infer_shape=False
)
window = inputs[1]
for i in tf.range(window):
x = self.model(x)
outputs = outputs.write(i, x)
outputs = tf.transpose(outputs.stack(), [1, 2, 3, 0, 4])
return outputs
This works, and the model trains, but i want to save the model using the tensorflow.keras.Model.save() function. Trying this leads to the following error:
Traceback (most recent call last):
File "/zhome/22/4/118839/Masters_Thesis/Model_files/Unet.py", line 562, in <module>
model_.save(savepath + "/saved_model/Model")
File "/zhome/22/4/118839/Masters_Thesis/Menv/lib/python3.9/site-packages/keras/utils/traceback_utils.py", line 70, in error_handler
raise e.with_traceback(filtered_tb) from None
File "/appl/python/3.9.11/lib/python3.9/contextlib.py", line 126, in __exit__
next(self.gen)
File "/zhome/22/4/118839/Masters_Thesis/Model_files/Unet.py", line 485, in call
for i in tf.range(4):
tensorflow.python.framework.errors_impl.OperatorNotAllowedInGraphError: Iterating over a symbolic `tf.Tensor` is not allowed: AutoGraph did convert this function. This might indicate you are trying to use an unsupported feature.
Is there a better way of doing what I'm trying to do? Any other threads I have found recommend using the tf.map_fn() function, but this does not work for me due to the sequential nature of the model. Any help is appreciated!

Connecting BatchDataset with Keras VGG16 preprocess_input

I am using tf.keras.preprocessing.image_dataset_from_directory to get a BatchDataset, where the dataset has 10 classes.
I am trying to integrate this BatchDataset with a Keras VGG16 (docs) network. From the docs:
Note: each Keras Application expects a specific kind of input preprocessing. For VGG16, call tf.keras.applications.vgg16.preprocess_input on your inputs before passing them to the model.
However, I am struggling to get this preprocess_input working with a BatchDataset. Can you please help me figure out how to connect these two dots?
Please see the below code:
train_ds = tf.keras.preprocessing.image_dataset_from_directory(train_data_dir, image_size=(224, 224))
train_ds = tf.keras.applications.vgg16.preprocess_input(train_ds)
This will throw TypeError: 'BatchDataset' object is not subscriptable:
Traceback (most recent call last):
...
File "/path/to/venv/lib/python3.10/site-packages/keras/applications/vgg16.py", line 232, in preprocess_input
return imagenet_utils.preprocess_input(
File "/path/to/venv/lib/python3.10/site-packages/keras/applications/imagenet_utils.py", line 117, in preprocess_input
return _preprocess_symbolic_input(
File "/path/to/venv/lib/python3.10/site-packages/keras/applications/imagenet_utils.py", line 278, in _preprocess_symbolic_input
x = x[..., ::-1]
TypeError: 'BatchDataset' object is not subscriptable
From TypeError: 'DatasetV1Adapter' object is not subscriptable (from BatchDataset not subscriptable when trying to format Python dictionary as table) the suggestion was to use:
train_ds = tf.keras.applications.vgg16.preprocess_input(
list(train_ds.as_numpy_iterator())
)
However, this also fails:
Traceback (most recent call last):
...
File "/path/to/venv/lib/python3.10/site-packages/keras/applications/vgg16.py", line 232, in preprocess_input
return imagenet_utils.preprocess_input(
File "/path/to/venv/lib/python3.10/site-packages/keras/applications/imagenet_utils.py", line 117, in preprocess_input
return _preprocess_symbolic_input(
File "/path/to/venv/lib/python3.10/site-packages/keras/applications/imagenet_utils.py", line 278, in _preprocess_symbolic_input
x = x[..., ::-1]
TypeError: list indices must be integers or slices, not tuple
This is all using Python==3.10.3 with tensorflow==2.8.0.
How can I get this working? Thank you in advance.
Okay I figured it out. I needed to pass a tf.Tensor, not a tf.data.Dataset. One can get a Tensor out by iterating over the Dataset.
This can be done in a few ways:
train_ds = tf.keras.preprocessing.image_dataset_from_directory(...)
# Option 1
batch_images = next(iter(train_ds))[0]
preprocessed_images = tf.keras.applications.vgg16.preprocess_input(batch_images)
# Option 2:
for batch_images, batch_labels in train_ds:
preprocessed_images = tf.keras.applications.vgg16.preprocess_input(batch_images)
If you convert option 2 into a generator, it can be directly passed into the downstream model.fit. Cheers!

RuntimeError: Expected object of backend CUDA but got backend CPU for argument #3 'index'

LSTM(
(embed): Embedding(139948, 12, padding_idx=0)
(lstm): LSTM(12, 12, num_layers=2, batch_first=True, bidirectional=True)
(lin): Linear(in_features=240, out_features=6, bias=True)
)
Train epoch : 1, loss : 771.319284286499, accuracy :0.590
=================================================================================================
Traceback (most recent call last):enter code here
File "C:/Users/Administrator/PycharmProjects/untitled/example.py", line 297, in <module>
scores = model(x_test, x_test_seq_length)
File "C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py", line 493, in __call__
result = self.forward(*input, **kwargs)
File "C:/Users/Administrator/PycharmProjects/untitled/example.py", line 141, in forward
x = self.embed(x) # sequence_length(max_len), batch_size, embed_size
File "C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\module.py", line 493, in __call__
result = self.forward(*input, **kwargs)
File "C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\modules\sparse.py", line 117, in forward
self.norm_type, self.scale_grad_by_freq, self.sparse)
File "C:\ProgramData\Anaconda3\lib\site-packages\torch\nn\functional.py", line 1506, in embedding
return torch.embedding(weight, input, padding_idx, scale_grad_by_freq, sparse)
RuntimeError: Expected object of backend CUDA but got backend CPU for argument #3 'index'
It works fine on the training set, but I keep getting that error in the test set. I've been thinking for 10 hours.
What is problem??
It seems that your program is expecting to run using the GPU but is instead being run on the CPU. Make sure you have your GPU settings for your program set correctly and the version of CUDA you're using is up-to-date.
You can find more information on this here (Assuming you're using tensorflow):
https://www.tensorflow.org/install/gpu
If you trained the model on your CPU, then the test data was loaded and converted to the CUDA datatype somehow. So, you can solve this issue by moving your input tensors to CPU device. And move the model as well (it won't hurt).
This can be done like so:
>>> import torch
>>> device = torch.device("cpu")
>>> # move the model
>>> model = model.to(device)
>>> # move any input tensors
>>> test_data = test_data.to(device)

Keras predict_classes method returns "list index out of range" error

I am new to CNN and machine learning in general and have been trying to follow Image Classification tutorial of TensorFlow.
Now, the Google Colab can be found here. I've followed the this official tutorial of TensorFlow. And I've changed it slightly so it saves the model as h5 instead of tf format so I can use the Keras' model.predict_classes.
Now, I have the model trained and the model reloaded from the saved model alright. But I'm repeatedly getting list index out of range error whenever I am trying to predict the image which I am doing so:
def predict():
image = tf.io.read_file('target.jpeg')
image = tf.image.decode_jpeg(image, channels=3)
image = tf.image.resize(image, [224, 224])
print(model.predict_classes(image)[0])
target.jpeg is one of the images I took from the flowers_photos dataset on which the model is trained.
The Traceback is:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 7, in predict
File "/home/amitjoki/.local/lib/python3.6/site-packages/tensorflow/python/keras/engine/sequential.py", line 319, in predict_classes
proba = self.predict(x, batch_size=batch_size, verbose=verbose)
File "/home/amitjoki/.local/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 821, in predict
use_multiprocessing=use_multiprocessing)
File "/home/amitjoki/.local/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_arrays.py", line 712, in predict
callbacks=callbacks)
File "/home/amitjoki/.local/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_arrays.py", line 187, in model_iteration
f = _make_execution_function(model, mode)
File "/home/amitjoki/.local/lib/python3.6/site-packages/tensorflow/python/keras/engine/training_arrays.py", line 555, in _make_execution_function
return model._make_execution_function(mode)
File "/home/amitjoki/.local/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 2037, in _make_execution_function
self._make_predict_function()
File "/home/amitjoki/.local/lib/python3.6/site-packages/tensorflow/python/keras/engine/training.py", line 2027, in _make_predict_function
**kwargs)
File "/home/amitjoki/.local/lib/python3.6/site-packages/tensorflow/python/keras/backend.py", line 3544, in function
return EagerExecutionFunction(inputs, outputs, updates=updates, name=name)
File "/home/amitjoki/.local/lib/python3.6/site-packages/tensorflow/python/keras/backend.py", line 3468, in __init__
self.outputs[0] = array_ops.identity(self.outputs[0])
IndexError: list index out of range
I searched extensively but couldn't get any solution. It would be helpful if anyone can point me in the direction of getting this up and running.
All the predict functions in Keras expect batch of inputs. Therefore, since you are doing prediction on one single image, you need to add an axis at the beginning of image tensor to represent the batch axis:
image = tf.expand_dims(image, axis=0) # the shape would be (1, 224, 224, 3)
print(model.predict_classes(image)[0])

Tensorflow: Getting scalar tensor value as int for pass to set_shape()

I'm attempting to load 3D images and their labels from a numpy array to TensorFlow records, then read them from a queue while training my network. The code for conversion is based on the conversion for TensorFlow's Inception model.
Each image has a different height, width, and depth value, so when reshaping the array I need to know these values. However, I'm getting an error when I try to use set_shape, as somewhere down the line int() is being used, and it doesn't accept Tensor values.
reader = tf.TFRecordReader()
_, value = reader.read(filename_queue)
# Features in Example proto
feature_map = {
'height': tf.VarLenFeature(dtype=tf.int64),
'width': tf.VarLenFeature(dtype=tf.int64),
'depth': tf.VarLenFeature(dtype=tf.int64),
'label': tf.VarLenFeature(dtype=tf.int64),
'image_raw': tf.VarLenFeature(dtype=tf.string)
}
features = tf.parse_single_example(value, feature_map)
result.label = tf.cast(features['label'].values[0], dtype=tf.int32)
result.height = tf.cast(features['height'].values[0], dtype=tf.int32)
result.width = tf.cast(features['width'].values[0], dtype=tf.int32)
result.depth = tf.cast(features['depth'].values[0], dtype=tf.int32)
image = tf.decode_raw(features['image_raw'].values[0], tf.int16)
image = tf.reshape(image, [result.depth, result.height, result.width])
image = tf.cast(tf.transpose(image, [1, 2, 0]), tf.float32)
result.image = tf.expand_dims(image, 3)
result.image.set_shape([result.height, result.width, result.depth, 1])
result.label = tf.expand_dims(result.label, 0)
result.label.set_shape([1])
Error trace:
Traceback (most recent call last):
File "dsb17_multi_gpu_train.py", line 227, in <module>
tf.app.run()
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/platform/app.py", line 44, in run
_sys.exit(main(_sys.argv[:1] + flags_passthrough))
File "dsb17_multi_gpu_train.py", line 223, in main
train()
File "dsb17_multi_gpu_train.py", line 129, in train
loss = tower_loss(scope)
File "dsb17_multi_gpu_train.py", line 34, in tower_loss
images, labels = dsb17.inputs(False)
File "/home/ubuntu/dsb17/model/dsb17.py", line 104, in inputs
batch_size=FLAGS.batch_size)
File "/home/ubuntu/dsb17/model/dsb17_input.py", line 161, in inputs
read_input = read_data(filename_queue)
File "/home/ubuntu/dsb17/model/dsb17_input.py", line 62, in read_data
result.image.set_shape([result.height, result.width, result.depth, 1])
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/ops.py", line 425, in set_shape
self._shape = self._shape.merge_with(shape)
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/tensor_shape.py", line 573, in merge_with
other = as_shape(other)
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/tensor_shape.py", line 821, in as_shape
return TensorShape(shape)
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/tensor_shape.py", line 457, in __init__
self._dims = [as_dimension(d) for d in dims_iter]
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/tensor_shape.py", line 457, in <listcomp>
self._dims = [as_dimension(d) for d in dims_iter]
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/tensor_shape.py", line 378, in as_dimension
return Dimension(value)
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/tensor_shape.py", line 33, in __init__
self._value = int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'Tensor'
I originally thought this was because the Tensor did not have a value until it was evaluated in a session, but loss is being evaluated in a sess.run(), which is what requires the call to tower_loss(). My training code is identical in structure to cifar10_multi_gpu_train.py, and the overall file structure is also very similar.
The question then is: Is it actually being evaluated in a session, or is the graph not built yet? Do I need to somehow extract a value from the zero-dimensional Tensor? More generally, what am I misunderstanding about Tensors and sessions that is making my code not work as I expect it to?
According to TensorFlow's tf.cast docs, tf.cast returns a Tensor.
Your error says that when using set_shape(), you cannot have a Tensor as an argument, but rather an int.
You may try to force Tensorflow to evaluate the cast. This simple example works for me:
a = tf.constant(2.0)
b = tf.constant([1.0,2.0])
b.set_shape(a.eval())
Without the call to eval(), I get the same error as you.
In general you cannot do this using tf.Tensor.set_shape(), because that method expects a static shape. The tensors result.height, result.width, result.depth represent values read from a file, and at runtime they could evaluate to many different integers (depending on what is in your file), so there is no single int that you can pass for them. In that case, the best you can currently do is represent those dimensions as being statically unknown, using None for the unknown dimensions:
result.image.set_shape([None, None, None, 1])
Note that this statement shouldn't change anything, because TensorFlow should already be able to infer that the shape is 4-D with size 1 in the last dimension.
For more details about static and dynamic shapes, see this answer.
Actually you can pass the image shape to the reshape function but you need one more step. Just change the line:
image = tf.reshape(image, [result.depth, result.height, result.width])
to:
image_shape = tf.stack([result.depth, result.height, result.width])
image = tf.reshape(image, image_shape)

Categories

Resources