深度學習框架TensorFlow學習與應用(四)——擬合問題、優化器

一、擬合

1)迴歸問題:

這裏寫圖片描述

過擬合儘量去通過每一個樣本點,誤差爲零。假如有一個新的樣本點:

這裏寫圖片描述

會發現過擬合的偏差會很大。

2)分類問題:

這裏寫圖片描述

同樣的當得到新的樣本點後,過擬合的錯誤率可能會提高。

3)防止過擬合:

1.增加數據集

2.正則化方法,在代價函數後面加一個正則項

這裏寫圖片描述

3.Dropout:訓練時,在每一次迭代時使得一些神經元工作,一些神經元不工作。測試時再使用所有的神經元。

這裏寫圖片描述

4)使用Dropout避免過擬合:

例如:創建一個神經網絡,2000個神經元的隱藏層,後面又是2000個神經元的隱藏層,之後是1000個神經元的隱藏層,最後是10個輸出層。用來進行前部分的MINST數據集分類訓練。

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
#載入數據集
mnist=input_data.read_data_sets("D:\BaiDu\MNIST_data",one_hot=True)

#每個批次的大小
batch_size=100
#計算一共有多少個批次
n_batch=mnist.train.num_examples//batch_size

#定義placeholder
x=tf.placeholder(tf.float32,[None,784])
y=tf.placeholder(tf.float32,[None,10])#標籤
keep_prob=tf.placeholder(tf.float32)

#創建一個的神經網絡,2000個神經元的隱藏層,後面又是2000個神經元的隱藏層,只有是1000個神經元的隱藏層,最後是10個輸出層
W1=tf.Variable(tf.truncated_normal([784,2000],stddev=0.1))
b1=tf.Variable(tf.zeros([2000])+0.1)
L1=tf.nn.tanh(tf.matmul(x,W1)+b1)
L1_drop=tf.nn.dropout(L1,keep_prob)

W2=tf.Variable(tf.truncated_normal([2000,2000],stddev=0.1))
b2=tf.Variable(tf.zeros([2000])+0.1)
L2=tf.nn.tanh(tf.matmul(L1_drop,W2)+b2)
L2_drop=tf.nn.dropout(L2,keep_prob)

W3=tf.Variable(tf.truncated_normal([2000,1000],stddev=0.1))
b3=tf.Variable(tf.zeros([1000])+0.1)
L3=tf.nn.tanh(tf.matmul(L2_drop,W3)+b3)
L3_drop=tf.nn.dropout(L3,keep_prob)

W4=tf.Variable(tf.truncated_normal([1000,10],stddev=0.1))
b4=tf.Variable(tf.zeros([10])+0.1)

prediction=tf.nn.softmax(tf.matmul(L3_drop,W4)+b4)

#二次代價函數
#loss=tf.reduce_mean(tf.square(y-prediction))
loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction))
#使用梯度下降法
train_step=tf.train.GradientDescentOptimizer(0.2).minimize(loss)

#初始化變量
init=tf.global_variables_initializer()

#結果存放在一個布爾型列表中
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))#比較兩個參數大小,相同爲true。argmax返回一維張量中最大的值所在的位置
#求準確率
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#將布爾型轉化爲32位浮點型,再求一個平均值。true變爲1.0,false變爲0。

with tf.Session() as sess:
    sess.run(init)
    for epoch in range(31):
        for batch in range(n_batch):
            batch_xs,batch_ys=mnist.train.next_batch(batch_size)
            sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys,keep_prob:1.0})#keep_prob爲1.0表示所有的神經元都是工作的

        test_acc=sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels,keep_prob:1.0})#測試數據算出來的準確率
        train_acc=sess.run(accuracy,feed_dict={x:mnist.train.images,y:mnist.train.labels,keep_prob:1.0})#訓練集算出的準確率
        print("Iter "+str(epoch)+",Testing Accuracy "+str(test_acc)+",Training Accuracy "+str(train_acc))

由於神經元較多,運行會很慢很慢。。。。。
結果是:

