Tensorflow學習:(三)神經網絡優化

1、完善經常使用概念和細節

一、神經元模型:

  以前的神經元結構都採用線上的權重w直接乘以輸入數據x,用數學表達式即,但這樣的結構不夠完善。git

  完善的結構須要加上偏置,並加上激勵函數。用數學公式表示爲:。其中f爲激勵函數。算法

  神經網絡就是由以這樣的神經元爲基本單位構成的。網絡

  

二、激活函數

  引入非線性激活因素,提升模型的表達力。app

  經常使用的激活函數有:框架

  (1)relu函數,用 tf.nn.relu()表示dom

  

  (2)sigmoid函數,用 tf.nn.sigmoid()表示函數

  

  (3)tanh函數,用 tf.nn.tanh()表示學習

  

 

三、神經網絡的複雜度

  能夠用神經網絡的層數和神經網絡待優化的參數個數來表示測試

四、神經網絡的層數

  層數=n個隱藏層 + 1個輸出層  優化

  注意:通常不計入輸入層

五、神經網絡待優化的參數

  神經網絡全部參數w、b的個數

  舉例:下圖爲神經網絡示意圖

     

  在該神經網絡中,包含1個輸入層、1個隱藏層和1個輸出層,該神經網絡的層數爲2層。(不計入輸入層)

  在該神經網絡中,參數的個數是全部參數w的個數加上全部參數b的總數,第一層參數用三行四列的二階張量表示(即12個線上的權重w)再加上4個偏置b;第二層參數是四行兩列的二階張量(即8個線上的權重w)再加上2個偏置b。總參數=3*4+4+4*2+2=26。

 

2、神經網絡優化

      上一節講了神經網絡前向傳播和後向傳播大致框架,這一節討論神經網絡的優化問題。

一、損失函數(loss)

  用來表示預測值(y)與已知答案(y_)的差距。在訓練神經網絡時,經過不斷改變神經網絡中全部參數,使損失函數不斷減少,從而訓練出更高準確率的神經網絡模型。

  經常使用的損失函數有:

  (1)均方偏差(mse)

  以前的隨筆有提到過,所謂均方偏差就是n個樣本的預測值y與已知答案y_之差的平方和,再求平均值

  數學公式爲,在Tensorflow中表示爲 tf.reduce_mean(tf.square(y-y_))

 

  在本篇文章中咱們用一個預測酸奶日銷量 y 的例子來驗證神經網絡優化的效果。x一、x2是影響日銷量的兩個因素。因爲目前沒有數據集,因此利用隨機函數生成x一、x2,製造標準答案y_=x1+x2,爲了更真實,求和後還添加了正負0.05的隨機噪聲。

  選擇mse的損失函數,把自制的數據集喂入神經網絡,構建神經網絡,看訓練出來的參數是否和標準答案y_ = x1+x2

  代碼以下:

 1 import tensorflow as tf
 2 import numpy as np
 3 
 4 BATCH_SIZE = 8
 5 SEED = 23455
 6 
 7 # 構造數據集
 8 rdm = np.random.RandomState(SEED)
 9 X = rdm.rand(32,2)
10 Y_ = [[x1+x2+(rdm.rand()/10.0-0.05)] for (x1, x2) in X]     # rand()會構造0-1的隨機數,/10以後構造0-0.1的隨機數,0~0.1-0.05至關於構造了-0.05~+0.05的隨機數,也就是咱們須要的噪聲
11 
12 #1定義神經網絡的輸入、參數和輸出,定義前向傳播過程。
13 x = tf.placeholder(tf.float32, shape=(None, 2))
14 y_ = tf.placeholder(tf.float32, shape=(None, 1))
15 w1= tf.Variable(tf.random_normal([2, 1], stddev=1, seed=1))
16 y = tf.matmul(x, w1)
17 
18 #2定義損失函數及反向傳播方法。
19 #定義損失函數爲MSE,反向傳播方法爲梯度降低。
20 loss_mse = tf.reduce_mean(tf.square(y_ - y))
21 train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss_mse)
22 
23 #3生成會話,訓練STEPS輪
24 with tf.Session() as sess:
25     init_op = tf.global_variables_initializer()
26     sess.run(init_op)
27     STEPS = 20000
28     for i in range(STEPS):
29         start = (i*BATCH_SIZE) % 32
30         end = (i*BATCH_SIZE) % 32 + BATCH_SIZE
31         sess.run(train_step, feed_dict={x: X[start:end], y_: Y_[start:end]})
32         if i % 500 == 0:
33             print("After %d training steps, w1 is: " % (i))
34             print(sess.run(w1), "\n")
35     print("Final w1 is: \n", sess.run(w1))

        最後的訓練結果爲:

