为了账号安全,请及时绑定邮箱和手机立即绑定

Keras 不一致的预测时间

Keras 不一致的预测时间

蝴蝶刀刀 2022-08-02 18:36:54
我试图估计我的keras模型的预测时间,并意识到一些奇怪的东西。除了通常相当快之外,每隔一段时间,模型需要相当长的时间才能得出预测。不仅如此,这些时间也随着模型运行时间的延长而增加。我添加了一个最小的工作示例来重现错误。import timeimport numpy as npfrom sklearn.datasets import make_classificationfrom tensorflow.keras.models import Sequentialfrom tensorflow.keras.layers import Dense, Flatten# Make a dummy classification problemX, y = make_classification()# Make a dummy modelmodel = 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))时间不取决于样本(它是随机挑选的)。如果重复测试,则预测需要较长时间的 for 循环中的索引将(几乎)再次相同。我正在使用:tensorflow 2.0.0 python 3.7.4对于我的应用程序,我需要保证在一定时间内执行。然而,考虑到这种行为,这是不可能的。哪里出错了?是 Keras 中的 bug 还是 tensorflow 后端中的 bug?
查看完整描述

2 回答

?
12345678_0001

TA贡献1802条经验 获得超5个赞

在我遇到的几个实例中,TF2通常表现出糟糕且类似错误的内存管理 - 此处此处的简要说明。特别是对于预测,最有效的喂养方法是直接通过 - 请参阅此处及其链接的讨论。model(x)

简而言之:通过其方法(它从base_layer继承)起作用。Layer),而 、 等通过 _select_training_loop();每个都利用不同的数据预处理和后处理方法,适合不同的用例,并且在2.1中专门设计用于产生最快的小模型/小批量(可能是任何尺寸)性能(并且在2.0中仍然最快)。model(x)__call__predict()predict_classes()model(x)

引用链接讨论中一位TensorFlow开发者的话:

您可以使用模型调用来预测输出,而不是模型预测,也就是说,调用将使这更快,因为没有“转换为数据集”部分,并且它还直接调用缓存。model(x)tf.function

注意:这在2.1中应该不是一个问题,尤其是2.2 - 但无论如何都要测试每种方法。我也意识到这并不能直接回答你关于时间峰值的问题;我怀疑它与 Eager 缓存机制有关,但最可靠的确定方法是通过 TF Profiler,这在 2.1 中被破坏了


更新:关于增加峰值,可能的GPU限制;你已经做了大约1000次迭代,尝试10,000次 - 最终,增加应该停止。正如您在评论中指出的那样,这在 ;这是有道理的,因为涉及的GPU步骤更少(“转换为数据集”)。model(x)

Update2:如果您遇到此问题,您可以在此处对开发人员进行错误处理;主要是我在那里唱歌


查看完整回答
反对 回复 2022-08-02
?
潇湘沐

TA贡献1816条经验 获得超6个赞

虽然我无法解释执行时间的不一致,但我可以建议您尝试将模型转换为TensorFlow Lite,以加快对单个数据记录或小批量的预测。

我在这个模型上运行了一个基准测试:

model = tf.keras.models.Sequential([
    tf.keras.layers.Dense(384, activation='elu', input_shape=(256,)),
    tf.keras.layers.Dense(384, activation='elu'),
    tf.keras.layers.Dense(256, activation='elu'),
    tf.keras.layers.Dense(128, activation='elu'),
    tf.keras.layers.Dense(32, activation='tanh')
])

单个记录的预测时间为:

  1. model.predict(input): 18毫秒

  2. model(input): 1.3毫秒

  3. 转换为TensorFlow Lite的模型:43us

转换模型的时间为 2 秒。

下面的类演示如何转换和使用模型,并提供类似于 Keras 模型的方法。请注意,它需要修改以用于不仅具有单个1-D输入和单个1-D输出的模型。predict

class LiteModel:


    @classmethod

    def from_file(cls, model_path):

        return LiteModel(tf.lite.Interpreter(model_path=model_path))


    @classmethod

    def from_keras_model(cls, kmodel):

        converter = tf.lite.TFLiteConverter.from_keras_model(kmodel)

        tflite_model = converter.convert()

        return LiteModel(tf.lite.Interpreter(model_content=tflite_model))


    def __init__(self, interpreter):

        self.interpreter = interpreter

        self.interpreter.allocate_tensors()

        input_det = self.interpreter.get_input_details()[0]

        output_det = self.interpreter.get_output_details()[0]

        self.input_index = input_det["index"]

        self.output_index = output_det["index"]

        self.input_shape = input_det["shape"]

        self.output_shape = output_det["shape"]

        self.input_dtype = input_det["dtype"]

        self.output_dtype = output_det["dtype"]


    def predict(self, inp):

        inp = inp.astype(self.input_dtype)

        count = inp.shape[0]

        out = np.zeros((count, self.output_shape[1]), dtype=self.output_dtype)

        for i in range(count):

            self.interpreter.set_tensor(self.input_index, inp[i:i+1])

            self.interpreter.invoke()

            out[i] = self.interpreter.get_tensor(self.output_index)[0]

        return out


    def predict_single(self, inp):

        """ Like predict(), but only for a single record. The input data can be a Python list. """

        inp = np.array([inp], dtype=self.input_dtype)

        self.interpreter.set_tensor(self.input_index, inp)

        self.interpreter.invoke()

        out = self.interpreter.get_tensor(self.output_index)

        return out[0]

完整的基准代码和绘图可以在这里找到:https://medium.com/@micwurm/using-tensorflow-lite-to-speed-up-predictions-a3954886eb98


查看完整回答
反对 回复 2022-08-02
  • 2 回答
  • 0 关注
  • 135 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信