python - 当导数未知并且需要一批输出来计算成本时,如何训练模型?

标签 python tensorflow

如果无法评估每个输入的成本,我想知道如何在 tensorflow 中训练模型。例如。如果我的目标函数测试某个条件是否在一半的情况下得到满足(任何偏离此条件的情况都会受到惩罚)。

以前,我会编写类似于以下内容的代码来定义我的成本函数和反向传播学习器:

# Backward propagation
loss = tensorflow.losses.mean_squared_error(labels=y, predictions=yhat)
cost = tensorflow.reduce_mean(loss, name='cost')
updates = tensorflow.train.GradientDescentOptimizer(0.01).minimize(cost)

其中yhat是一个张量,产生输出y的一些估计,而cost只是之间差异的平方>真实预测值。

但是,如果我的目标函数只能在我们拥有所有输入(或一批数据)后才能计算,并且导数未知,该怎么办?

这方面的一个例子可能是训练神经网络来查找其他函数内部的一组笛卡尔坐标(例如,在圆内 x^2 + y^2 = r^2 对于各种r) 50% 的时间。正确和错误答案的空间不是有限的,虽然无法计算成本相对于输出的导数(使得反向传播不可能),但损失函数本身计算起来相对简单。

def loss(yhat_all, inputs):
  for prediction, input in zip(yhat_all, inputs):
    correct += is_inside(prediction, input)

  return -abs(correct / len(inputs) - 0.5)

显然,在这种情况下,loss 不是一个有效的张量,我只是用 native python 代码将其写出来来说明问题。鉴于上面的示例,在这种情况下我将如何定义我的 updates 张量?显然我不能使用梯度下降,所以我需要使用不同的优化器,但我也不知如何计算损失,因为我不能再使用正常的损失> 独立运行在每个单独输出上的张量。

最佳答案

首先,您可以做的是在整批而不是单个输入上定义自己的成本函数。坚持你的圆圈示例,你可以这样做:

inside_bool = ( tf.square( X_pred ) + tf.square( Y_pred ) ) < tf.square( r )
inside_float = tf.cast( inside_bool, tf.float32 )
proportion_inside = tf.reduce_mean( inside_float )
loss = -tf.abs( proportion_inside - 0.5 )

另一个问题是这样一个网络的输入是什么。我建议你从随机张量开始。 (基本上,构建一个生成网络。)

如果你的损失函数不可导,训练起来就会很困难。所以我建议用可导出的近似值替换不可导出的部分。最重要的是,从内到外的 bool 值可以是距周长距离的大根(保持符号)。取大根使其接近于一。 (基本上是 0 次幂。)您还可以添加一个正则化器,它喜欢 1 和负 1 左右的值。 (但是,如果这是一个因素,这会破坏坐标的分布。)

tf.abs() 并不是什么大问题,这基本上是 L1 正则化。 因此,一个想法可能是(未经测试的代码):

dist_from_perimeter = ( tf.square( X_pred ) + tf.square( Y_pred ) ) - tf.square( r )
dist_loss = tf.sign( dist_from_perimeter ) * tf.pow( tf.abs( dist_from_perimeter ), 0.2 ) # 0.2 for 5th root
inside = tf.reduce_mean( dist_loss ) # 0-based now!
loss = -tf.abs( inside )

这将迫使所有点都在周边上,但周边的梯度会变得非常大,因此它不太可能停留在那里。它们会由内向外振荡,但一旦比例稳定下来,它们就不会移动太多。 (或者我认为......:))

如果你有圆以外的东西,那么你必须想出一个相当容易计算的距离度量,它会对 X 和 Y 坐标施加接近相等的压力。

希望这一切有所帮助!

为此编写了工作代码,尽管没有调查生成结果的内部结构:

import tensorflow as tf

r = 1.0

rnd = tf.random_uniform( shape = ( 100, 50 ), dtype = tf.float32, minval = 0.0, maxval = 1.0 )

l1 = tf.layers.dense( rnd, 50, activation = tf.nn.relu, kernel_regularizer = tf.nn.l2_loss )
l2 = tf.layers.dense( l1, 50, activation = tf.nn.relu, kernel_regularizer = tf.nn.l2_loss )
l3 = tf.layers.dense( l2, 50, activation = None, kernel_regularizer = tf.nn.l2_loss )
X_pred = tf.layers.dense( l3, 1, activation = None, kernel_regularizer = tf.nn.l2_loss )
Y_pred = tf.layers.dense( l3, 1, activation = None, kernel_regularizer = tf.nn.l2_loss )

dist_from_perimeter = ( tf.square( X_pred ) + tf.square( Y_pred ) ) - tf.square( r )
dist_loss = tf.sign( dist_from_perimeter ) * tf.pow( tf.abs( dist_from_perimeter ), 0.5 ) # 0.5 for square root
inside = tf.reduce_mean( dist_loss ) # 0-based now!
loss = tf.abs( inside )

