【问题标题】:How to feed further model parameters along the inputs to Tensorflow Estimator?如何将更多模型参数沿输入提供给 Tensorflow Estimator?
【发布时间】:2018-09-15 02:02:20
【问题描述】:

短版: 我有一个自定义模型,其层可以通过值sigma 进行参数化。

我正在将此模型与 Tensorflow Estimator 一起使用:

    classifier = tf.estimator.Estimator(model_fn=model_fun)

例如,训练声明如下:

    # Train the model
    train_input_fn=tf.estimator.inputs.numpy_input_fn(x={"x": train_data}, 
    batch_size=batch_size, num_epochs=nEpochs, shuffle=True)
    classifier.train(input_fn=train_input_fn,max_steps=nSteps)

在此设置中,我如何将 sigma 传递给我的自定义 Estimator,以便可以使用不同的值对其进行训练/评估?


加长版:

我正在研究这个 DNN 自动编码器,为此我有一个层,它通过考虑已知标准偏差 sigma 分布中的 random_normal() 值来添加高斯噪声。

这是一个通信系统的模型,输出 logits(来自最后一层)是使用 model.predict() 函数检索的,我的指标,即误码率是由 Tensor Flow 1.5 中的自定义函数计算的,Python 3.5,Windows 10。

问题如下:

  1. 我想针对 sigma=sigma1 训练系统,并检索输出 logits。(这部分很好,我能够获得所需的输出。)

  2. 我还想使用定义的相同估计器(在同一程序中)预测 sigma=sigma2、sigma=sigma3、sigma=sigma4 等的输出。

我的 DNN 看起来像这样,并且在模型函数中定义:

  1. 输入第一层热编码值在此处输入。

  2. 密集+ReLU

  3. 密集+线性

  4. 归一化层

  5. 添加噪声:这里我在前一层的输出中添加了一个 tf.random_normal(stddev=sigma)。这是我希望帮助我了解如何为每次运行(训练/测试)使用不同 sigma 的地方。我想你可以说 sigma 应该是一个参数,每次测试运行可以有不同的值。

     gnoise=tf.random_normal(mean=0,stddev=sigma) 
     Then the layer's output=norm(which is the prev layer's output)+gnoise
    
  6. 密集+RELU

  7. Softmax-输出为 Logits

我将我的估算器定义为:

    classifier = tf.estimator.Estimator(model_fn=model_fun)

训练声明如下:

    # Train the model
    train_input_fn=tf.estimator.inputs.numpy_input_fn(x={"x": train_data}, 
    batch_size=batch_size, num_epochs=nEpochs, shuffle=True)
    classifier.train(input_fn=train_input_fn,max_steps=nSteps)

predict函数被声明并调用为:

    pred_input_fn=tf.estimator.inputs.numpy_input_fn(x={"x": test_data}, 
    batch_size=batch_size, num_epochs=nEpochs, shuffle=False)
    pred_results = classifier.predict(input_fn=pred_input_fn)

【问题讨论】:

  • 请提供您的高斯噪声层代码,以便大家回复。
  • gnoise=tf.random_normal(mean=0,stddev=sigma) 然后层的输出=norm(即prev层的输出)+gnoise

标签: python numpy tensorflow deep-learning tensorflow-estimator


【解决方案1】:

您应该让您的 sigma 成为您层的参数,然后在运行时通过您的 features 将其值提供给您的模型(使用列键区分 xsigma)。

没有你的高斯层代码很难准确回复,但假设你的模型是这样定义的:

import tensorflow as tf

def gaussian_noise_layer(x):
    # Currently, your sigma is probably fixed somewhere here, e.g.
    sigma = 1

    dist = tf.distributions.Normal(loc=0., scale=sigma)

    # Build Gaussian kernel from dist:
    # gaussian_kernel = ...

    return tf.nn.depthwise_conv2d(x, gaussian_kernel, [1, 1, 1, 1], padding='SAME')

def model_fun(features, labels, mode, params):

    # Get input x from features:
    x = tf.feature_column.input_layer(features, params.feature_column)

    # ... building your model here, adding at some point the gaussian layer, e.g.
    # ... net = f(x)
    net = gaussian_noise_layer(net)
    # ... predictions = f'(net)
    # ...

    return tf.estimator.EstimatorSpec(
        mode=mode,
        predictions=predictions,
        loss=loss,
        train_op=train_op,
        eval_metric_ops=eval_metric_ops
    )