Final w1 is: 
 [[0.98019385]
 [1.0159807 ]]

        顯然w一、w2是趨近於答案1的。這部分的NN和上一篇筆記沒什麼太多不同的地方,只是訓練了兩個權重而已。 

  (2)自定義

        上面的模型中,損失函數採用的是MSE,但根據事實狀況咱們知道,銷量預測問題不是簡單的成本和利潤相等問題。若是預測多了,賣不出去,損失的是成本,反之預測少了,損失的是利潤,現實狀況每每利潤和成本是不相等的。所以,須要使用符合該問題的自定義損失函數。

        自定義損失函數數學公式爲:loss = Σnf(y_,y)

        到本問題中能夠定義成分段函數:

      

        用tf的函數表示爲:loss = tf.reduce_sum(tf.where(tf.greater(y,y_),cost(y-y_),PROFIT(y_-y))) 

        如今假設酸奶成本爲1元,利潤爲9元,顯然但願多預測點,這樣咱們只需改變上面代碼中的損失函數,指定一下cost和profit的值就能夠了。代碼訓練結果爲:

Final w1 is: 
 [[1.0296593]
 [1.0484141]]

        顯然要比單純的y=x1+x2要多預測。

        那麼若是如今假設酸奶成本爲9元,利潤爲1元,又會獲得怎樣的參數呢。訓練結果爲:

Final w1 is: 
 [[0.9600407]
 [0.9733418]]

        顯然比y=x1+x2要少預測。這是符合咱們想法的。

        所以,綜上所述,採用自定義損失函數的方法可能更符合預測結果。

  (3)交叉熵(Cross Entropy)

        表示兩個機率分佈之間的距離,交叉熵越大,說明兩個機率分佈距離越遠,兩個機率分佈越相異;

                                                       交叉熵越小,說明兩個機率分佈距離越近,兩個機率分佈越類似。

        交叉熵計算公式爲:H(y_,y)=-Σy_ * log10 y

        在tf中表示爲:ce = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y,1e-12,1.0)))     # 確保y<1e-12爲1e-2,y>1爲1

        舉一個數學的例子,好比標準答案y_=(1,0)。y1=(0.6,0.4 )  y2=(0.8,0.2),哪一個更接近標準答案呢。

        

         可是爲了可以將輸出變爲知足機率分佈在(0,1)上,我麼們須要使用softmax函數

         

         在tf中,通常讓模型的輸出通過softmax函數,進而得到輸出分類的機率分佈,再與標準答案對比,求得交叉熵,獲得損失函數,而且有專門的函數。

         ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))

         cem = tf.reduce_mean(ce)

         這也就代替了ce = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y,1e-12,1.0)))    這句函數

二、學習率

        上一篇筆記中有討論過學習率的問題,獲得的大體結論是:學習率過大,會致使待優化參數在最小值附近波動,不收斂;學習率太小,致使訓練次數增大,收斂緩慢

        在這裏咱們須要展開討論有關學習率的問題。

