我的训练数据保存在3个文件中,每个文件都太大而无法放入内存中。对于每个训练示例,数据都是二维的(2805行和222列,第222列用于标签)并且是数字值。我想在进入训练模型之前对数据进行标准化。下面是我的input_pipeline代码,和 在创建数据集之前,数据尚未标准化。 tensorflow中是否有一些函数可以对我的情况进行规范化?
dataset = tf.data.TextLineDataset([file1, file2, file3])
# combine 2805 lines into a single example
dataset = dataset.batch(2805)
def parse_example(line_batch):
record_defaults = [[1.0] for col in range(0, 221)]
record_defaults.append([1])
content = tf.decode_csv(line_batch, record_defaults = record_defaults, field_delim = '\t')
features = tf.stack(content[0:221])
features = tf.transpose(features)
label = content[-1][-1]
label = tf.one_hot(indices = tf.cast(label, tf.int32), depth = 2)
return features, label
dataset = dataset.map(parse_example)
dataset = dataset.shuffle(1000)
# batch multiple examples
dataset = dataset.batch(batch_size)
dataset = dataset.repeat(num_epochs)
iterator = dataset.make_one_shot_iterator()
data_batch, label_batch = iterator.get_next()
答案 0 :(得分:11)
除了benjaminplanche对“#4数据集归一化”的回答外,实际上有一种很简单的方法可以实现这一点。
Tensorflow的Keras提供了preprocessing normalization layer。现在,由于这是一个层,因此其意图将在模型中使用。但是,您不必(稍后再介绍)。
模型用法很简单:
input = tf.keras.Input(shape=dataset.element_spec.shape)
norm = tf.keras.layers.preprocessing.Normalization()
norm.adapt(dataset) # you can use dataset.take(N) if N samples is enough for it to figure out the mean & variance.
layer1 = norm(input)
...
在模型中使用它的优点是将归一化均值和方差保存为模型权重的一部分。因此,当您加载保存的模型时,它将使用与训练时相同的值。
如前所述,如果您不想使用keras模型,则不必将图层用作图层的一部分。如果您希望在数据集管道中使用它,也可以这样做。
norm = tf.keras.layers.experimental.preprocessing.Normalization()
norm.adapt(dataset)
dataset = dataset.map(lambda t: norm(t))
缺点是您需要立即手动保存和恢复这些权重(norm.get_weights()
和norm.set_weights()
)。 Numpy具有方便的save()
和load()
功能,您可以在此处使用。
np.save("norm_weights.npy", norm.get_weights())
norm.set_weights(np.load("norm_weights.npy", allow_pickle=True))
答案 1 :(得分:7)
有不同的方法来规范化数据"。根据您的想法,在您的情况下可能会或可能不容易实施。
如果您知道值的固定范围(例如,功能#1的值为[-5, 5]
,则功能#2的值为[0, 100]
等),您可以轻松预测处理feature
中的parse_example()
张量,例如:
def normalize_fixed(x, current_range, normed_range):
current_min, current_max = tf.expand_dims(current_range[:, 0], 1), tf.expand_dims(current_range[:, 1], 1)
normed_min, normed_max = tf.expand_dims(normed_range[:, 0], 1), tf.expand_dims(normed_range[:, 1], 1)
x_normed = (x - current_min) / (current_max - current_min)
x_normed = x_normed * (normed_max - normed_min) + normed_min
return x_normed
def parse_example(line_batch,
fixed_range=[[-5, 5], [0, 100], ...],
normed_range=[[0, 1]]):
# ...
features = tf.transpose(features)
features = normalize_fixed(features, fixed_range, normed_range)
# ...
如果您的要素具有大致相同的值范围,则还可以考虑每个样本的归一化,即考虑每个样本的特征矩(均值,方差)应用归一化:
def normalize_with_moments(x, axes=[0, 1], epsilon=1e-8):
mean, variance = tf.nn.moments(x, axes=axes)
x_normed = (x - mean) / tf.sqrt(variance + epsilon) # epsilon to avoid dividing by zero
return x_normed
def parse_example(line_batch):
# ...
features = tf.transpose(features)
features = normalize_with_moments(features)
# ...
您可以在完整批次而不是每个样本上应用相同的过程,这可以使过程更稳定:
data_batch = normalize_with_moments(data_batch, axis=[1, 2])
同样,您可以使用tf.nn.batch_normalization
使用在整个数据集上计算的均值/方差进行标准化将是最棘手的,因为正如您所提到的那样,它是一个大的,分裂的。
tf.data.Dataset
并非真正意味着进行此类全局计算。解决方案是使用您拥有的任何工具来预先计算数据集时刻,然后将此信息用于TF预处理。
如@MiniQuark所述,Tensorflow有一个Transform库,可用于预处理数据。请查看Get Started,或者使用tft.scale_to_z_score()
方法查看样本规范化。
答案 2 :(得分:1)
定义inputs
后,执行以下代码行:
import tensorflow as tf
inputs = tf.keras.layers.LayerNormalization(
axis=-1,
center=True,
scale=True,
trainable=True,
name='input_normalized',
)(inputs)
我从 tensorflow API(自上述答案以来已更新)中推断出这一点。