Traté de obtener una estimación del tiempo de predicción de mi modelo de keras y me di cuenta de algo extraño. Además de ser bastante rápido normalmente, de vez en cuando el modelo necesita bastante tiempo para llegar a una predicción. Y no solo eso, esos tiempos también aumentan cuanto más tiempo se ejecuta el modelo. Agregué un ejemplo de trabajo mínimo para reproducir el error.
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))
El tiempo no depende de la muestra (se selecciona al azar). Si se repite la prueba, los índices en el bucle for donde la predicción lleva más tiempo serán (casi) los mismos nuevamente.
Estoy usando:
tensorflow 2.0.0
python 3.7.4
Para mi aplicación, necesito garantizar la ejecución en un momento determinado. Sin embargo, esto es imposible teniendo en cuenta ese comportamiento. ¿Qué va mal? ¿Es un error en Keras o un error en el backend de Tensorflow?
EDITAR:
predict_on_batch
muestra el mismo comportamiento, sin embargo, más escaso:
y_pred = model(sample, training=False).numpy()
muestra algunos valores atípicos pesados también, sin embargo, no están aumentando.
EDIT 2: bajé a la última versión de tensorflow 1 (1.15). No solo el problema ya no existe, sino que el tiempo de predicción "normal" mejoró significativamente. No veo los dos picos como problemáticos, ya que no aparecieron cuando repetí la prueba (al menos no con los mismos índices y aumentando linealmente) y son porcentuales no tan grandes como en la primera gráfica.
Por lo tanto, podemos concluir que esto parece ser un problema inherente al tensorflow 2.0, que muestra un comportamiento similar en otras situaciones como menciona @OverLordGoldDragon.
fuente
predict_on_batch
?y_pred = model(sample).numpy()
y cony_pred = model(sample, training=False).numpy()
?predict_classes
sigue siendo el más rápido ... parece. ¿Qué tal solopredict
?Respuestas:
TF2 generalmente exhibe una administración de memoria pobre y similar a un error en varias instancias que he encontrado: breve descripción aquí y aquí . Con la predicción en particular, el método de alimentación más eficaz es
model(x)
directamente, ver aquí , y sus discusiones vinculadas.En pocas palabras:
model(x)
actúa a través de su su__call__
método (que se hereda debase_layer.Layer
), mientras quepredict()
,predict_classes()
, etc. implicar una función de bucle dedicado a través de_select_training_loop()
; cada uno utiliza diferentes métodos de procesamiento previo y posterior de datos adecuados para diferentes casos de uso, ymodel(x)
en 2.1 fue diseñado específicamente para obtener el rendimiento más rápido de modelo pequeño / lote pequeño (y tal vez cualquier tamaño) (y aún más rápido en 2.0).Citando a un desarrollador de TensorFlow de las discusiones vinculadas:
Nota : esto debería ser un problema menor en 2.1, y especialmente 2.2, pero pruebe cada método de todos modos. También me doy cuenta de que esto no responde directamente a su pregunta sobre los picos de tiempo; Sospecho que está relacionado con los mecanismos de almacenamiento en caché Eager, pero la forma más segura de determinarlo es a través de
TF Profiler
, que se divide en 2.1.Actualización : respecto al aumento de picos, posible aceleración de GPU; has hecho ~ 1000 iters, prueba 10,000 en su lugar; eventualmente, el aumento debería detenerse. Como notó en sus comentarios, esto no ocurre con
model(x)
; tiene sentido ya que se trata de un paso menos de GPU ("conversión a conjunto de datos").Actualización 2 : podría molestar a los desarrolladores aquí si enfrenta este problema; es sobre todo yo cantando allí
fuente
Si bien no puedo explicar las inconsistencias en el tiempo de ejecución, puedo recomendar que intente convertir su modelo a TensorFlow Lite para acelerar las predicciones en registros de datos únicos o lotes pequeños.
Ejecuté un punto de referencia en este modelo:
Los tiempos de predicción para registros individuales fueron:
model.predict(input)
: 18 msmodel(input)
: 1.3msEl tiempo para convertir el modelo fue de 2 segundos.
La siguiente clase muestra cómo convertir y usar el modelo y proporciona un
predict
método como el modelo Keras. Tenga en cuenta que debería modificarse para su uso con modelos que no solo tienen una sola entrada 1-D y una sola salida 1-D.El código de referencia completo y un diagrama se pueden encontrar aquí: https://medium.com/@micwurm/using-tensorflow-lite-to-speed-up-predictions-a3954886eb98
fuente