(1)隨機梯度降低算法更新參數

        首先隨機梯度降低方法更新參數的公式爲:wn+1=wn - learning_rate * ▽  (▽表示損失函數關於參數的偏導)

        若是參數初值爲5,學習率爲0.2,則參數更新狀況爲:

        

         再舉個例子,若是損失函數爲loss=(w+1)2,畫出函數圖像爲:

       能看的出來,若是損失函數使用隨機梯度降低優化器,loss的最小值應該是0,此時參數w爲-1 。

(2)指數衰減學習率

        指數衰減學習率就是指學習率會隨着訓練輪數變化而實現動態更新,它再也不是一個定值。

        計算公式爲:learning_rate = learning_rate_base *   learning_rate_decay global_step/learning_rate_step

        這裏面的概念:

        learning_rate_base:學習率基數,通常認爲和學習率初始值相等

        learning_rate_decay:學習率衰減率,範圍是(0,1)

        global_step:運行了幾輪batch_size

        learning_rate_step:多少論更新一次學習率=總樣本數/batch_size

        在tensorflow中,咱們用這樣的函數來表示:

        首先要有一個值指向當前的訓練輪數,這是一個不可訓練參數,做爲一個「線索」

        global_step = tf.Variable(0,trainable=False)

        再來就是一個學習率的函數:

        learning_rate = tf.train.exponential_decay(

                                  LEARNING_RATE_BASE,

                                  global_step,

                                  LEARNING_RATE_STEP,

                                  LEARNING_RATE_DECAY,

                                  staircase=True/False)    # 其餘的參數已經在上面提到過,最後一個參數staircase,當設置爲True時,表示global_step/learning_rate_step取整數,學習率階梯型衰減;若爲False,學習率是一條平滑降低的曲線。

          在代碼中展現指數衰減學習率:

#設損失函數 loss=(w+1)^2, 令w初值是常數10。反向傳播就是求最優w,即求最小loss對應的w值
#使用指數衰減的學習率,在迭代初期獲得較高的降低速度,能夠在較小的訓練輪數下取得更有收斂度。
import tensorflow as tf

LEARNING_RATE_BASE = 0.1 #最初學習率
LEARNING_RATE_DECAY = 0.99 #學習率衰減率
LEARNING_RATE_STEP = 1  #喂入多少輪BATCH_SIZE後,更新一次學習率,通常設爲:總樣本數/BATCH_SIZE

#運行了幾輪BATCH_SIZE的計數器,初值給0, 設爲不被訓練
global_step = tf.Variable(0, trainable=False)
#定義指數降低學習率
learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE, global_step, LEARNING_RATE_STEP, LEARNING_RATE_DECAY, staircase=True)
#定義待優化參數,初值給10
w = tf.Variable(tf.constant(10, dtype=tf.float32))
#定義損失函數loss
loss = tf.square(w+1)
#定義反向傳播方法
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)
#生成會話,訓練40輪
with tf.Session() as sess:
    init_op=tf.global_variables_initializer()
    sess.run(init_op)
    for i in range(40):
        sess.run(train_step)
        learning_rate_val = sess.run(learning_rate)
        global_step_val = sess.run(global_step)    # global_step也要放在會話中運行,要否則怎麼更新
        w_val = sess.run(w)
        loss_val = sess.run(loss)
        print("After %s steps: global_step is %f, w is %f, learning rate is %f, loss is %f" % (i, global_step_val, w_val, learning_rate_val, loss_val))

           運行顯示結果爲

