2015-12-11 50 views
20

最近我开始玩弄神经网络。我试图用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的后here阅读:

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

因此,有可以在任何地方使用任何费用的功能呢?我的意思是没有标准成本函数,可用于任何神经网络。对?请在此纠正我。


我还执行了AND栅极与不同的方法,将具有输出作为独热真。正如你可以看到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我注意到需要很多迭代才能收敛到接近准确的预测。我认为,收敛速度取决于学习速度(使用过大的将错过解决方案)和成本函数(纠正我,如果我错了)。那么,是否有任何最佳途径(意思是最快)或成本函数来收敛到正确的解决方案?

回答

30

我会回答你的问题有点乱序,从更普遍的答案,并与特定的那些您的具体实验完成。

激活功能不同的激活功能,事实上,确实有不同的性质。我们首先考虑一个神经网络两层之间的激活函数。激活函数的唯一目的是作为非线性。如果你没有在两层之间放置激活函数,那么两层一起效果不会好于一层,因为它们的效果仍然只是线性变换。很久以前,人们使用sigmoid函数和tanh,几乎任意选择,而sigmoid更受欢迎,直到最近,当ReLU成为主导nonleniarity时。人们在层之间使用ReLU的原因是因为它不饱和(并且计算速度也更快)。考虑一个sigmoid函数的图形。如果x绝对值大,那么双曲线函数的导数小,这意味着,我们向后传播的错误,错误的梯度就会消失得很快,因为我们回去通过各层。与RELU衍生物是1对所有正输入端,所以该烧制这些神经元的梯度将不会被激活单元在所有被改变,也不会减慢梯度下降。

对于网络激活单元还取决于任务的最后一层。对于回归,您将希望使用sigmoid或tanh激活,因为您希望结果在0和1之间。对于分类,您只需要其中一个输出为一个和所有其他零,但是没有可区分的方式来实现正是这一点,所以你会想用softmax来近似它。

你的榜样。现在让我们看看你的例子。你的第一个例子试图计算的AND输出的格式如下:

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

注意W1W2总会收敛到相同的值,因为输出(x1x2)应该等于输出(x2,x1)。因此,您所安装的型号是:

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

x1 + x2只能取三个值之一(0,1或2),并要为将案件退回0x1 + x2 < 2和1的情况下x1 + x2 = 2 。由于sigmoid函数非常平滑,因此需要使用非常大的值WB才能使输出接近所需的值,但由于学习速率较小,因此无法快速达到这些较大的值。在第一个例子中提高学习速度会增加收敛速度。

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

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

  1. 如果你这样做分类,使用softmax最后一层的非线性和cross entropy作为成本函数。

  2. 如果你这样做回归,用sigmoidtanh最后一层的非线性和squared error的成本函数。

  3. 使用ReLU作为图层之间的非平行性。

  4. 用更好的优化(AdamOptimizerAdagradOptimizer),而不是GradientDescentOptimizer,或使用势头较快的收敛,