How can I get prediction for only one instance in Keras?

16

6

When I request Keras to apply prediction with a fitted model to a new dataset without label like this:

model1.predict_classes(X_test)

it works fine. But when I try to make prediction for only one row, it fails:

model1.predict_classes(X_test[10])

Exception: Error when checking : expected dense_input_6 to have shape (None, 784) but got array with shape (784, 1)

I wonder, why?

Hendrik

Posted 2016-08-16T14:38:24.193

Reputation: 6 637

Answers

13

You can do:

q = model.predict( np.array( [single_x_test,] )  )

Alexandre Meyer

Posted 2016-08-16T14:38:24.193

Reputation: 131

Which also returns a numpy.ndarray. So to get just the value you want: q = model.predict(np.array([single_x_test]))[0] – Loisaida Sam Sandberg – 2019-01-08T18:31:38.630

7

predict_classes is expecting a 2D array of shape (num_instances, features), like X_test is. But indexing a single instance as in X_test[10] returns a 1D array of shape (features,).

To add back the extra axis, you can use np.expand_dims(X_test[10], axis=0), or X_test[10][np.newaxis,:], or don't get rid of it in the first place (e.g., by using X_test[10:11]).

Ken Arnold

Posted 2016-08-16T14:38:24.193

Reputation: 206

It doesn't seem to work: no error message but no output either. Weird. – Hendrik – 2016-08-17T07:40:22.173

5

Currently (Keras v2.0.8) it takes a bit more effort to get predictions on single rows after training in batch.

Basically, the batch_size is fixed at training time, and has to be the same at prediction time.

The workaround right now is to take the weights from the trained model, and use those as the weights in a new model you've just created, which has a batch_size of 1.

The quick code for that is

model = create_model(batch_size=64)
mode.fit(X, y)
weights = model.get_weights()
single_item_model = create_model(batch_size=1)
single_item_model.set_weights(weights)
single_item_model.compile(compile_params)

Here's a blog post that goes into more depth.

I've used this approach in the past to have multiple models at prediction time- one that makes predictions on big batches, one that makes predictions on small batches, and one that makes predictions on single items. Since batch predictions are much more efficient, this gives us the flexibility to take in any number of prediction rows (not just a number that is evenly divisible by batch_size), while still getting predictions pretty rapidly.

ClimbsRocks

Posted 2016-08-16T14:38:24.193

Reputation: 151

3

This would be how to predict for one element, this time number 17.

model.predict_classes(X_test[17:18])

qutorial

Posted 2016-08-16T14:38:24.193

Reputation: 31

what's wrong with the answer? – Supamee – 2018-09-06T17:42:51.030

2

You should pass a list with just 1 example, I can't test right now but this should work:

model1.predict_classes([X_test[10]])

Jan van der Vegt

Posted 2016-08-16T14:38:24.193

Reputation: 8 538

It doesn't work unfortunately. – Hendrik – 2016-08-17T07:39:41.937

1

self.result = self.model.predict(X)

where X is numpy array. That is all I did and it worked.

Meghna

Posted 2016-08-16T14:38:24.193

Reputation: 11

1

I have fixed this by using the following approach:

single_test = X_test[10]
single_test = single_test.reshape(1,784)

Please note that amount of features (784) in the reshape function is based on your example above, if you have fewer features then you need to adjust it.

Hope it will work for you too.

Rimi

Posted 2016-08-16T14:38:24.193

Reputation: 11

1

if you try to print out the instance you will see this:

x_test:\n
array([[0., 1., 1., ..., 0., 0., 0.],
        [0., 1., 1., ..., 0., 0., 0.],
        [0., 1., 1., ..., 0., 0., 0.],
        ...,
        [0., 1., 0., ..., 0., 0., 0.],
        [0., 1., 1., ..., 0., 0., 0.],
        [0., 1., 1., ..., 0., 0., 0.]])

x_test[0]:
array([0., 1., 1., ..., 0., 0., 0.])

so I think we can just add back a dimension using np.array:

mode.predict(np.array(x_test[0],ndmin=2))

Krince Liu

Posted 2016-08-16T14:38:24.193

Reputation: 11

0

It means that your training data had the shape of (784, 1). You can just reshape it as the following. It worked for me.

model1.predict_classes(X_test[10].reshape(784,1))

You can also do transpose() if shape is (1,784),

model1.predict_classes(X_test[10].transpose())

Gravity Mass

Posted 2016-08-16T14:38:24.193

Reputation: 101