with tf.Session() as sess:
    # ...

    # Specifying your params and inputs:
    params = tf.contrib.training.HParams(
        # ... other hyperparameters,
        # Define feature column for input x of shape "shape_x" (e.g. (64, 64, 3)):
        feature_column=tf.feature_column.numeric_column(key="x", shape=shape_x)
    )

    classifier = tf.estimator.Estimator(model_fn=model_fun, params=params)

    # For training:
    train_input_fn = tf.estimator.inputs.numpy_input_fn(x={"x": train_data},
                                                        batch_size=batch_size, num_epochs=nEpochs, shuffle=True)
    classifier.train(input_fn=train_input_fn, max_steps=nSteps)

...那么您需要像这样编辑它:

import tensorflow as tf

def gaussian_noise_layer(x, sigma):

    # sigma is now a parameter
    dist = tf.distributions.Normal(loc=0., scale=sigma)

    # Build Gaussian kernel from dist:
    # gaussian_kernel = ...

    return tf.nn.depthwise_conv2d(x, gaussian_kernel, [1, 1, 1, 1], padding='SAME')

def model_fun(features, labels, mode, params):

    # Get input x from features:
    x = tf.feature_column.input_layer(features, params.input_feature_column)
    # Get sigma from features:
    sigma = tf.feature_column.input_layer(features, params.sigma_feature_column)

    # ... building your model here, adding at some point the gaussian layer, e.g.
    # ... net = f(x)
    net = gaussian_noise_layer(net, sigma)
    # ... predictions = f'(net)
    # ...

    return tf.estimator.EstimatorSpec(
        mode=mode,
        predictions=predictions,
        loss=loss,
        train_op=train_op,
        eval_metric_ops=eval_metric_ops
    )

with tf.Session() as sess:
    # ...

    # We now specify which columns contain the actual inputs (x), and which columns contain other parameters (sigma):
    params = tf.contrib.training.HParams(
        # ... other hyperparameters,
        # Define feature column for input x of shape "shape_x" (e.g. (64, 64, 3)):
        input_feature_column=tf.feature_column.numeric_column(key="x", shape=shape_x),
        # Define feature column for input sigma of shape () i.e. scalar (default shape):
        sigma_feature_column=tf.feature_column.numeric_column(key="sigma")
    )

    classifier = tf.estimator.Estimator(model_fn=model_fun, params=params)

    # Train:
    num_train_elements = train_data.shape[0]
    sigma = [1] * num_train_elements  # or e.g. sigma = [1, 1, 2, 1, 3, ...]
    # We can now feed sigma along x:
    train_input_fn = tf.estimator.inputs.numpy_input_fn(
         x={"x": train_data, "sigma": numpy.array(sigma)},
         batch_size=batch_size, num_epochs=nEpochs, shuffle=True)

    classifier.train(input_fn=train_input_fn, max_steps=nSteps)

    # ...

    # Predict:
    sigma = [2] * num_train_elements  # or e.g. sigma = [1, 1, 2, 1, 3, ...]
    pred_input_fn=tf.estimator.inputs.numpy_input_fn(
         x={"x": train_data, "sigma": numpy.array(sigma)},
         batch_size=batch_size, num_epochs=nEpochs, shuffle=True)
    pred_results = classifier.predict(input_fn=pred_input_fn)

【讨论】:

  • 感谢您的回答。您能否描述一下我将如何将不同的参数 sigma 添加到预测函数声明和调用中?
  • 此外,TF 似乎希望在 train_input_fn 中声明的“x”和“sigma”的值具有相同的形状。是否有解决方法,因为我希望 sigma 保持单个标量值,例如 1、2、3 等?
  • 1) 对于预测,您只需以与训练相同的方式定义其输入,即将 sigma(作为 numpy 元素)添加到 tf.estimator.inputs.numpy_input_fn 的字典中。我更新了答案以添加示例。 2)正如您在答案中看到的(我添加了 cmets 以进一步澄清),在 params 中定义特征列时,x 和 sigma 的形状被传递给 TF。在答案中,x 具有形状“shape_x”(例如 (64, 64, 3)),而 sigma 具有默认形状 (),即是一个标量。
  • 我的意思是在遵循此代码时,我看到此错误:ValueError:x 和 y 中的张量长度不匹配。 x 和 y 中的所有元素必须具有相同的长度。 x 和 y 是 numpy 输入函数的参数,可以包含特征字典。这基本上意味着 numpy 输入函数需要 SNR 和 train_data 具有相同的大小
  • 好吧,我的错。我忘记扩展 [sigma] 使其长度与 train_data 相同,例如做[sigma_val] * train_data.shape[0](代码已更新)。实际上,在这个实现中,必须为训练数据中的每个元素传递一个 sigma 值(这样做的一个积极方面是您可以为每个元素设置不同的 sigma 值)。希望这会有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-14
  • 2022-01-23
相关资源
最近更新 更多