After 0 steps: global_step is 1.000000, w is 7.800000, learning rate is 0.099000, loss is 77.440002
After 1 steps: global_step is 2.000000, w is 6.057600, learning rate is 0.098010, loss is 49.809719
After 2 steps: global_step is 3.000000, w is 4.674170, learning rate is 0.097030, loss is 32.196201
After 3 steps: global_step is 4.000000, w is 3.573041, learning rate is 0.096060, loss is 20.912704
After 4 steps: global_step is 5.000000, w is 2.694472, learning rate is 0.095099, loss is 13.649124
After 5 steps: global_step is 6.000000, w is 1.991791, learning rate is 0.094148, loss is 8.950812
After 6 steps: global_step is 7.000000, w is 1.428448, learning rate is 0.093207, loss is 5.897362
After 7 steps: global_step is 8.000000, w is 0.975754, learning rate is 0.092274, loss is 3.903603
After 8 steps: global_step is 9.000000, w is 0.611131, learning rate is 0.091352, loss is 2.595742
After 9 steps: global_step is 10.000000, w is 0.316771, learning rate is 0.090438, loss is 1.733887
After 10 steps: global_step is 11.000000, w is 0.078598, learning rate is 0.089534, loss is 1.163375
After 11 steps: global_step is 12.000000, w is -0.114544, learning rate is 0.088638, loss is 0.784033
After 12 steps: global_step is 13.000000, w is -0.271515, learning rate is 0.087752, loss is 0.530691
After 13 steps: global_step is 14.000000, w is -0.399367, learning rate is 0.086875, loss is 0.360760
After 14 steps: global_step is 15.000000, w is -0.503726, learning rate is 0.086006, loss is 0.246287
After 15 steps: global_step is 16.000000, w is -0.589091, learning rate is 0.085146, loss is 0.168846
After 16 steps: global_step is 17.000000, w is -0.659066, learning rate is 0.084294, loss is 0.116236
After 17 steps: global_step is 18.000000, w is -0.716543, learning rate is 0.083451, loss is 0.080348
After 18 steps: global_step is 19.000000, w is -0.763853, learning rate is 0.082617, loss is 0.055765
After 19 steps: global_step is 20.000000, w is -0.802872, learning rate is 0.081791, loss is 0.038859
After 20 steps: global_step is 21.000000, w is -0.835119, learning rate is 0.080973, loss is 0.027186
After 21 steps: global_step is 22.000000, w is -0.861821, learning rate is 0.080163, loss is 0.019094
After 22 steps: global_step is 23.000000, w is -0.883974, learning rate is 0.079361, loss is 0.013462
After 23 steps: global_step is 24.000000, w is -0.902390, learning rate is 0.078568, loss is 0.009528
After 24 steps: global_step is 25.000000, w is -0.917728, learning rate is 0.077782, loss is 0.006769
After 25 steps: global_step is 26.000000, w is -0.930527, learning rate is 0.077004, loss is 0.004827
After 26 steps: global_step is 27.000000, w is -0.941226, learning rate is 0.076234, loss is 0.003454
After 27 steps: global_step is 28.000000, w is -0.950187, learning rate is 0.075472, loss is 0.002481
After 28 steps: global_step is 29.000000, w is -0.957706, learning rate is 0.074717, loss is 0.001789
After 29 steps: global_step is 30.000000, w is -0.964026, learning rate is 0.073970, loss is 0.001294
After 30 steps: global_step is 31.000000, w is -0.969348, learning rate is 0.073230, loss is 0.000940
After 31 steps: global_step is 32.000000, w is -0.973838, learning rate is 0.072498, loss is 0.000684
After 32 steps: global_step is 33.000000, w is -0.977631, learning rate is 0.071773, loss is 0.000500
After 33 steps: global_step is 34.000000, w is -0.980842, learning rate is 0.071055, loss is 0.000367
After 34 steps: global_step is 35.000000, w is -0.983565, learning rate is 0.070345, loss is 0.000270
After 35 steps: global_step is 36.000000, w is -0.985877, learning rate is 0.069641, loss is 0.000199
After 36 steps: global_step is 37.000000, w is -0.987844, learning rate is 0.068945, loss is 0.000148
After 37 steps: global_step is 38.000000, w is -0.989520, learning rate is 0.068255, loss is 0.000110
After 38 steps: global_step is 39.000000, w is -0.990951, learning rate is 0.067573, loss is 0.000082
After 39 steps: global_step is 40.000000, w is -0.992174, learning rate is 0.066897, loss is 0.000061

          根據損失函數的公式,咱們知道理論上w在-1時,loss取最小值爲0.顯然結果是符合理論的。

          這裏留下一個待解決的問題,改變指數衰減學習率公式中的幾個參數, 會對訓練次數,權重更新,學習率,損失值分別有什麼影響?      

 