inside_binary = tf.sign(tf.sign( dist_from_perimeter ) + 1 )
prop = tf.reduce_mean( inside_binary )

global_step = tf.Variable(0, name='global_step', trainable=False)
updates = tf.train.GradientDescentOptimizer( 0.0001 ).minimize( loss )

with tf.Session() as sess:
    init = tf.global_variables_initializer()
    sess.run(init)
    for step in xrange( 100000 ):
        _, loss_value, prop_val = sess.run( [ updates, loss, prop ] )
        if 0 == step % 2000:
            print( "Step {}, loss {:.6f}, proportion inside: {:.4f}". format( step, loss_value, prop_val ) )

输出:

Step 0, loss 0.963431, proportion inside: 0.0000
Step 2000, loss 0.012302, proportion inside: 0.4900
Step 4000, loss 0.044224, proportion inside: 0.5300
Step 6000, loss 0.055603, proportion inside: 0.5400
Step 8000, loss 0.001739, proportion inside: 0.4100
Step 10000, loss 0.136604, proportion inside: 0.5900
Step 12000, loss 0.028738, proportion inside: 0.4600
Step 14000, loss 0.089664, proportion inside: 0.4100
Step 16000, loss 0.035139, proportion inside: 0.4900
Step 18000, loss 0.021432, proportion inside: 0.5100
Step 20000, loss 0.008821, proportion inside: 0.4600
Step 22000, loss 0.079573, proportion inside: 0.5500
Step 24000, loss 0.145942, proportion inside: 0.3700
Step 26000, loss 0.009984, proportion inside: 0.4700
Step 28000, loss 0.010401, proportion inside: 0.4700
Step 30000, loss 0.077145, proportion inside: 0.4000
Step 32000, loss 0.029588, proportion inside: 0.5300
Step 34000, loss 0.032815, proportion inside: 0.5100
Step 36000, loss 0.081417, proportion inside: 0.4000
Step 38000, loss 0.079384, proportion inside: 0.3900
Step 40000, loss 0.040977, proportion inside: 0.5500
Step 42000, loss 0.095768, proportion inside: 0.5900
Step 44000, loss 0.012109, proportion inside: 0.5300
Step 46000, loss 0.064089, proportion inside: 0.4200
Step 48000, loss 0.001401, proportion inside: 0.4700
Step 50000, loss 0.024378, proportion inside: 0.5400
Step 52000, loss 0.037057, proportion inside: 0.4900
Step 54000, loss 0.004553, proportion inside: 0.4800
Step 56000, loss 0.097677, proportion inside: 0.4000
Step 58000, loss 0.060175, proportion inside: 0.5300
Step 60000, loss 0.008686, proportion inside: 0.4800
Step 62000, loss 0.077828, proportion inside: 0.3600
Step 64000, loss 0.000750, proportion inside: 0.4600
Step 66000, loss 0.071392, proportion inside: 0.5700
Step 68000, loss 0.066447, proportion inside: 0.5600
Step 70000, loss 0.057511, proportion inside: 0.5600
Step 72000, loss 0.008800, proportion inside: 0.5400
Step 74000, loss 0.000322, proportion inside: 0.5200
Step 76000, loss 0.002286, proportion inside: 0.4700
Step 78000, loss 0.008778, proportion inside: 0.4900
Step 80000, loss 0.044092, proportion inside: 0.4500
Step 82000, loss 0.018876, proportion inside: 0.4600
Step 84000, loss 0.108120, proportion inside: 0.3500
Step 86000, loss 0.054647, proportion inside: 0.5600
Step 88000, loss 0.024990, proportion inside: 0.4600
Step 90000, loss 0.030924, proportion inside: 0.4700
Step 92000, loss 0.021789, proportion inside: 0.5100
Step 94000, loss 0.066370, proportion inside: 0.5600
Step 96000, loss 0.057060, proportion inside: 0.4100
Step 98000, loss 0.030641, proportion inside: 0.5200

关于python - 当导数未知并且需要一批输出来计算成本时,如何训练模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49888935/

相关文章:

machine-learning - TensorFlow Dataset.shuffle - 大数据集

python - 如何通过dvc run从conda环境执行python

python - 使用正则表达式用逗号或点捕获数字

python - 在 Python 中模拟全功能交换机

python - Keras:val_loss 正在增加,评估损失太高

python-3.x - Keras ImageDataGenerator 弄乱了灰色图像,如何正确增强灰度图像?

python - 无法安装支持 python 的 GDB

python - pyinstaller 不显示图像和图标

tensorflow - ValueError : Tensor Tensor(. ..) 不是该图的元素。使用全局变量 keras 模型时

python - 在 keras 中使用 SparseCategoricalCrossEntropy 损失进行多类分类时,实际的类标签是什么?