如何规范张量流中模型的输入数据

jin*_*ng 11 tensorflow

我的训练数据保存在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() 
Run Code Online (Sandbox Code Playgroud)

Pat*_*ick 14

扩展本杰明普朗什对“#4 数据集规范化”的回答,实际上有一种非常简单的方法来实现这一点。

Tensorflow 的 Keras 提供了预处理归一化层。现在这是一个层,它的意图是在模型中使用。但是,您不必(稍后会详细介绍)。

模型使用很简单:

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)
...
Run Code Online (Sandbox Code Playgroud)

在模型中使用它的优点是归一化均值和方差被保存为模型权重的一部分。因此,当您加载保存的模型时,它将使用与训练时相同的值。

 

如前所述,如果您不想使用 keras 模型,则不必将层用作其中的一部分。如果您更愿意在数据集管道中使用它,您也可以这样做。

norm = tf.keras.layers.experimental.preprocessing.Normalization()
norm.adapt(dataset)
dataset = dataset.map(lambda t: norm(t))
Run Code Online (Sandbox Code Playgroud)

缺点是您现在需要手动保存和恢复这些权重(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))
Run Code Online (Sandbox Code Playgroud)


ben*_*che 12

有"标准化数据"的不同方法.根据您的想法,在您的情况下可能或可能不容易实施.

1.修正了规范化

如果您知道值的固定范围(例如,特征#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)
    # ...
Run Code Online (Sandbox Code Playgroud)

2.每样本标准化

如果您的要素应具有大致相同的值范围,则还可以考虑每个样本的归一化,即考虑每个样本的特征矩(均值,方差)应用归一化:

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)
    # ...
Run Code Online (Sandbox Code Playgroud)

3.批量标准化

您可以在完整批次而不是每个样本上应用相同的过程,这可以使过程更稳定:

data_batch = normalize_with_moments(data_batch, axis=[1, 2])
Run Code Online (Sandbox Code Playgroud)

同样,你可以使用 tf.nn.batch_normalization

4.数据集规范化

使用在整个数据集上计算的均值/方差进行归一化将是最棘手的,因为正如您所提到的那样,它是一个大的,分裂的.

tf.data.Dataset并不是真正意义上的全球计算.解决方案是使用您拥有的任何工具来预先计算数据集时刻,然后将此信息用于TF预处理.


正如@MiniQuark所提到的,Tensorflow有一个可用于预处理数据的Transform库.查看"入门",或者tft.scale_to_z_score()查看样本规范化的方法.

  • 您可能想提及 TensorFlow Transform,https://github.com/tensorflow/transform。 (3认同)