【问题标题】:how to normalize input data for models in tensorflow如何规范化张量流中模型的输入数据
【发布时间】:2019-01-18 13:35:41
【问题描述】:

我的训练数据保存在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() 

【问题讨论】:

    标签: tensorflow


    【解决方案1】:

    “规范化数据”有不同的方法。根据您的想法,在您的情况下实施起来可能容易,也可能不容易。

    1。固定归一化

    如果您知道值的固定范围(例如,特征 #1 的值在 [-5, 5] 中,特征 #2 的值在 [0, 100] 中,等等),您可以轻松地预处理您的 @987654328 @张量在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)
        # ...
    

    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)
        # ...
    

    3。批量归一化

    您可以对整个批次而不是每个样本应用相同的程序,这可能会使过程更加稳定:

    data_batch = normalize_with_moments(data_batch, axis=[1, 2])
    

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

    4。数据集规范化

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

    tf.data.Dataset 并不是真正用于这种全局计算。一种解决方案是使用任何工具来预先计算数据集矩,然后将此信息用于 TF 预处理。


    正如@MiniQuark 所提到的,Tensorflow 有一个Transform 库,您可以使用它来预处理您的数据。查看Get Started,或者例如tft.scale_to_z_score() 样本标准化方法。

    【讨论】:

    • 您可能想提及 TensorFlow Transform,github.com/tensorflow/transform。
    • @MiniQuark 我不知何故不知道这个库...感谢您的提及(以及之前的更正)!
    • 感谢您的帮助。 @MiniQuark @Aldream
    • 很棒的帖子,谢谢!对于像我这样的新手:如果您想在整个批次中执行此过程,只需使用 axes=[0,1,2]。
    【解决方案2】:

    扩展 benjaminplanche 对“#4 Dataset normalization”的回答,实际上有一种非常简单的方法可以完成此操作。

    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))
    

    【讨论】:

    • 嗨,@Patrick,我只有 TF1.12 和 Keras 2.2.4,我有这个错误,模块 'tensorflow._api.v1.keras.layers' 没有属性 'experimental',有没有任何使用 '''module 'tensorflow._api.v1.keras.layers' 的旧 API 都没有属性 'experimental''''?
    • 我认为在模型中使用归一化不是一个好主意,所以我不想使用规范层。非常感谢
    【解决方案3】:

    定义inputs后,执行以下代码行:

    import tensorflow as tf
    inputs = tf.keras.layers.LayerNormalization(
        axis=-1,
        center=True,
        scale=True,
        trainable=True,
        name='input_normalized',
    )(inputs)
    

    我从 tensorflow API 推断出这一点(自上述答案以来已更新)。

    【讨论】:

    • 注意:以上示例中的所有关键字参数都是默认值。
    猜你喜欢
    • 1970-01-01
    • 2020-03-01
    • 2021-10-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2019-09-19
    • 1970-01-01
    相关资源
    最近更新 更多