2015-12-11 49 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,或使用勢頭較快的收斂,