如何在TF2中的call()函数中获取batch_size



我正在尝试在TF2模型的call()函数中获取batch_size。然而,我无法得到它,因为我知道的所有方法都返回None或张量,而不是维度元组。

以下是的一个简短示例

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Model
class MyModel(Model):
def __init__(self):
super(MyModel, self).__init__()

def call(self, x):
print(len(x))
print(x.shape)
print(tf.size(x))
print(np.shape(x))
print(x.get_shape())
print(x.get_shape().as_list())
print(tf.rank(x))
print(tf.shape(x))
print(tf.shape(x)[0])
print(tf.shape(x)[1])        
return tf.random.uniform((2, 10))

m = MyModel()
m.compile(optimizer="Adam", loss="sparse_categorical_crossentropy", metrics=['accuracy'])
m.fit(np.array([[1,2,3,4], [5,6,7,8]]), np.array([0, 1]), epochs=1)

输出为:

Tensor("my_model_26/strided_slice:0", shape=(), dtype=int32)
(None, 4)
Tensor("my_model_26/Size:0", shape=(), dtype=int32)
(None, 4)
(None, 4)
[None, 4]
Tensor("my_model_26/Rank:0", shape=(), dtype=int32)
Tensor("my_model_26/Shape_2:0", shape=(2,), dtype=int32)
Tensor("my_model_26/strided_slice_1:0", shape=(), dtype=int32)
Tensor("my_model_26/strided_slice_2:0", shape=(), dtype=int32)
1/1 [==============================] - 0s 1ms/step - loss: 3.1796 - accuracy: 0.0000e+00

在本例中,我将(2,4)numpy数组作为输入,将(2, )作为目标提供给模型。但正如您所看到的,我无法在call()函数中获得batch_size

我需要它的原因是,我必须迭代batch_size的张量,这在我的真实模型中是动态的。

例如,如果数据集大小为10,批大小为3,则最后一批中的最后一批大小将为1。所以,我必须动态地知道批量大小。

有人能帮我吗?


  • Tensorflow 2.3.3
  • 库达10.2
  • python 3.6.9

这是因为您使用的是TensorFlow(这是强制性的,因为Keras现在在TensorFlow中(,并且通过使用TensorFlow,您需要注意;汇编;将动态图转换为静态图。

简而言之,您的call方法是用@tf.function装饰器进行装饰的。

这个装饰师:

  1. 跟踪python函数的执行
  2. 转换TensorFlow操作中的python操作(例如if a > b变为tf.cond(tf.greater(a,b), something, something_else)(
  3. 创建tf.Graph(静态图(
  4. 执行刚刚创建的静态图形

Al您的print调用在第一步(python执行跟踪(中执行,这就是为什么即使您训练模型,也只能看到一次输出。

也就是说,要获得张量的运行时(动态形状(,必须使用tf.shape(x),批大小仅为batch_size = tf.shape(x)[0]

请注意,如果您想查看形状(使用打印(,则不能使用打印,但必须使用tf.print

import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras.models import Model

class MyModel(Model):
def __init__(self):
super(MyModel, self).__init__()
def call(self, x):
shape = tf.shape(x)
batch_size = shape[0]
tf.print(shape, batch_size)
return tf.random.uniform((2, 10))

m = MyModel()
m.compile(
optimizer="Adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"]
)
m.fit(np.array([[1, 2, 3, 4], [5, 6, 7, 8]]), np.array([0, 1]), epochs=1)

有关静态和动态形状的详细信息:https://pgaleone.eu/tensorflow/2018/07/28/understanding-tensorflow-tensors-shape-static-dynamic/

有关tf.function行为的更多信息:https://pgaleone.eu/tensorflow/tf.function/2019/03/21/dissecting-tf-function-part-1/

注:这些文章是我写的。

如果你想准确地获得数据和形状,你可能会实现急切的跑步,但这不是一个好的解决方案,因为它会使训练变得缓慢。

设置如下:

m.compile(optimizer="Adam", loss="sparse_categorical_crossentropy",
metrics=['accuracy'], run_eagerly=True)

然后输出为:

(2, 4)
tf.Tensor(8, shape=(), dtype=int32)
(2, 4)
(2, 4)
[2, 4]
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor([2 4], shape=(2,), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(4, shape=(), dtype=int32)

最新更新