Keras模型的predict和predict_on_batch方法有什么区别?

31
根据 Keras 的 文档
predict_on_batch(self, x)
Returns predictions for a single batch of samples.

然而,在对一个批次进行预测时,使用标准的predict方法和仅使用一个元素或多个元素时没有任何区别。
model.predict_on_batch(np.zeros((n, d_in)))

是同义词

model.predict(np.zeros((n, d_in)))

一个形状为(n, d_out)numpy.ndarray


数组的大小是多少?predict函数有一个参数batch_size,如果没有设置,默认为32。如果n <= 32,则这两个函数调用应该是相同的。 - Toterich
3个回答

38

不同之处在于当你传递给x的数据超过一个批次时。

predict将逐个批次地遍历所有数据,预测标签。因此它在内部分批处理并一次馈送一个批次。

另一方面,predict_on_batch假设您传递的数据恰好是一个批次,因此将其馈送到网络中。它不会尝试拆分它(这取决于您的设置,如果该数组非常大,则可能导致GPU内存问题)。


好的,谢谢。batch_size实际上与SGD(及其变体)的小批量相同。这里也得到了确认:https://stats.stackexchange.com/questions/221886/how-to-set-mini-batch-size-in-sgd-in-keras。 - Phylliade
是的,无论何时你看到“batch”,通常的假设是你在谈论学习算法的小批量。 - GPhilo
还没有遇到过那种用例,不清楚。 - GPhilo

8
似乎predict_on_batch在单个批次上执行时比predict更快。
批次和模型信息: - 批次形状:(1024, 333) - 批次数据类型:float32 - 模型参数:约150k
时间结果: - predict: 约1.45秒 - predict_on_batch: 约95.5毫秒
总之,predict方法有额外的操作以确保一组批次被正确处理,而predict_on_batch是一个轻量级的替代方案,应该在单个批次上使用。

3

我想补充一些评论中未涉及的内容。看起来predict函数会仔细检查输出形状:

class ExtractShape(keras.engine.topology.Layer):
    def call(self, x):
        return keras.backend.sum(x, axis=0)
    def compute_output_shape(self, input_shape):
        return input_shape

a = keras.layers.Input((None, None))
b = ExtractShape()(a)
m = keras.Model(a, b)
m.compile(optimizer=keras.optimizers.Adam(), loss='binary_crossentropy')
A = np.ones((5,4,3))

然后:
In [163]: m.predict_on_batch(A)
Out[163]: 
array([[5., 5., 5.],
       [5., 5., 5.],
       [5., 5., 5.],
       [5., 5., 5.]], dtype=float32)
In [164]: m.predict_on_batch(A).shape
Out[164]: (4, 3)

但是:
In [165]: m.predict(A)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-165-c5ba5fc88b6e> in <module>()

----> 1 m.predict(A)

~/miniconda3/envs/ccia/lib/python3.6/site-packages/keras/engine/training.py in predict(self, x, batch_size, verbose, steps)
   1746         f = self.predict_function
   1747         return self._predict_loop(f, ins, batch_size=batch_size,
-> 1748                                   verbose=verbose, steps=steps)
   1749 
   1750     def train_on_batch(self, x, y,

~/miniconda3/envs/ccia/lib/python3.6/site-packages/keras/engine/training.py in _predict_loop(self, f, ins, batch_size, verbose, steps)
   1306                         outs.append(np.zeros(shape, dtype=batch_out.dtype))
   1307                 for i, batch_out in enumerate(batch_outs):
-> 1308                     outs[i][batch_start:batch_end] = batch_out
   1309                 if verbose == 1:
   1310                     progbar.update(batch_end)

ValueError: could not broadcast input array from shape (4,3) into shape (5,3)

我不确定这是否真的是一个bug。


我不明白(5,3)是从哪里来的。你的批次中有5个元素,但为什么第二个维度会消失? - GPhilo
@GPhilo 请查看 https://github.com/keras-team/keras/blob/master/keras/engine/training.py#L1336,输出列表是预先计算的,并且假定第一个维度是“批次索引”,因此输出形状被切片。 - Jorge E. Cardona
1
好的,现在我明白你的意思了。我认为predict必须检查输出的形状,因为它需要将所有结果放在一起并同时返回它们,所以它会预先分配空间。另一方面,predict_batch只需要返回一个评估运行的结果,因此它不需要关心返回内容的形状。因此,在自定义层不每批次产生一个结果的情况下,predict将无法正常工作。我也不认为这是一个错误。 - GPhilo
@GPhilo 我认为这是一个bug的原因是因为compute_output_shape方法没有被使用。predict仅仅是通过预先分配列表outs的形状来检查形状,这是第一批次的形状。似乎用户需要负责适当地处理第一个维度,包括正确定义compute_output_shape方法并返回该形状的张量。此外,在样本少于batch_size的情况下,predictpredict_on_batch应该以类似的方式运行。 - Jorge E. Cardona

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接