Como posso obter previsões para apenas uma instância no Keras?


13

Quando solicito ao Keras para aplicar a previsão com um modelo ajustado a um novo conjunto de dados sem rótulo como este:

model1.predict_classes(X_test)

Funciona bem. Mas quando tento fazer previsão para apenas uma linha, ela falha:

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)

Eu quero saber porque?

Respostas:


12

Você pode fazer:

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

O que também retorna a numpy.ndarray. Assim, para obter apenas o valor que deseja:q = model.predict(np.array([single_x_test]))[0]
Loisaida Sam Sandberg

7

predict_classesestá esperando uma matriz 2D de forma (num_instances, features), como X_testé. Mas indexar uma única instância como em X_test[10]retorna uma matriz 1D de forma (features,).

Para adicionar de volta o eixo extra, você pode usar , ou , ou não se livrar dele em primeiro lugar (por exemplo, usando ).np.expand_dims(X_test[10], axis=0)X_test[10][np.newaxis,:]X_test[10:11]


Parece não funcionar: nenhuma mensagem de erro, mas também não há saída. Esquisito.
Hendrik

5

Atualmente (Keras v2.0.8), é necessário um pouco mais de esforço para obter previsões em linhas únicas após o treinamento em lote.

Basicamente, o batch_size é corrigido no tempo de treinamento e deve ser o mesmo no tempo de previsão.

A solução agora é pegar os pesos do modelo treinado e usá-los como pesos em um novo modelo que você acabou de criar, com um lote de tamanho 1.

O código rápido para isso é

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)

Aqui está uma postagem de blog que tem mais detalhes: https://machinelearningmastery.com/use-different-batch-sizes-training-predicting-python-keras/

Eu usei essa abordagem no passado para ter vários modelos no momento da previsão - um que faz previsões em lotes grandes, um que faz previsões em lotes pequenos e outro que faz previsões em itens únicos. Como as previsões de lote são muito mais eficientes, isso nos dá a flexibilidade de receber qualquer número de linhas de previsão (não apenas um número que é igualmente divisível por batch_size), enquanto ainda obtemos previsões rapidamente.



2

Você deve passar uma lista com apenas 1 exemplo, não posso testar agora, mas isso deve funcionar:

model1.predict_classes([X_test[10]])

Infelizmente não funciona.
Hendrik

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

onde X é um array numpy. Foi tudo o que fiz e funcionou.


1

Corrigi isso usando a seguinte abordagem:

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

Observe que a quantidade de recursos (784) na função remodelar é baseada no seu exemplo acima, se você tiver menos recursos, precisará ajustá-lo.

Espero que funcione para você também.


1

se você tentar imprimir a instância, verá o seguinte:

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.])

então acho que podemos adicionar de volta uma dimensão usando o np.array:

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

0

Isso significa que seus dados de treinamento tinham a forma de (784, 1). Você pode apenas remodelá-lo da seguinte forma. Funcionou para mim.

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

Você também pode fazer transpose()se a forma for (1.784),

model1.predict_classes(X_test[10].transpose())
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.