Tentei obter uma estimativa do tempo de previsão do meu modelo keras e percebi algo estranho. Além de ser bastante rápido normalmente, de vez em quando o modelo precisa de muito tempo para apresentar uma previsão. E não apenas isso, esses tempos também aumentam quanto mais tempo o modelo é executado. Adicionei um exemplo de trabalho mínimo para reproduzir o erro.
import time
import numpy as np
from sklearn.datasets import make_classification
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
# Make a dummy classification problem
X, y = make_classification()
# Make a dummy model
model = Sequential()
model.add(Dense(10, activation='relu',name='input',input_shape=(X.shape[1],)))
model.add(Dense(2, activation='softmax',name='predictions'))
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(X, y, verbose=0, batch_size=20, epochs=100)
for i in range(1000):
# Pick a random sample
sample = np.expand_dims(X[np.random.randint(99), :], axis=0)
# Record the prediction time 10x and then take the average
start = time.time()
for j in range(10):
y_pred = model.predict_classes(sample)
end = time.time()
print('%d, %0.7f' % (i, (end-start)/10))
O tempo não depende da amostra (está sendo escolhida aleatoriamente). Se o teste for repetido, os índices no loop for, onde a previsão leva mais tempo, serão (quase) os mesmos novamente.
Estou a usar:
tensorflow 2.0.0
python 3.7.4
Para minha aplicação, preciso garantir a execução em um determinado período de tempo. No entanto, isso é impossível considerando esse comportamento. O que está acontecendo de errado? É um bug no Keras ou no backend tensorflow?
EDIT:
predict_on_batch
mostra o mesmo comportamento, no entanto, mais esparsos:
y_pred = model(sample, training=False).numpy()
mostra alguns outliers pesados também, no entanto, eles não estão aumentando.
EDIT 2: Fiz o downgrade para a versão mais recente do tensorflow 1 (1.15). Além de o problema não existir mais, o tempo de previsão "normal" melhorou significativamente! Não vejo os dois picos como problemáticos, pois não apareceram quando repeti o teste (pelo menos não nos mesmos índices e aumentando linearmente) e são percentuais não tão grandes quanto no primeiro gráfico.
Assim, podemos concluir que esse parece ser um problema inerente ao tensorflow 2.0, que mostra um comportamento semelhante em outras situações, como menciona o @OverLordGoldDragon.
fonte
predict_on_batch
?y_pred = model(sample).numpy()
e comy_pred = model(sample, training=False).numpy()
?predict_classes
ainda é o mais rápido .... parece. Que tal apenaspredict
?Respostas:
O TF2 geralmente exibe um gerenciamento de memória ruim e semelhante a erros em vários casos que encontrei - breve descrição aqui e aqui . Com a previsão em particular, o método de alimentação com melhor desempenho é via
model(x)
diretamente - veja aqui e suas discussões vinculadas.Em poucas palavras:
model(x)
actua através do seu seu__call__
método (que herdabase_layer.Layer
), ao passo quepredict()
,predict_classes()
etc. envolver uma função de circuito dedicado via_select_training_loop()
; cada um utiliza diferentes métodos de pré e pós-processamento de dados, adequados para diferentes casos de uso, emodel(x)
no 2.1 foi projetado especificamente para obter o desempenho mais rápido de modelos pequenos / lotes pequenos (e talvez de qualquer tamanho) (e ainda mais rápido no 2.0).Citando um desenvolvedor TensorFlow de discussões vinculadas:
Nota : isso deve ser um problema menor no 2.1, e principalmente no 2.2 - mas teste cada método de qualquer maneira. Também sei que isso não responde diretamente à sua pergunta sobre os picos de tempo; Suspeito que esteja relacionado aos mecanismos de cache do Eager, mas a maneira mais segura de determinar é via
TF Profiler
, que é quebrada no 2.1.Atualização : quanto ao aumento de picos, possível otimização da GPU; você fez ~ 1000 iters, tente 10.000 - eventualmente, o aumento deve parar. Como você observou em seus comentários, isso não ocorre com
model(x)
; faz sentido, pois uma etapa a menos da GPU está envolvida ("conversão em conjunto de dados").Update2 : você pode corrigir os desenvolvedores aqui sobre isso se enfrentar esse problema; é principalmente eu cantando lá
fonte
Embora não possa explicar as inconsistências no tempo de execução, recomendo que você tente converter seu modelo em TensorFlow Lite para acelerar as previsões em registros de dados únicos ou em pequenos lotes.
Eu executei uma referência neste modelo:
Os tempos de previsão para registros únicos foram:
model.predict(input)
: 18msmodel(input)
: 1.3msO tempo para converter o modelo foi de 2 segundos.
A classe abaixo mostra como converter e usar o modelo e fornece um
predict
método como o modelo Keras. Observe que precisaria ser modificado para uso com modelos que não possuem apenas uma única entrada 1-D e uma única saída 1-D.O código de referência completo e uma plotagem podem ser encontrados aqui: https://medium.com/@micwurm/using-tensorflow-lite-to-speed-up-predictions-a3954886eb98
fonte