如何在不急切的情况下将 Keras 规范化应用于 ParallelMapDataset?
How to apply Keras Normalization to a ParallelMapDataset without making it eager?
我正在对图像训练 Tensorflow Keras CNN,训练数据太多,无法放入内存。我有一个 tf.Dataset 预处理管道,它使用 dataset.map()
管道步骤从 HDF5 文件中读取图像。现在我正在尝试将数字图像数据标准化为 0 均值和单位方差。
我正在关注 this example from this guide,除了我在里面有那个 .map()
:
def load_features_from_hdf5(filename):
spec = tf.TensorSpec(feature_shape, dtype=tf.dtypes.float32, name=None)
dataset = tfio.IODataset.from_hdf5(filename, "/features", spec=spec) # returns a Dataset
feature = dataset.get_single_element()
feature.set_shape(feature_shape)
return feature
train_x = tf.data.Dataset.from_tensor_slices(filenames).map(load_features_from_fbank, num_parallel_calls=tf.data.AUTOTUNE)
normalizer = tf.keras.layers.Normalization(axis=None)
normalizer.adapt(train_x.take(1000))
train_x_normalized = normalizer(train_x) # <-- ValueError
adapt()
成功计算了数据集的均值和方差。但是,当我尝试在完全相同的数据集上实际应用值规范化时,它在尝试将我的 ParallelMapDataset 转换为 EagerTensor 时出错。
ValueError: Attempt to convert a value (<ParallelMapDataset shapes: (41, 682, 1), types: tf.float32>) with an unsupported type (<class 'tensorflow.python.data.ops.dataset_ops.ParallelMapDataset'>) to a Tensor.
我怎样才能让它工作?由于数据如此之大,我认为在训练开始之前我不想做任何事情。我应该将规范化作为数据集上的显式管道步骤吗?还是模型本身的显式层? (如果是后一种情况,如何在另一个过程中将训练时间的均值和方差值带到推理时间?)
您可以尝试这样的操作:
import tensorflow as tf
# Create dummy data
train_x = tf.data.Dataset.from_tensor_slices((tf.random.normal((100, 28, 28, 3)), tf.random.normal((100, 1)))).batch(10)
normalizer = tf.keras.layers.Normalization(axis=None)
# Adapt
normalizer.adapt(train_x.map(lambda x, y: x))
# Apply to images
train_x_normalized = train_x.map(lambda x, y: (normalizer(x), y))
示例:
for x, y in train_x_normalized.take(1):
print(tf.reduce_mean(x), tf.math.reduce_variance(x))
tf.Tensor(0.00930768, shape=(), dtype=float32) tf.Tensor(1.0023469, shape=(), dtype=float32)
或者,正如您在问题中提到的,您可以将规范化层用作模型的一部分。
我正在对图像训练 Tensorflow Keras CNN,训练数据太多,无法放入内存。我有一个 tf.Dataset 预处理管道,它使用 dataset.map()
管道步骤从 HDF5 文件中读取图像。现在我正在尝试将数字图像数据标准化为 0 均值和单位方差。
我正在关注 this example from this guide,除了我在里面有那个 .map()
:
def load_features_from_hdf5(filename):
spec = tf.TensorSpec(feature_shape, dtype=tf.dtypes.float32, name=None)
dataset = tfio.IODataset.from_hdf5(filename, "/features", spec=spec) # returns a Dataset
feature = dataset.get_single_element()
feature.set_shape(feature_shape)
return feature
train_x = tf.data.Dataset.from_tensor_slices(filenames).map(load_features_from_fbank, num_parallel_calls=tf.data.AUTOTUNE)
normalizer = tf.keras.layers.Normalization(axis=None)
normalizer.adapt(train_x.take(1000))
train_x_normalized = normalizer(train_x) # <-- ValueError
adapt()
成功计算了数据集的均值和方差。但是,当我尝试在完全相同的数据集上实际应用值规范化时,它在尝试将我的 ParallelMapDataset 转换为 EagerTensor 时出错。
ValueError: Attempt to convert a value (<ParallelMapDataset shapes: (41, 682, 1), types: tf.float32>) with an unsupported type (<class 'tensorflow.python.data.ops.dataset_ops.ParallelMapDataset'>) to a Tensor.
我怎样才能让它工作?由于数据如此之大,我认为在训练开始之前我不想做任何事情。我应该将规范化作为数据集上的显式管道步骤吗?还是模型本身的显式层? (如果是后一种情况,如何在另一个过程中将训练时间的均值和方差值带到推理时间?)
您可以尝试这样的操作:
import tensorflow as tf
# Create dummy data
train_x = tf.data.Dataset.from_tensor_slices((tf.random.normal((100, 28, 28, 3)), tf.random.normal((100, 1)))).batch(10)
normalizer = tf.keras.layers.Normalization(axis=None)
# Adapt
normalizer.adapt(train_x.map(lambda x, y: x))
# Apply to images
train_x_normalized = train_x.map(lambda x, y: (normalizer(x), y))
示例:
for x, y in train_x_normalized.take(1):
print(tf.reduce_mean(x), tf.math.reduce_variance(x))
tf.Tensor(0.00930768, shape=(), dtype=float32) tf.Tensor(1.0023469, shape=(), dtype=float32)
或者,正如您在问题中提到的,您可以将规范化层用作模型的一部分。