Iter 0,Testing Accuracy 0.9469,Training Accuracy 0.956455
Iter 1,Testing Accuracy 0.9567,Training Accuracy 0.974745
Iter 2,Testing Accuracy 0.9617,Training Accuracy 0.982473
Iter 3,Testing Accuracy 0.9632,Training Accuracy 0.986273
Iter 4,Testing Accuracy 0.9654,Training Accuracy 0.988509
Iter 5,Testing Accuracy 0.9679,Training Accuracy 0.989818
Iter 6,Testing Accuracy 0.9676,Training Accuracy 0.991
Iter 7,Testing Accuracy 0.9675,Training Accuracy 0.991655
Iter 8,Testing Accuracy 0.9681,Training Accuracy 0.992164
Iter 9,Testing Accuracy 0.9688,Training Accuracy 0.992509
Iter 10,Testing Accuracy 0.968,Training Accuracy 0.993018
Iter 11,Testing Accuracy 0.9692,Training Accuracy 0.993255
Iter 12,Testing Accuracy 0.968,Training Accuracy 0.993527
Iter 13,Testing Accuracy 0.9688,Training Accuracy 0.993745
Iter 14,Testing Accuracy 0.9699,Training Accuracy 0.994018
Iter 15,Testing Accuracy 0.9697,Training Accuracy 0.994109
Iter 16,Testing Accuracy 0.9693,Training Accuracy 0.9942
Iter 17,Testing Accuracy 0.9695,Training Accuracy 0.994345
Iter 18,Testing Accuracy 0.9692,Training Accuracy 0.9944
Iter 19,Testing Accuracy 0.9696,Training Accuracy 0.994436
Iter 20,Testing Accuracy 0.9704,Training Accuracy 0.994527
Iter 21,Testing Accuracy 0.9704,Training Accuracy 0.994582
Iter 22,Testing Accuracy 0.97,Training Accuracy 0.994727
Iter 23,Testing Accuracy 0.9698,Training Accuracy 0.994764
Iter 24,Testing Accuracy 0.97,Training Accuracy 0.994855
Iter 25,Testing Accuracy 0.9701,Training Accuracy 0.994891
Iter 26,Testing Accuracy 0.9705,Training Accuracy 0.995036
Iter 27,Testing Accuracy 0.9707,Training Accuracy 0.995145
Iter 28,Testing Accuracy 0.9707,Training Accuracy 0.995273
Iter 29,Testing Accuracy 0.9705,Training Accuracy 0.995364
Iter 30,Testing Accuracy 0.9705,Training Accuracy 0.9954

之後使用Dropout:

sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys,keep_prob:0.7})

得到:

Iter 0,Testing Accuracy 0.9179,Training Accuracy 0.912891
Iter 1,Testing Accuracy 0.9328,Training Accuracy 0.9284
Iter 2,Testing Accuracy 0.9344,Training Accuracy 0.935255
Iter 3,Testing Accuracy 0.9409,Training Accuracy 0.940891
Iter 4,Testing Accuracy 0.9439,Training Accuracy 0.944909
Iter 5,Testing Accuracy 0.9471,Training Accuracy 0.949964
Iter 6,Testing Accuracy 0.9499,Training Accuracy 0.952018
Iter 7,Testing Accuracy 0.9502,Training Accuracy 0.953527
Iter 8,Testing Accuracy 0.9548,Training Accuracy 0.957055
Iter 9,Testing Accuracy 0.9563,Training Accuracy 0.958418
Iter 10,Testing Accuracy 0.9566,Training Accuracy 0.959309
Iter 11,Testing Accuracy 0.958,Training Accuracy 0.961364
Iter 12,Testing Accuracy 0.9593,Training Accuracy 0.962527
Iter 13,Testing Accuracy 0.96,Training Accuracy 0.964055
Iter 14,Testing Accuracy 0.9607,Training Accuracy 0.965745
Iter 15,Testing Accuracy 0.9622,Training Accuracy 0.966818
Iter 16,Testing Accuracy 0.9624,Training Accuracy 0.967655
Iter 17,Testing Accuracy 0.9641,Training Accuracy 0.968564
Iter 18,Testing Accuracy 0.964,Training Accuracy 0.969564
Iter 19,Testing Accuracy 0.9633,Training Accuracy 0.969945
Iter 20,Testing Accuracy 0.9661,Training Accuracy 0.971182
Iter 21,Testing Accuracy 0.9664,Training Accuracy 0.972127
Iter 22,Testing Accuracy 0.9682,Training Accuracy 0.972709
Iter 23,Testing Accuracy 0.968,Training Accuracy 0.973145
Iter 24,Testing Accuracy 0.9662,Training Accuracy 0.974345
Iter 25,Testing Accuracy 0.9695,Training Accuracy 0.974436
Iter 26,Testing Accuracy 0.9689,Training Accuracy 0.975164
Iter 27,Testing Accuracy 0.9689,Training Accuracy 0.9756
Iter 28,Testing Accuracy 0.9699,Training Accuracy 0.976091
Iter 29,Testing Accuracy 0.9696,Training Accuracy 0.976545
Iter 30,Testing Accuracy 0.9719,Training Accuracy 0.977236

