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

时间:2015-12-11 17:26:11

标签: python machine-learning neural-network svm tensorflow

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

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

我尝试使用ReLU和Softmax作为激活功能(具有相同的成本函数),但它不起作用。我弄清楚他们为什么不工作。我也尝试过使用Cross Entropy成本函数的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帖子here中读到:

  

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

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


我还使用不同的方法实现了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 那么在这种情况下我可以使用哪种成本函数和激活函数?我如何理解应该使用哪种类型的成本和激活功能?是否有标准的方式或规则,或只是经验?我是否应该以蛮力的方式尝试每一项成本和激活功能?我找到了答案here。但我希望有更详细的解释。

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

2 个答案:

答案 0 :(得分:40)

我会稍微解答您的问题,从更一般的答案开始,然后完成特定实验的那些问题。

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

对于网络的最后一层,激活单元也依赖于任务。对于回归,你需要使用sigmoid或tanh激活,因为你希望结果在0和1之间。对于分类,你只需要一个输出是一个而所有其他的零,但是没有实现精确的可微分方式,所以你需要使用softmax来近似它。

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

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

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

x1

sigmoid(W * (x1 + x2) + B) 只能取三个值中的一个(0,1或2),并且您希望在x1 + x2时返回0,在{{1}时返回1 }}。由于sigmoid函数相当平滑,因此需要非常大的x1 + x2 < 2x1 + x2 = 2值才能使输出接近所需值,但由于学习率较小,因此无法实现那些大价值快。在第一个例子中提高学习率将提高收敛速度。

你的第二个例子收敛得更好,因为W函数擅长使一个输出恰好等于B而其他所有输出都等于softmax。由于这正是你的情况,它确实快速收敛。请注意,1最终也会收敛到良好的值,但它会花费更多的迭代次数(或更高的学习率)。

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

  1. 如果进行分类,请使用0作为最后一层的非线性,sigmoid作为成本函数。

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

  3. 使用ReLU作为图层之间的非一致性。

  4. 使用更好的优化器(tanhsquared error)代替AdamOptimizer,或使用动量来加快收敛速度​​,

答案 1 :(得分:0)

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

如第一个答案所述,激活函数使网络有可能学习非线性函数,并确保响应于输入的微小变化而使输出具有较小的变化。 Sigmoid激活函数在这些假设下效果很好。其他激活函数也可以这样做,但计算开销可能较小,有关完整性,请参见activation functions。但是,通常应避免使用Sigmoid激活函数,因为vanishing gradient problem

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

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

对于分类问题,应始终使用交叉熵代价函数,而不是使用二次代价函数。

请注意,在神经网络中,交叉熵函数的含义不一定与您在概率上遇到的交叉熵函数的含义相同,此处用于比较两个概率分布。在神经网络中,如果您对最终层有唯一的S型输出,并希望将其视为概率分布,则可能是正确的。但这会失去意义,如果您在最后一层有多个乙状结肠神经元。