繁体   English   中英

从神经网络的不同成本函数和激活函数中选择

[英]Choosing from different cost function and activation function of a neural network

最近我开始玩弄神经网络。 我试图用 Tensorflow 实现一个AND门。 我无法理解何时使用不同的成本和激活函数。 这是一个基本的神经网络,只有输入和输出层,没有隐藏层。

首先,我尝试以这种方式实现它。 正如你所看到的,这是一个糟糕的实现,但我认为它至少在某种程度上完成了工作。 所以,我只尝试了真正的输出,没有人尝试真正的热输出。 对于激活函数,我使用了 sigmoid 函数,而对于成本函数,我使用了平方误差成本函数(我认为它叫那个,如果我错了,请纠正我)。

我试过使用 ReLU 和 Softmax 作为激活函数(具有相同的成本函数),但它不起作用。 我想出了为什么它们不起作用。 我还尝试了具有交叉熵成本函数的 sigmoid 函数,它也不起作用。

import tensorflow as tf
import numpy

train_X = numpy.asarray([[0,0],[0,1],[1,0],[1,1]])
train_Y = numpy.asarray([[0],[0],[0],[1]])

x = tf.placeholder("float",[None, 2])
y = tf.placeholder("float",[None, 1])

W = tf.Variable(tf.zeros([2, 1]))
b = tf.Variable(tf.zeros([1, 1]))

activation = tf.nn.sigmoid(tf.matmul(x, W)+b)
cost = tf.reduce_sum(tf.square(activation - y))/4
optimizer = tf.train.GradientDescentOptimizer(.1).minimize(cost)

init = tf.initialize_all_variables()

with tf.Session() as sess:
    sess.run(init)
    for i in range(5000):
        train_data = sess.run(optimizer, feed_dict={x: train_X, y: train_Y})

    result = sess.run(activation, feed_dict={x:train_X})
    print(result)

5000 次迭代后:

[[ 0.0031316 ]
[ 0.12012422]
[ 0.12012422]
[ 0.85576665]]

问题 1 - 是否有任何其他激活函数和成本函数可以为上述网络工作(学习),而无需更改参数(即不更改 W、x、b)。

问题2 -我从StackOverflow的阅读后在这里

[激活功能] 选择取决于问题。

那么没有可以在任何地方使用的成本函数吗? 我的意思是没有可用于任何神经网络的标准成本函数。 对? 请纠正我。


我还用不同的方法实现了AND门,输出为 one-hot true。 如你所见, train_Y [1,0]表示第 0 个索引为 1,所以答案为 0,希望你明白。

这里我使用了一个 softmax 激活函数,以交叉熵作为代价函数。 Sigmoid 函数作为激活函数惨遭失败。

import tensorflow as tf
import numpy

train_X = numpy.asarray([[0,0],[0,1],[1,0],[1,1]])
train_Y = numpy.asarray([[1,0],[1,0],[1,0],[0,1]])

x = tf.placeholder("float",[None, 2])
y = tf.placeholder("float",[None, 2])

W = tf.Variable(tf.zeros([2, 2]))
b = tf.Variable(tf.zeros([2]))

activation = tf.nn.softmax(tf.matmul(x, W)+b)

cost = -tf.reduce_sum(y*tf.log(activation))

optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(cost)

init = tf.initialize_all_variables()

with tf.Session() as sess:
    sess.run(init)
    for i in range(5000):
        train_data = sess.run(optimizer, feed_dict={x: train_X, y: train_Y})

    result = sess.run(activation, feed_dict={x:train_X})
    print(result)

经过 5000 次迭代

[[  1.00000000e+00   1.41971401e-09]
 [  9.98996437e-01   1.00352429e-03]
 [  9.98996437e-01   1.00352429e-03]
 [  1.40495342e-03   9.98595059e-01]]

问题 3那么在这种情况下,我可以使用什么成本函数和激活函数? 我如何理解我应该使用哪种类型的成本和激活函数? 有没有标准的方法或规则,或者只是经验? 我是否应该以蛮力的方式尝试每个成本和激活函数? 我在这里找到了答案。 但我希望有更详细的解释。

问题 4我注意到需要多次迭代才能收敛到接近准确的预测。 我认为收敛率取决于学习率(使用太大会错过解决方案)和成本函数(如果我错了,请纠正我)。 那么,是否有任何最佳方式(意味着最快)或成本函数可以收敛到正确的解决方案?

我会有点乱回答你的问题,从更一般的答案开始,最后是那些特定于你的特定实验的答案。

