在 Tensorflow 中训练时获取 Tensor 形状
Get Tensor shape at train time in Tensorflow
如何在训练时获得张量的“实际”形状?例如,
(None, 64) -> (128, 64)
换句话说,在训练时,我得到类似 (None, 64)
的形状,其中 None
表示张量的第一维是动态的 w.r.t 输入大小,并且 64
是第二个维度的示例值。我假设在训练时,框架知道该张量的“实际”大小,所以我想知道 how/if 我可以获得张量的实际大小,其中 None
被评估为 train/test/eval 数据集大小。因此,我有兴趣获得 (128, 64)
而不是 (None, 64)
,其中 128
是输入的大小。
请考虑以下简化的代码示例。
class ALayer(tensorflow.keras.layers.Layer):
def call(self, inputs):
features = tf.matmul(inputs, self.kernel) + self.bias
# These are the different approaches I've tried.
print(features.shape)
# This prints: (None, 64)
print(tf.shape(features)
# This prints: Tensor("ALayer/Shape:0", shape=(2,), dtype=int32)
return features
input_layer = layers.Input(input_dim)
x = ALayer()([input_layer])
x = layers.Dense(1)(x)
model = keras.Model(inputs=[input_layer], outputs=[x])
model.compile()
train_dataset = tf.data.Dataset.from_tensor_slices((X_train, (y_train)))
val_dataset = tf.data.Dataset.from_tensor_slices((X_val, (y_val)))
model.fit(train_dataset, validation_data=val_dataset)
您应该使用 tf.print
,因为在 TF 2.7 中默认激活急切执行:
import tensorflow as tf
class ALayer(tf.keras.layers.Layer):
def __init__(self, units=32):
super(ALayer, self).__init__()
self.units = units
def build(self, input_shape):
self.w = self.add_weight(
shape=(input_shape[-1], self.units),
initializer="random_normal",
trainable=True,
)
self.b = self.add_weight(
shape=(self.units,), initializer="random_normal", trainable=True
)
def call(self, inputs):
features = tf.matmul(inputs, self.w) + self.b
tf.print('Features shape -->', tf.shape(features), '\n')
return features
input_layer = tf.keras.layers.Input(shape=(10,))
x = ALayer(10)(input_layer)
x = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs=[input_layer], outputs=[x])
model.compile(loss=tf.keras.losses.BinaryCrossentropy())
X_train, y_train = tf.random.normal((64, 10)), tf.random.uniform((64,), maxval=2, dtype=tf.int32)
X_val, y_val = tf.random.normal((64, 10)), tf.random.uniform((64,), maxval=2, dtype=tf.int32)
train_dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train)).batch(32)
val_dataset = tf.data.Dataset.from_tensor_slices((X_val, y_val)).batch(32)
model.fit(train_dataset, validation_data=val_dataset, epochs=1, verbose=0)
Features shape --> [32 10]
Features shape --> [32 10]
Features shape --> [32 10]
Features shape --> [32 10]
<keras.callbacks.History at 0x7fab3ce15910>
如何在训练时获得张量的“实际”形状?例如,
(None, 64) -> (128, 64)
换句话说,在训练时,我得到类似 (None, 64)
的形状,其中 None
表示张量的第一维是动态的 w.r.t 输入大小,并且 64
是第二个维度的示例值。我假设在训练时,框架知道该张量的“实际”大小,所以我想知道 how/if 我可以获得张量的实际大小,其中 None
被评估为 train/test/eval 数据集大小。因此,我有兴趣获得 (128, 64)
而不是 (None, 64)
,其中 128
是输入的大小。
请考虑以下简化的代码示例。
class ALayer(tensorflow.keras.layers.Layer):
def call(self, inputs):
features = tf.matmul(inputs, self.kernel) + self.bias
# These are the different approaches I've tried.
print(features.shape)
# This prints: (None, 64)
print(tf.shape(features)
# This prints: Tensor("ALayer/Shape:0", shape=(2,), dtype=int32)
return features
input_layer = layers.Input(input_dim)
x = ALayer()([input_layer])
x = layers.Dense(1)(x)
model = keras.Model(inputs=[input_layer], outputs=[x])
model.compile()
train_dataset = tf.data.Dataset.from_tensor_slices((X_train, (y_train)))
val_dataset = tf.data.Dataset.from_tensor_slices((X_val, (y_val)))
model.fit(train_dataset, validation_data=val_dataset)
您应该使用 tf.print
,因为在 TF 2.7 中默认激活急切执行:
import tensorflow as tf
class ALayer(tf.keras.layers.Layer):
def __init__(self, units=32):
super(ALayer, self).__init__()
self.units = units
def build(self, input_shape):
self.w = self.add_weight(
shape=(input_shape[-1], self.units),
initializer="random_normal",
trainable=True,
)
self.b = self.add_weight(
shape=(self.units,), initializer="random_normal", trainable=True
)
def call(self, inputs):
features = tf.matmul(inputs, self.w) + self.b
tf.print('Features shape -->', tf.shape(features), '\n')
return features
input_layer = tf.keras.layers.Input(shape=(10,))
x = ALayer(10)(input_layer)
x = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(inputs=[input_layer], outputs=[x])
model.compile(loss=tf.keras.losses.BinaryCrossentropy())
X_train, y_train = tf.random.normal((64, 10)), tf.random.uniform((64,), maxval=2, dtype=tf.int32)
X_val, y_val = tf.random.normal((64, 10)), tf.random.uniform((64,), maxval=2, dtype=tf.int32)
train_dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train)).batch(32)
val_dataset = tf.data.Dataset.from_tensor_slices((X_val, y_val)).batch(32)
model.fit(train_dataset, validation_data=val_dataset, epochs=1, verbose=0)
Features shape --> [32 10]
Features shape --> [32 10]
Features shape --> [32 10]
Features shape --> [32 10]
<keras.callbacks.History at 0x7fab3ce15910>