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

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

首先我尝试以这种方式实现它。正如你所见,这是一个糟糕的实现,但我认为它至少在某种程度上完成了任务。所以,我只尝试了真实输出,没有使用独热编码的真实输出。对于激活函数,我使用了Sigmoid函数,对于成本函数,我使用了平方误差成本函数(我想是这么叫的,如果我错了请纠正我)。

我尝试使用ReLU和Softmax作为激活函数(使用相同的成本函数),但它不起作用。我弄清楚了它们为什么不起作用。我还尝试了Sigmoid函数与交叉熵成本函数的组合,它也不起作用。

import tensorflow as tfimport numpytrain_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))/4optimizer = 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门,输出为独热编码的真实值。正如你所见,train_Y中的[1,0]表示第0个索引为1,所以答案是0。我希望你能理解。

在这里,我使用了Softmax激活函数,并以交叉熵作为成本函数。使用Sigmoid函数作为激活函数的效果非常差。

import tensorflow as tfimport numpytrain_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,其余都为0,但没有可微分的方式能精确实现这一点,所以你会想要使用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的情况下返回1。由于Sigmoid函数相当平滑,需要非常大的WB值才能使输出接近期望值,但由于学习率较小,它们无法快速达到那些大的值。在你的第一个例子中增加学习率将提高收敛速度。

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

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

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

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

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

  4. 使用更好的优化器(如AdamOptimizerAdagradOptimizer)代替GradientDescentOptimizer,或使用动量来加快收敛速度,

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注