可以看出:

使用Dropout後,模型的收斂速度變慢,準確率上升的速度慢。那麼爲什麼還要使用Dropout呢?通過對比兩次的測試準確率和訓練準確率,可以看到,沒有使用Dropout的方法測試準確率和訓練準確率相差比較大,這就是過擬合的問題,使用了Dropout就可以進行優化。另外,本部分提供的例子並沒有很好的體現出Dropout的優勢,兩者的準確率的對比不明顯,如果使用大型卷積神經網絡進行樣本訓練,結果會更明顯。


二、優化器

tf.train.GradientDescentOptimizer
tf.train.AdadeltaOptimizer
tf.train.AdagradOptimizer
tf.train.AdagradDAOptimizer
tf.train.MomentumOptimizer
tf.train.AdamOptimizer
tf.train.FtrlOptimizer
tf.train.ProximalGradientDescentOptimizer
tf.train.ProximalAdagradOptimizer
tf.train.RMSPropOptimizer

各種優化器對比:
標準梯度下降法:標準梯度下降先計算所有樣本彙總誤差,然後根據總誤差來更新權值。
隨機梯度下降法:隨機梯度下降隨機抽取一個樣本來計算誤差,然後更新權值。
批量梯度下降法:批量梯度下降算是一種折中的方案,從總樣本中選取一個批次(比如一共有10000個樣本,隨機選取100個樣本作爲一個batch),然後計算這個batch的總誤差,根據總誤差來更新權值。

梯度下降法運行的方式

接下來具體講一下幾個優化器:

W:要訓練的參數

J(W):代價函數

這裏寫圖片描述:代價函數的梯度

這裏寫圖片描述:學習率

1)SGD(隨機梯度下降法):

這裏寫圖片描述

2)Momentum:

這裏寫圖片描述

當前權值的改變會受到上一次權值改變的影響,類似於小球向下滾動的時候帶上了慣性。這樣可以加快小球的向下的速度。

3)NAG(Nesterov accelerated gradient):

這裏寫圖片描述

NAG在TF中跟Momentum合併在同一個函數tf.train.MomentumOptimizer中,可以通過參數配置啓用。在Momentum中小球會盲目跟從下坡的梯度,容易發生錯誤,所以我們需要一個更聰明的小球,這個小球提前知道它要去哪裏,它還要知道走到坡底的時候速度慢下來而不是又衝上另一個坡。我們可以提前計算下一個位置的梯度,然後使用到當前位置。

4)Adagrad:

這裏寫圖片描述

它是基於SGD的一種算法,它的核心思想是對比比較常見的數據給予它比較小的學習率去調整參數,對於比較罕見的數據給予它較大的學習率去調整參數。它很適合應用於數據稀疏的數據集(比如一個圖片的數據集,有10000張狗的照片,10000張貓的照片,只有100張大象的照片)。
Adagrad主要的優勢在於不需要人爲的調節學習率,它可以自動調節。它的缺點在於,隨着迭代次數的增多,學習率也會越來越低,最終會趨向於0。

5)RMSprop:
RMS(Root Mean Square)是均方根的縮寫。

這裏寫圖片描述

RMSprop借鑑了一些Adagrad的思想,不過這裏RMSprop只用到了前t-1次梯度平方的平均值加上當前梯度的平方的和的開平方作爲學習率的分母。這樣RMSprop不會出現學習率越來越低的問題,而且也能自己調節學習率,並且可以有一個比較好的效果。

6)Adadelta:

這裏寫圖片描述

使用Adadelta我們甚至不需要設置一個默認的學習率,在Adadelta不需要使用學習率也可以達到一個很好的效果。

7)Adam:

這裏寫圖片描述

就像Adadelta和RMSprop一樣Adam會存儲之前衰減的平方梯度,同時它也會保存之前衰減的梯度。經過一些處理之後再使用類似Adadelta和RMSprop的方式更新參數。

8)舉例:

更改學習率、優化器種類、迭代次數、神經元等對比一下。

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
#載入數據集
mnist=input_data.read_data_sets("D:\BaiDu\MNIST_data",one_hot=True)

#每個批次的大小
batch_size=100
#計算一共有多少個批次
n_batch=mnist.train.num_examples//batch_size

#定義兩個placeholder
x=tf.placeholder(tf.float32,[None,784])
y=tf.placeholder(tf.float32,[None,10])#標籤

#創建一個簡單的神經網絡
W=tf.Variable(tf.zeros([784,10]))
b=tf.Variable(tf.zeros([10]))
prediction=tf.nn.softmax(tf.matmul(x,W)+b)

#二次代價函數
loss=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y,logits=prediction))
#使用優化器
#train_step=tf.train.GradientDescentOptimizer(0.2).minimize(loss)
train_step=tf.train.AdamOptimizer(0.001).minimize(loss)
#初始化變量
init=tf.global_variables_initializer()

#結果存放在一個布爾型列表中
correct_prediction=tf.equal(tf.argmax(y,1),tf.argmax(prediction,1))#比較兩個參數大小,相同爲true。argmax返回一維張量中最大的值所在的位置
#求準確率
accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#將布爾型轉化爲32位浮點型,再求一個平均值。true變爲1.0,false變爲0。

with tf.Session() as sess:
    sess.run(init)
    for epoch in range(21):
        for batch in range(n_batch):
            batch_xs,batch_ys=mnist.train.next_batch(batch_size)
            sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys})

        acc=sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels})
        print("Iter "+str(epoch)+",Testing Accuracy "+str(acc))

結果:

Iter 0,Testing Accuracy 0.8988
Iter 1,Testing Accuracy 0.9125
Iter 2,Testing Accuracy 0.916
Iter 3,Testing Accuracy 0.919
Iter 4,Testing Accuracy 0.9221
Iter 5,Testing Accuracy 0.9227
Iter 6,Testing Accuracy 0.9271
Iter 7,Testing Accuracy 0.9269
Iter 8,Testing Accuracy 0.9274
Iter 9,Testing Accuracy 0.9282
Iter 10,Testing Accuracy 0.929
Iter 11,Testing Accuracy 0.9291
Iter 12,Testing Accuracy 0.9304
Iter 13,Testing Accuracy 0.9288
Iter 14,Testing Accuracy 0.9302
Iter 15,Testing Accuracy 0.9304
Iter 16,Testing Accuracy 0.93
Iter 17,Testing Accuracy 0.9315
Iter 18,Testing Accuracy 0.9311
Iter 19,Testing Accuracy 0.9321
Iter 20,Testing Accuracy 0.9311

可以看出,同之前使用梯度下降法相比,使用Adam的收斂性和準確率更好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章