最近我开始玩弄神经网络。我试图用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将错过解决方案)和成本函数(如果我错了,请纠正我)。那么,有没有什么最佳的方法(意思是最快的)或成本函数来收敛到正确的解呢?
我会把你的问题回答得有点乱,先从更一般的答案开始,然后用你特定实验的具体答案结束。
激活函数实际上,不同的激活函数有不同的属性。让我们首先考虑两层神经网络之间的激活函数。激活函数的唯一目的是充当非线性函数。如果你不把一个激活函数放在两层之间,那么两层在一起就不会比一层更好,因为它们的效果仍然只是一个线性变换。很长一段时间以来,人们一直在使用乙状结肠功能和tanh,选择相当武断,乙状结肠更受欢迎,直到最近,当ReLU成为占主导地位的非晶状体。人们之所以在层之间使用ReLU,是因为它不饱和(而且计算速度也更快)。想想乙状结肠的功能图。如果
x
的绝对值很大,那么sigmoid函数的导数就很小,这意味着当我们向后传播误差时,当我们穿过这些层时,误差的梯度会很快消失。在ReLU中,所有正输入的导数都是1
,因此激发神经元的梯度根本不会被激活单元改变,也不会减缓梯度下降。对于网络的最后一层,激活单元也取决于任务。对于回归,您将希望使用乙状结肠或tanh激活,因为您希望结果介于0和1之间。对于分类,您只希望一个输出为1,而所有其他输出为0,但是没有可微的方法可以精确地实现这一点,因此您需要使用softmax来近似它。
您的示例。现在让我们看看你的例子。第一个示例尝试以以下形式计算
AND
的输出:注意
W1
和W2
总是收敛到相同的值,因为(x1
,x2
)的输出应该等于(x2
,x1
)的输出。因此,您要拟合的模型是:x1 + x2
只能接受三个值(0、1或2)中的一个,并且您希望在x1 + x2 < 2
时返回0
,在x1 + x2 = 2
时返回1。由于sigmoid函数相当平滑,需要非常大的W
和B
值才能使输出接近所需的值,但是由于学习率很低,它们无法快速地获得这些大值。在第一个例子中提高学习速度将提高收敛速度。您的第二个示例收敛得更好,因为
softmax
函数擅长使精确的一个输出等于1
,而所有其他输出等于0
。因为这正是你的情况,它确实很快收敛。注意sigmoid
最终也会收敛到好的值,但它需要更多的迭代(或更高的学习率)。使用什么。最后一个问题是,如何选择使用哪些激活和成本函数。这些建议适用于大多数情况:
如果进行分类,则使用
softmax
作为最后一层的非线性,使用cross entropy
作为成本函数。如果进行回归,则使用
sigmoid
或tanh
作为最后一层的非线性,使用squared error
作为成本函数。使用ReLU作为层之间的非优先权。
使用更好的优化器(
AdamOptimizer
,AdagradOptimizer
)而不是GradientDescentOptimizer
,或者使用动量更快地收敛,相关问题 更多 >
编程相关推荐