深層神經網絡常用方法
深度學習所示深層神經網絡的代名詞,重要特性:多層、非線性。
若只通過線性變換,任意層的神經網絡模型與單層神經網絡模型的表達能力沒有任何區別,這是線性模型的局限性。對於線性可分的問題中,線性模型可解決,但在現實生活中,絕大部分的問題都是無法線性分割的。
感知機:單層神經網絡。不能處理異或問題。
1、激活函數
將每一個神經元(神經網絡的節點)的輸出通過一個非線性函數便可使得整個神經網絡的模型非線性化,這個非線性函數就是激活函數。
常用非線性激活函數:tf.nn.relu、tf.sigmoid、tf.tanh;使用方法,例:
tf.nn.relu(tf.matmul(x,w1)+biases1)
偏置項:可理解為數學中y=ax+b中的b,如果在分類的情況下,兩點剛好在經過原點的直線上,如果沒有偏置項b的話,無法劃分直線將兩個點分開。
2、損失函數
概念:用來評價模型的預測值Y^=f(X)與真實值Y的不一致程度,它是一個非負實值函數。通常使用L(Y,f(x))來表示,損失函數越小,模型的性能就越好。
- 經典損失函數
1.分類問題:將不同的樣本分到事先定義好的類別中。常用交叉熵計算;計算方法:
cross_entropy=-tf.reduce_mean(y_*tf.log(tf.clip_by_value(y,1e-10,1.0))) #y_正確結果,y測試結果;y_*tf.log(tf.clip_by_value(y,1e-10,1.0))得到n*m的二維矩陣,#n為樣例的數量,m為分類的類別數量。由於交叉熵一般與softmax回歸一起使用,所以tf對其進行統一封裝, cross_entropy=tf.nn.softmax_cross_entropy_with_logits(y,y_)
2.回歸問題:對具體數值的預測。常用均方差;計算方法:
mse=tf.reduce_mean(tf.square(y_-y)#y_標準答案,y輸出答案
- 自定義損失函數
除了分類和回歸還有其他問題,所以可以根據具體情況,具體寫對應的損失函數。
3、神經網絡優化算法
目的:使損失函數盡可能的小;
- 反向傳播算法(backpropagtion):給出一個高效的方式在所有參數上使用梯度下降算法;是訓練神經網絡的核心算法,可以根據定義好的損失函數優化神經網絡中參數的取值;
- 梯度下降算法(gradient decent):優化單個參數的取值
當要求損失函數的值為最小值時,可以根據其偏導來判斷其下降方向,梯度便是偏導值;當損失函數未到最小值時,(損失函數-梯度)可變的更小,使用反向傳播算法,可一直將損失函數減去其梯度,知道獲得最小的損失函數;其中由於梯度可能過大,導致錯過最小值,所以可在梯度的值乘以學習率。即:下一個損失函數=損失函數-梯度*學習率(其中梯度便是損失函數的偏導)
註意:梯度下降算法並不可保證優化的函數能得到全局最優解,只有損失函數為凸函數時才可保證;樣例如下圖 -
隨機梯度下降算法(stochastic gradient decent):梯度下降算法中,由於計算的是全部訓練數據上最小化最優,所以損失函數是在所有訓練數據上的損失和,這樣每輪叠代導致時間過長;由此問題引出隨機梯度下降算法,隨機優化某一條訓練數據上的損失函數。該方法雖然達到時間縮短,但是會導致函數無法得到全局最優。下面給出一個損失函數為y=x^2的例子:
-
TRAINING_STEPS=5 x=tf.Variable(tf.constant(5,dtype=tf.float32),name=‘x‘) y=tf.square(x) train_op=tf.train.GradientDescentOptimizer(0.3).minimize(y)#實現梯度下降算法的優化器 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for i in range(TRAINING_STEPS): sess.run(train_op) x_value=sess.run(x) print(i+1, x_value)
-
實際采用方法:梯度與隨機梯度的折中--每次計算一小部分訓練數據的損失函數(batch),該方法可大大減少收斂所需的叠代次數,縮短時間,同時可使收斂到的結果最優。神經網絡的訓練大都遵循以下過程:
-
batch_size=n #讀取一小部分數據作為當前訓練集 x=tf.placeholder(tf.float32,shape=[None,2],name=‘x-input‘) x=tf.placeholder(tf.float32,shape=[None,1],name=‘y-input‘) #定義神經網絡結構和優化算法 loss=... train_step=tf.train.AdamOptimizer(0.001).minimize(loss) with tf.Session() as sess: #參數初始化 ... #叠代更新參數 for i in range(STEPS): #將所有隨機數據重新打亂之後再選取將會獲得更好的優化效果 X=.. Y=... sess.run(train_step,feed_dict={x:X,y:Y})
4、神經網絡的進一步優化
-
學習率的設置
在梯度下降算法中,如果學習率取值過大,可能會出現數值兩邊震蕩的情況,永遠都到達不了極值,而若學習率取值過小,則會大大降低優化的速度,TensorFlow提供了學習率設置的方法--指數衰減法,更改上面的梯度例子如下: -
TRAINING_STEPS=100 global_step=tf.Variable(1)#初始化為0 #def exponential_decay(learning_rate, global_step, decay_steps, decay_rate, # staircase=False, name=None):分別為:初始學習率,經過decay_steps輪計算,學習率乘以decay_rate,staircase為T,學習率階梯狀衰減,否則,連續衰減 LEA_RATE=tf.train.exponential_decay(0.1,global_step,1,0.96,staircase=False)#獲得學習率,指數衰減法,開始較大的衰減率,後來指數變小 x=tf.Variable(tf.constant(5,dtype=tf.float32),name=‘x‘) y=tf.square(x) train_op=tf.train.GradientDescentOptimizer(LEA_RATE).minimize(y,global_step=global_step)#實現梯度下降算法的優化器,global_step會自動加1,可當計數器用 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for i in range(TRAINING_STEPS): sess.run(train_op) LEA_RATE_value=sess.run(LEA_RATE) x_value=sess.run(x) print(i+1, i+1, x_value, LEA_RATE_value,sess.run(global_step))
-
過擬合問題
概念:當一個模型過為復雜之後,它會很好的‘記憶’每一個訓練數據中隨機隨機噪音的部分而忘記了要去‘學習’訓練數據中通用的趨勢。意思就是過擬合數據中的隨機噪音雖然可得到極小的損失函數,但是對位置數據可能無法做出可靠的判讀。 解決方法:正則化--在損失函數中添加刻畫模型復雜程度的指標。使用方法: -
#lambda正則化項的權重,w需要計算正則化損失的參數 loss=之前的損失函數+tf.contrib.layers.l2_regularizer(lambda)(w) print(sess.run(tf.contrib.layers.l1_regularizer(0.5)(w)))#w中每個元素的絕對值之和乘0.5,所以值為5 print(sess.run(tf.contrib.layers.l2_regularizer(0.5)(w)))#w中每個元素的平方和除以2再乘0.5,結果為7.5 print(sess.run(tf.contrib.layers.l1_l2_regularizer(0.5)(w)))#w中的每個元素之和乘0.5+w中每個元素的平方和乘(1-0.5)
當神經網絡的參數增多時,損失函數也將會增多,若將其寫在一個定義中,可讀性會很差,容易出錯,所以在TensorFlow中可以用一下方法:
-
#losses是集合的名字1,mse_loss是加入集合的內容 tf.add_to_collection(‘losses‘, mse_loss) #get_collection返回的是losses集合,add_n是將集合的中值求和 loss = tf.add_n(tf.get_collection(‘losses‘))
5、滑動平均模型
作用:在使用隨機梯度下降算法訓練神經網絡時,可只用該方法在一定程度上進行優化。使用方法如下:
v1=tf.Variable(0,dtype=tf.float32) step=tf.Variable(0,trainable=False) #定義一個滑動平均模型的類,初始化衰減率為0.99,控制衰減率的變量step ema=tf.train.ExponentialMovingAverage(0.99,step) #定義一個更新變量滑動平均的操作,並給定一個列表,每次執行這個操作時,列表更新 maintain_ave_op=ema.apply([v1]) with tf.Session() as sess: init_op=tf.global_variables_initializer() sess.run(init_op) #上面的V1*衰減率+(1-衰減率)*更新變量v1,其中衰減率=min{初始化衰減率,(1+step)/(10+step)} print(sess.run([v1,ema.average(v1)]))#結果:[0,0] sess.run(tf.assign(v1,5)) sess.run(maintain_ave_op) print(sess.run([v1,ema.average(v1)]))#0*min{0.99,((1+step)/(step+10))}+(1-min{0.99,((1+step)/(step+10))})*5 sess.run(tf.assign(step,10000)) sess.run(tf.assign(v1,10)) sess.run(maintain_ave_op) print(sess.run([v1,ema.average(v1)])) sess.run(maintain_ave_op) print(sess.run([v1,ema.average(v1)]))
6、常用方法
- tf.reduce_sum() #和
- tf.greater(v1,v2)#v1和v2的每個對應元素比較,若v1大於v2,則為True否則為False
- tf.where(tf.greater(v1,v2),v1,v2)#根據第一個參數的T和F來選擇v1和v2,若為False則元素選V2中的值,整個函數相當於選取v1和v2中較大的數組成一個舉證
深層神經網絡常用方法