三、滑動平均(影子)

        滑動平均值(也有人稱爲影子值),記錄了一段時間內模型中全部的參數w和b各自的平均值。使用影子值能夠加強模型的泛化能力。就感受是給參數加了影子,參數變化,影子緩慢跟隨。

        影子 = 衰減率*影子 + (1-衰減率)*參數

        其中,影子初值 = 參數初值;衰減率 = min{moving_average_decay , (1+輪數)/(10+輪數) }

        例如,moving_average_decay賦值爲0.99,參數w設置爲0,影子值爲0

          (1)    開始時,訓練輪數爲0,參數更新爲1,則w的影子值爲:

                  影子 = min(0.99,1/10)*0+(1-min(0.99,1/10))*1=0.9

          (2)    當訓練輪數爲100時,參數w更新爲10,則w的影子值爲:

                  影子 = min(0.99,101/110)*0.9+(1– min(0.99,101/110)*10 = 0.826+0.818=1.644

         (3)    當訓練輪數爲100時,參數w更新爲1.644,則w的影子值爲:

                  影子 = min(0.99,101/110)*1.644+(1– min(0.99,101/110)*10 = 2.328

         (4)    當訓練輪數爲100時,參數w更新爲2.328,則w的影子值爲:

                  影子 = 2.956

        用tensorflow函數能夠表示爲如下內容:(相關注釋在完整代碼中寫)

        ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)   

        ema_op = ema.apply(tf.trainable_variables()) 

        with tf.control_dependencies([train_step, ema_op]):
                train_op = tf.no_op(name='train')

        因此上面的例子用完整的滑動平均代碼爲:

import tensorflow as tf

# 1. 定義變量及滑動平均類
# 定義一個32位浮點變量,初始值爲0.0  這個代碼就是不斷更新w1參數,優化w1參數,滑動平均作了個w1的影子
w1 = tf.Variable(0, dtype=tf.float32)
# 定義num_updates(NN的迭代輪數),初始值爲0,不可被優化(訓練),這個參數不訓練
global_step = tf.Variable(0, trainable=False)
# 實例化滑動平均類,給衰減率爲0.99,通常賦值爲接近1的值
MOVING_AVERAGE_DECAY = 0.99
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)

# ema.apply後的括號裏是更新列表,每次運行sess.run(ema_op)時,對更新列表中的元素求滑動平均值。
# ema.apply()函數實現對括號內參數求滑動平均
# 在實際應用中會使用tf.trainable_variables()自動將全部待訓練的參數彙總爲列表
# ema_op = ema.apply([w1])
ema_op = ema.apply(tf.trainable_variables())

# 2. 查看不一樣迭代中變量取值的變化。
with tf.Session() as sess:
    # 初始化
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    # 用ema.average(w1)獲取w1滑動平均值 (要運行多個節點,做爲列表中的元素列出,寫在sess.run中)
    # 打印出當前參數w1和w1滑動平均值
    print("current global_step:", sess.run(global_step))
    print("current w1", sess.run([w1, ema.average(w1)]))

    # 參數w1的值賦爲1
    sess.run(tf.assign(w1, 1))
    sess.run(ema_op)
    print("current global_step:", sess.run(global_step))
    print("current w1", sess.run([w1, ema.average(w1)]))

    # 更新global_step和w1的值,模擬出輪數爲100時,參數w1變爲10, 如下代碼global_step保持爲100,每次執行滑動平均操做,影子值會更新
    sess.run(tf.assign(global_step, 100))
    sess.run(tf.assign(w1, 10))
    sess.run(ema_op)
    print("current global_step:", sess.run(global_step))
    print("current w1:", sess.run([w1, ema.average(w1)]))

    # 每次sess.run會更新一次w1的滑動平均值
    sess.run(ema_op)
    print("current global_step:", sess.run(global_step))
    print("current w1:", sess.run([w1, ema.average(w1)]))

    sess.run(ema_op)
    print("current global_step:", sess.run(global_step))
    print("current w1:", sess.run([w1, ema.average(w1)]))

           屢次執行訓練輪數爲100的ema_op,觀察影子值,運行結果爲:

current global_step: 0
current w1 [0.0, 0.0]
current global_step: 0
current w1 [1.0, 0.9]
current global_step: 100
current w1: [10.0, 1.6445453]
current global_step: 100
current w1: [10.0, 2.3281732]
current global_step: 100
current w1: [10.0, 2.955868]
current global_step: 100
current w1: [10.0, 3.532206]
current global_step: 100
current w1: [10.0, 4.061389]
current global_step: 100
current w1: [10.0, 4.547275]
current global_step: 100
current w1: [10.0, 4.9934072]

            可以看得出來,訓練輪數不變的時候,影子值一直在逼近於10,說明影子值隨參數的改變而改變。有一個「影子追隨「的感受。

四、正則化

           正則化是解決神經網絡過擬合的有效方法。天然要先提一下過擬合問題。

           過擬合:神經網絡模型在訓練集上準確率高,在測試集進行預測或分類時準確率吧較低,說明模型的泛化能力差

           正則化:在損失函數中給每一個參數w加上權重,引入模型複雜度指標,從而抑制模型噪聲,減少過擬合。

           根據正則化的定義,咱們能夠得出新的損失函數值:、

           loss = loss(y-y_) + regularizer* loss(w)               第一項是預測結果與標準答案的差距,第二項是正則化計算結果

           正則化有兩種計算方法:

           (1)L1正則化:lossL1 = ∑|wi|  ,  tf函數表示爲:loss(w) = tf.contrib.layers.l1_regularizer(regularizer)(w)

           (2)L2正則化:lossL2 = ∑|wi|2 ,  tf函數表示爲:loss(w) = tf.contrib.layers.l2_regularizer(regularizer)(w)

           正則化實現用tensorflow能夠表示爲:

           tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w)

           loss = cem + tf.add_n(tf.get_collection('losses'))        # cem即交叉熵損失函數的值

           舉例:

                  隨機生成300個符合正態分佈的點(x0,x1),當x02+x12<2 時,y_=1,標註爲紅色,x02+x12≥2時,y_=0,標註爲藍色。使用matplotlib模塊分別畫出無正則化和有正則化的擬合曲線

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

BATCH_SIZE = 30
seed = 2
# 基於seed產生隨機數
rdm = np.random.RandomState(seed)
# 隨機數返回300行2列的矩陣,表示300組座標點(x0,x1)做爲輸入數據集
# randn()函數是從正態分佈中返回樣本值,rand()函數是從(0,1)中返回樣本值
X = rdm.randn(300, 2)
# 從X這個300行2列的矩陣中取出一行,判斷若是兩個座標的平方和小於2,給Y賦值1,其他賦值0
# 做爲輸入數據集的標籤(正確答案)
Y_ = [int(x0 * x0 + x1 * x1 < 2) for (x0, x1) in X]
# 遍歷Y中的每一個元素,1賦值'red'其他賦值'blue',這樣可視化顯示時人能夠直觀區分
Y_c = [['red' if y else 'blue'] for y in Y_]
# 對數據集X和標籤Y進行shape整理,第一個元素爲-1表示,隨第二個參數計算獲得,第二個元素表示多少列,把X整理爲n行2列,把Y整理爲n行1列
X = np.vstack(X).reshape(-1, 2)
Y_ = np.vstack(Y_).reshape(-1, 1)
print(X)
print(Y_)
print(Y_c)
# 用plt.scatter畫出數據集X各行中第0列元素和第1列元素的點即各行的(x0,x1),用各行Y_c對應的值表示顏色(c是color的縮寫)
plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(Y_c))
plt.show()