激活函数不同的激活函数,其实有不同的属性。 让我们首先考虑神经网络两层之间的激活函数。 激活函数的唯一目的是作为非线性。 如果你不在两层之间放置一个激活函数,那么两层放在一起不会比一层更好,因为它们的效果仍然只是一个线性变换。 很长一段时间里,人们都在使用 sigmoid 函数和 tanh,选择几乎是任意的,sigmoid 更受欢迎,直到最近,当 ReLU 成为主要的非宽容性时。 人们在层之间使用 ReLU 的原因是它是非饱和的(并且计算速度也更快)。 考虑 sigmoid 函数的图形。 如果x的绝对值很大,那么 sigmoid 函数的导数就很小,这意味着当我们向后传播误差时,误差的梯度会随着我们返回层而很快消失。 对于 ReLU,所有正输入的导数都是1 ,因此激活单元根本不会改变那些被激发的神经元的梯度,也不会减慢梯度下降的速度。

对于网络的最后一层,激活单元也取决于任务。 对于回归,您需要使用 sigmoid 或 tanh 激活,因为您希望结果介于 0 和 1 之间。对于分类,您只希望输出之一为 1,其他所有输出为零,但没有可微分的方法来实现正是如此,因此您将需要使用 softmax 来近似它。

你的例子 现在让我们看看你的例子。 您的第一个示例尝试以以下形式计算AND的输出:

sigmoid(W1 * x1 + W2 * x2 + B)

请注意, W1W2将始终收敛到相同的值,因为 ( x1 , x2 ) 的输出应该等于 ( x2 , x1 ) 的输出。 因此,您拟合的模型是:

sigmoid(W * (x1 + x2) + B)

x1 + x2只能取三个值(0、1 或 2)之一,并且您希望在x1 + x2 < 2的情况下返回0 ,在x1 + x2 = 2的情况下返回x1 + x2 = 2 由于 sigmoid 函数相当平滑,因此需要非常大的WB值才能使输出接近所需的值,但由于学习率很小,它们无法快速达到这些大值。 在第一个示例中提高学习率将提高收敛速度。

您的第二个示例收敛得更好,因为softmax函数擅长精确地使一个输出等于1而所有其他输出等于0 由于这正是您的情况,因此它确实会很快收敛。 请注意, sigmoid最终也会收敛到良好的值,但需要更多的迭代(或更高的学习率)。

使用什么 现在到最后一个问题,如何选择要使用的激活和成本函数。 这些建议适用于大多数情况:

  1. 如果做分类,最后一层的非线性使用softmaxcross entropy作为代价函数。

  2. 如果您进行回归,请使用sigmoidtanh作为最后一层的非线性和squared error作为成本函数。

  3. 使用 ReLU 作为层之间的非线性。

  4. 使用更好的优化器( AdamOptimizerAdagradOptimizer )而不是GradientDescentOptimizer ,或者使用动量来加快收敛速度​​,

成本函数和激活函数在神经网络的学习阶段起着重要作用。

正如在第一个答案中所解释的那样,激活函数使网络有可能学习非线性函数,此外还可以确保响应于输入的微小变化而输出的微小变化。 sigmoid 激活函数适用于这些假设。 其他激活函数执行相同的操作,但计算成本可能更低,请参阅激活函数以了解完整性。 但是,通常应该避免 Sigmoid 激活函数,因为梯度消失问题

成本函数 C 对神经网络的学习速度起着至关重要的作用。 基于梯度的神经网络通过最小化成本函数以迭代方式学习,因此计算成本函数的梯度,并根据它改变权重。 如果使用二次成本函数,这意味着它的梯度相对于权重,与激活函数的一阶导数成正比。 现在,如果使用 sigmoid 激活函数,这意味着当输出接近 1 时,导数非常小,正如您从图像中看到的那样,因此神经元学习缓慢。 S形函数

交叉熵代价函数可以避免这个问题。 即使您使用的是 sigmoid 函数,使用交叉熵函数作为成本函数,也意味着它相对于权重的导数与激活函数的一阶导数并不成正比,就像二次函数发生的那样,而是它们与输出误差成正比。 这意味着当预测输出离目标很远时,您的网络学习得更快,反之亦然。

对于分类问题,应始终使用交叉熵成本函数,而不是使用二次成本函数,如上所述。

请注意,在神经网络中,交叉熵函数与您在概率中遇到的交叉熵函数的含义并不总是相同,它用于比较两个概率分布。 在神经网络中,如果您对最后一层有唯一的 sigmoid 输出并且想将其视为概率分布,则这可能是正确的。 但是这意味着如果你在最后一层有多个 sigmoid 神经元。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM