神经网络的不同代价函数和激活函数的选择

2024-05-14 16:50:37 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

我试过使用ReLU和Softmax作为激活函数(使用相同的成本函数),但它不起作用。我知道他们为什么不工作了。我还尝试了用交叉熵代价函数的乙状结肠函数,它也不起作用。

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 post here上看到:

[Activation Function] selection depends on the problem.

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


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

这里我使用了一个softmax激活函数,交叉熵作为代价函数。乙状结肠功能作为激活功能失败惨重。

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我注意到,要收敛到接近精确的预测,需要多次迭代。我认为收敛率取决于学习率(使用过大的of将错过解决方案)和成本函数(如果我错了,请纠正我)。那么,有没有什么最佳的方法(意思是最快的)或成本函数来收敛到正确的解呢?


Tags: 函数runimport功能numpytfastrain
1条回答
网友
1楼 · 发布于 2024-05-14 16:50:37

我会把你的问题回答得有点乱,先从更一般的答案开始,然后用你特定实验的具体答案结束。

激活函数实际上,不同的激活函数有不同的属性。让我们首先考虑两层神经网络之间的激活函数。激活函数的唯一目的是充当非线性函数。如果你不把一个激活函数放在两层之间,那么两层在一起就不会比一层更好,因为它们的效果仍然只是一个线性变换。很长一段时间以来,人们一直在使用乙状结肠功能和tanh,选择相当武断,乙状结肠更受欢迎,直到最近,当ReLU成为占主导地位的非晶状体。人们之所以在层之间使用ReLU,是因为它不饱和(而且计算速度也更快)。想想乙状结肠的功能图。如果x的绝对值很大,那么sigmoid函数的导数就很小,这意味着当我们向后传播误差时,当我们穿过这些层时,误差的梯度会很快消失。在ReLU中,所有正输入的导数都是1,因此激发神经元的梯度根本不会被激活单元改变,也不会减缓梯度下降。

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

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

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

注意W1W2总是收敛到相同的值,因为(x1x2)的输出应该等于(x2x1)的输出。因此,您要拟合的模型是:

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

x1 + x2只能接受三个值(0、1或2)中的一个,并且您希望在x1 + x2 < 2时返回0,在x1 + x2 = 2时返回1。由于sigmoid函数相当平滑,需要非常大的WB值才能使输出接近所需的值,但是由于学习率很低,它们无法快速地获得这些大值。在第一个例子中提高学习速度将提高收敛速度。

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

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

  1. 如果进行分类,则使用softmax作为最后一层的非线性,使用cross entropy作为成本函数。

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

  3. 使用ReLU作为层之间的非优先权。

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

相关问题 更多 >

    热门问题