# 定義神經網絡的輸入、參數和輸出,定義前向傳播過程
def get_weight(shape, regularizer):
    w = tf.Variable(tf.random_normal(shape), dtype=tf.float32)
    tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))
    return w


def get_bias(shape):
    b = tf.Variable(tf.constant(0.01, shape=shape))
    return b


x = tf.placeholder(tf.float32, shape=(None, 2))
y_ = tf.placeholder(tf.float32, shape=(None, 1))

w1 = get_weight([2, 11], 0.01)
b1 = get_bias([11])
y1 = tf.nn.relu(tf.matmul(x, w1) + b1)

w2 = get_weight([11, 1], 0.01)
b2 = get_bias([1])
y = tf.matmul(y1, w2) + b2

# 定義損失函數
loss_mse = tf.reduce_mean(tf.square(y - y_))
loss_total = loss_mse + tf.add_n(tf.get_collection('losses'))

# 定義反向傳播方法:不含正則化
train_step = tf.train.AdamOptimizer(0.0001).minimize(loss_mse)

with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    STEPS = 40000
    for i in range(STEPS):
        start = (i * BATCH_SIZE) % 300
        end = start + BATCH_SIZE
        sess.run(train_step, feed_dict={x: X[start:end], y_: Y_[start:end]})
        if i % 2000 == 0:
            loss_mse_v = sess.run(loss_mse, feed_dict={x: X, y_: Y_})
            print("After %d steps, loss is: %f" % (i, loss_mse_v))
    # xx在-3到3之間以步長爲0.01,yy在-3到3之間以步長0.01,生成二維網格座標點
    xx, yy = np.mgrid[-3:3:.01, -3:3:.01]
    # 將xx , yy拉直,併合併成一個2列的矩陣,獲得一個網格座標點的集合
    grid = np.c_[xx.ravel(), yy.ravel()]
    # 將網格座標點喂入神經網絡 ,probs爲輸出
    probs = sess.run(y, feed_dict={x: grid})
    # probs的shape調整成xx的樣子
    probs = probs.reshape(xx.shape)
    print("w1:\n", sess.run(w1))
    print("b1:\n", sess.run(b1))
    print("w2:\n", sess.run(w2))
    print("b2:\n", sess.run(b2))

plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(Y_c))
plt.contour(xx, yy, probs, levels=[.5])
plt.show()

# 定義反向傳播方法:包含正則化
train_step = tf.train.AdamOptimizer(0.0001).minimize(loss_total)

with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    STEPS = 40000
    for i in range(STEPS):
        start = (i * BATCH_SIZE) % 300
        end = start + BATCH_SIZE
        sess.run(train_step, feed_dict={x: X[start:end], y_: Y_[start:end]})
        if i % 2000 == 0:
            loss_v = sess.run(loss_total, feed_dict={x: X, y_: Y_})   # 與未正則化相比,這個地方的loss_mse換成了loss_total
            print("After %d steps, loss is: %f" % (i, loss_v))

    xx, yy = np.mgrid[-3:3:.01, -3:3:.01]
    grid = np.c_[xx.ravel(), yy.ravel()]
    probs = sess.run(y, feed_dict={x: grid})
    probs = probs.reshape(xx.shape)
    print("w1:\n", sess.run(w1))
    print("b1:\n", sess.run(b1))
    print("w2:\n", sess.run(w2))
    print("b2:\n", sess.run(b2))

plt.scatter(X[:, 0], X[:, 1], c=np.squeeze(Y_c))
plt.contour(xx, yy, probs, levels=[.5])
plt.show()

    分別畫出有無正則化的圖

  

    右圖加入了正則化,顯然正則化模型的擬合曲線平滑,泛化能力強一點。

    留下待解決問題,更改正則化參數,觀察擬合變化?   

   

    本人初學者,有任何錯誤歡迎指出,謝謝。

相關文章
相關標籤/搜索