【问题标题】:Minimize the output of Tensorflow regression model using one of the inputs使用输入之一最小化 Tensorflow 回归模型的输出
【发布时间】:2021-04-13 07:01:22
【问题描述】:

我正在尝试使用 this 指南训练 Tensorflow 模型,目的是使用深度神经网络 (Tensorflow) 解决优化问题。到目前为止,我的模型需要 9 个输入并产生 1 个输出。

我现在要做的是在一个应用程序中使用它,目标是在其他输入值固定的情况下通过调整一个输入值来最小化输出值。

例如,让我们表示输入值x1, x2, ..., x10 和输出y。给定x2, x3, ..., x10 的值,最小化输出yx1 的值是多少?有关我的问题的直观描述,请参见下图。

我使用 Keras 训练了一个网络并将其保存为 variable.data-00000-of-00001variables.index 文件,并使用 tf.keras.models.load_model 加载它。

我当前的代码是一个超慢的“硬编码”优化函数,它依赖于通过迭代 x1 值并通过网络运行它们来将值附加到列表中,将每个输出附加到列表中,并观察生成了哪个 x1 值最低的输出。这显然不是一个很好的解决方案。请参阅下面的代码。

for index, row in input_df.iterrows():
    prediction = model.predict(row[['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9']]).flatten()
    prediction = float(prediction)
    X1_predictions.ayend(prediction)

    # Optimized x1
    x1_values = []
    y_pred_values = []
    for x1 in np.arange(-1, 0, 0.01):
        row['x1'] = x1
        x1_values.append(x1)
        y_prediction = y_model.predict(row[['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9']]).flatten()
        y_prediction = float(y_prediction)
        y_pred_values.ayend(y_prediction)

    min_y_val = min(y_pred_values)
    min_y_idx = y_pred_values.index(min(y_pred_values))
    opt_x1 = x1_values[min_y_idx]

    x1_opt_list.ayend(opt_x1)
    y_opt_predictions.ayend(min_y_val)

我以前没有使用过这样的 TF 回归模型,我应该如何使用 Tensorflow/Keras 而不是列表和 for 循环以更优雅的方式解决这个问题?

【问题讨论】:

  • 你(可能)不需要神经网络来完成这项任务。如果我在你的位置,我会查看scipy.optimize 或类似的。虽然完全可以用 TensorFlow 编写优化问题,但我不确定我是否明白这一点。
  • @Lescurel 好吧,数据集由大约 4000 个数据点组成,它们之间的相关性并不高。我已经成功地训练了一个神经网络来很好地预测输出,所以我最好坚持这个解决方案。
  • 如果您有更多详细信息,我鼓励您在问题中添加它们。您的目标是“冻结”当前网络并根据网络的输出修改输入吗?
  • @Lescurel,是的,这就是我目前的策略。但是,我之前没有研究过这样的优化问题(我并没有真正在生产中使用 DL 模型,只是为了学术目的而训练),所以我愿意接受其他建议。假设我可以在 0-1 之间调整 x1。思路是根据固定的其他 8 个参数,找到产生最低输出值的 x1 值。

标签: tensorflow keras regression


【解决方案1】:

我可以给你一个粗略的例子,说明如何用 tensorflow 解决优化问题。

假设您有一个特定的函数,并希望根据一些基本事实 y 优化该函数的输入。我们称该函数为my_funct。 (在你的情况下,这将是一个冻结的神经网络)。在我的示例中,我将采用一个简单的函数,例如 sum :

@tf.function
def my_funct(inp):
    return tf.reduce_sum(inp)

现在,让我们定义一个输入和一个基本事实。在那个优化问题中,我的基本事实是输入的总和 + 1。所以在优化结束时,我的变量 x1 应该等于 x1 +1

inp = tf.random.normal((9,))
y_true = tf.reduce_sum(inp) + 1

现在,您需要在tf.Variable 中编码您想要优化的值(在您的示例中为x1)。这是 TensorFlow 跟踪需要优化的状态的方式。在我们的例子中,x1 是我们输入的第一个值。

x1 = tf.Variable(inp[0])

让我们自己开始优化。我们需要:

  • 成本函数,它将告诉我们距离目标有多远
  • 一种优化器,一种用于修改程序状态从而降低成本函数的算法。

在这种情况下,我将使用梯度下降优化器和均方误差作为目标函数,但还有很多其他可能更适合您的问题。

opt = tf.optimizers.SGD()
cost = tf.losses.mse

然后,我们可以使用 TensorFlow 自行编写优化。为此,我们需要计算成本函数相对于状态的梯度,并将其提供给优化器,以便优化器可以在正确的方向上修改状态,以最小化我们的成本。

可以这样做:

STEPS = 200
for _ in range(STEPS):
    with tf.GradientTape() as tape:
        tape.watch(x1)
        y_pred = my_funct(tf.concat([[x1], inp[1:]], axis=0))
        loss = cost([y], [y_pred])
    grad = tape.gradient(loss, [x1])
    opt.apply_gradients(zip(grad, [x1]))

tf.Variable 与其余输入一起处理有点麻烦,就像我处理tf.concat 一样。可能有一种更优雅的方法,但我不想过度设计这个简单的例子。

在该过程结束时,我们应该有接近 x1=inp[0] + 1 的东西 让我们检查一下:

>>> inp[0] + 1
<tf.Tensor: shape=(), dtype=float32, numpy=2.5110626>
>>> x1
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=2.4934747>

还不错!

注意: 在这些问题中,您可以调整一些超参数以获得更快、更好的结果,例如步数、学习率等。

【讨论】:

  • 非常感谢您提供如此详细而精心编写的回复!我会尽快实现这个,我会告诉你它是如何进行的。
  • 在您的示例中,您有一个基本事实x1+1,但在我的情况下,我想在不知道基本事实的情况下最小化 DNN 模型的输出变量y,以便说话。我不太确定如何将您的示例转化为我的案例,因为这是一个巨大的差异?
  • 如果你想最小化y,那么你的基本事实可能是0。 (如果你的 DNN 的输出是正的)。
  • 有道理!我现在已经实现了它,它似乎正在工作。然而,从实际的角度来看,优化的结果给出了一个不可行的结果。您如何使用这种技术将x1 限制在一定范围内?
  • 那你需要添加约束。一种方法是如果x1 的值超出/低于某个阈值,则对成本函数添加惩罚。
猜你喜欢
  • 2018-03-26
  • 2022-01-23
  • 2019-05-01
  • 2020-04-10
  • 2020-09-08
  • 2021-08-05
  • 1970-01-01
  • 2020-03-30
  • 1970-01-01
相关资源
最近更新 更多