一、準備數據集,提取特徵,做爲輸入餵給神經網絡
二、搭建神經網絡結構,從輸入到輸出
三、大量特徵數據餵給 NN,迭代優化 NN 參數
四、使用訓練好的模型預測和分類 算法
前向傳播就是搭建模型的計算過程,能夠針對一組輸入給出相應的輸出。數組
舉例:假如生產一批零件, 體積爲 x1, 重量爲 x2, 體積和重量就是咱們選擇的特徵,把它們喂入神經網絡, 當體積和重量這組數據走過神經網絡後會獲得一個輸出。
網絡
假如輸入的特徵值是:體積 0.7 ,重量 0.5 ,下圖是搭建的神經網絡框架圖
框架
由搭建的神經網絡可得, 隱藏層節點 a11=x1* w11+x2*w21=0.14+0.15=0.29, 同理算得節點 a12=0.32, a13=0.38,最終計算獲得輸出層 Y=-0.015, 這便實現了前向傳播過程。
dom
再來推導圖中的代碼實現過程。函數
第一層:學習
(1)x是輸入爲1*2的矩陣:用x表示輸入,是一個1行2列的矩陣,表示一次輸入一組特徵,這組特徵包含了體積和重量兩個元素。優化
(2)W前節點編號,後節點編號(層數)爲待優化的參數:前面兩個節點,後面三個節點。因此w應該是個兩行三列的矩陣。表示爲spa
注意:神經網絡共有幾層是指計算層, 輸入不算做計算層,因此 上圖中a 爲第一層網絡,a 是一個一行三列矩陣。3d
第二層:
(1)參數要知足前面三個節點,後面一個節點,因此W(2)是三行一列矩陣。表示爲
咱們把每層輸入乘以線上的權重w,這樣就能夠用矩陣乘法輸出y了。
下面討論這其中的細節問題。
一、神經網絡的參數
顯然權重w是很重要的參數,咱們剛開始設置w變量的時候,通常會先隨機生成這些參數,固然確定是變量形式。
因此這裏介紹一下 tf 經常使用的生成隨機數/數組的函數:
(1)tf.random_normal() 生成正態分佈隨機數
w=tf.Variable(tf.random_normal([2,3],stddev=2, mean=0, seed=1)) # 表示生成正態分佈隨機數,形狀兩行三列,標準差是2,均值是0,隨機種子是1
(2)tf.truncated_normal() 生成去掉過大偏離點的正態分佈隨機數,也就是若是隨機生成的數據偏離平均值超過兩個標準差,這個數據將從新生成
w=tf.Variable(tf.Truncated_normal([2,3],stddev=2, mean=0, seed=1))
(3)tf.random_uniform() 生成均勻分佈隨機數
w=tf.Variable(tf.random_uniform([2,3],minval=0,maxval=1,dtype=tf.float32,seed=1)) # 表示從一個均勻分佈[minval maxval)中隨機採樣,產生的數是均勻分佈的,注意定義域是左閉右開,即包含 minval,不包含 maxval。
以上這些函數,若是沒有特殊要求標準差、 均值、 隨機種子是能夠不寫的。看具體使用狀況。
(4)其它函數:tf.zeros 表示生成全 0 數組
tf.ones 表示生成全 1 數組
tf.fill 表示生成全定值數組
tf.constant 表示生成直接給定值的數組
tf.zeros([3,2],int32) # 表示生成[[0,0],[0,0],[0,0]] tf.ones([3,2],int32) # 表示生成[[1,1],[1,1],[1,1] tf.fill([3,2],6) # 表示生成[[6,6],[6,6],[6,6]] tf.constant([3,2,1]) # 表示生成[3,2,1]
二、placeholder佔位,輸入多組數據
不作贅述,直接在代碼裏面註釋這樣的操做
細節討論完,下面就是用代碼實現前向傳播
1 # (1) 用placeholder 實現輸入定義(sess.run 中喂入一組數據)的狀況,特徵有體積和重量,數據爲體積 0.七、重量 0.5 2 3 import tensorflow as tf 4 5 x = tf.placeholder(tf.float32,shape=(1,2)) # placeholder佔位,首先要指定數據類型,而後能夠指定形狀,由於咱們如今只須要佔一組數據,且有兩個特徵值,因此shape爲(1,2) 6 w1 = tf.Variable(tf.random_normal([2,3],stddev=1,seed=1)) # 生成權重 7 w2 = tf.Variable(tf.random_normal([3,1],stddev=1,seed=1)) 8 9 a = tf.matmul(x,w1) # 矩陣乘法op 10 y = tf.matmul(a,w2) 11 12 with tf.Session() as sess: 13 init = tf.global_variables_initializer() # 初始化之後就放在這裏,不容易忘記 14 sess.run(init) 15 print("y is",sess.run(y,feed_dict={x:[[0.7,0.5]]})) # 以字典形式給feed_dict賦值,賦的是一個一行兩列的矩陣,注意張量的階數。這裏只執行了y的op,由於執行了y也就執行了a這個op 16
運行顯示結果爲:
y is: [[ 3.0904665]]
# (2) 用 placeholder 實現輸入定義(sess.run 中喂入多組數據)的狀況 import tensorflow as tf #定義輸入和參數 x=tf.placeholder(tf.float32,shape=(None,2)) # 這裏佔位由於不知道要輸入多少組數據,但仍是兩個特徵,因此shape=(None,2),注意大小寫 w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1)) w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1)) #定義前向傳播過程 a=tf.matmul(x,w1) y=tf.matmul(a,w2) #用會話計算結果 with tf.Session() as sess: init_op=tf.global_variables_initializer() sess.run(init_op) print("y is:",sess.run(y,feed_dict={x:[[0.7,0.5], [0.2,0.3], [0.3,0.4], [0.4,0.5]]})) # 輸入數據,4行2列的矩陣
運行顯示結果爲:
y is: [[ 3.0904665 ] [ 1.2236414 ] [ 1.72707319] [ 2.23050475]]
以上就是最簡單的神經網絡前向傳播過程。
反向傳播:訓練模型參數,以減少loss值爲目的,使用優化方法,使得 NN 模型在訓練數據上的損失函數最小。
損失函數(loss): 計算獲得的預測值 y 與已知答案 y_ 的差距。損失函數的計算有不少方法,均方偏差( MSE) 是比較經常使用的方法之一。
均方偏差 MSE: 求前向傳播計算結果與已知答案之差的平方再求平均。
數學公式爲:
用tensorflow函數表示爲:loss_mse = tf.reduce_mean(tf.square(y_ - y))
反向傳播訓練方法: 以減少 loss 值爲優化目標。
通常有梯度降低、 momentum 優化器、 adam 優化器等優化方法。這三種優化方法用 tensorflow 的函數能夠表示爲:
train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
train_step=tf.train.MomentumOptimizer(learning_rate, momentum).minimize(loss)
train_step=tf.train.AdamOptimizer(learning_rate).minimize(loss)
三種優化方法的區別:
學習率:決定每次參數更新的幅度。
優化器中都須要一個叫作學習率的參數,使用時,若是學習率選擇過大會出現震蕩不收斂的狀況(步子跨的太大),若是學習率選擇太小,會出現收斂速度慢的狀況。咱們能夠選個比較小的值填入,好比 0.0一、0.001。
Python代碼實現加上反向傳播的NN:
隨機產生 32 組生產出的零件的體積和重量,訓練 3000 輪,每 500 輪輸出一次損失函數。
1 import tensorflow as tf 2 import numpy as np 3 4 BATCH_SIZE = 8 # 一次輸入網絡的數據,稱爲batch。一次不能喂太多數據 5 SEED = 23455 # 產生統一的隨機數 6 7 # 基於seed產生隨機數,這是根據隨機種子產生隨機數的一種經常使用方法,要熟練運用 8 rdm = np.random.RandomState(SEED) 9 # 隨機數返回32行2列的矩陣 表示32組 體積和重量 做爲輸入數據集。由於這裏沒用真實的數據集,因此這樣操做。 10 X = rdm.rand(32, 2) 11 # 從X這個32行2列的矩陣中 取出一行 判斷若是和小於1 給Y賦值1 若是和不小於1 給Y賦值0 (這裏只是人爲的定義),做爲輸入數據集的標籤(正確答案) 12 Y_ = [[int(x0 + x1 < 1)] for (x0, x1) in X] 13 print("X:\n", X) 14 print("Y_:\n",Y_) 15 16 17 # 1定義神經網絡的輸入、參數和輸出,定義前向傳播過程。 18 x = tf.placeholder(tf.float32, shape=(None, 2)) 19 y_ = tf.placeholder(tf.float32, shape=(None, 1)) 20 21 w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) 22 w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1)) 23 24 a = tf.matmul(x, w1) 25 y = tf.matmul(a, w2) 26 27 # 2定義損失函數及反向傳播方法。 28 loss = tf.reduce_mean(tf.square(y - y_)) 29 train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss) # 三種優化方法選擇一個就能夠 30 # train_step = tf.train.MomentumOptimizer(0.001,0.9).minimize(loss_mse) 31 # train_step = tf.train.AdamOptimizer(0.001).minimize(loss_mse) 32 33 # 3生成會話,訓練STEPS輪 34 with tf.Session() as sess: 35 init = tf.global_variables_initializer() 36 sess.run(init) 37 # 輸出目前(未經訓練)的參數取值。 38 print("w1:\n", sess.run(w1)) 39 print("w2:\n", sess.run(w2)) 40 print("\n") 41 42 # 訓練模型。 43 STEPS = 3000 44 for i in range(STEPS): #0-2999 45 start = (i * BATCH_SIZE) % 32 #i=0,start=0,end=8;i=1,start=8,end=16;i=2,start=16,end=24;i=3,start=24,end=32;i=4,start=0,end=8。也就是說每次訓練8組數據,一共訓練3000次。 46 end = start + BATCH_SIZE 47 sess.run(train_step, feed_dict={x: X[start:end], y_: Y_[start:end]}) 48 if i % 500 == 0: 49 total_loss = sess.run(loss, feed_dict={x: X, y_: Y_}) 50 print("After %d training step(s), loss on all data is %g"%(i,total_loss)) 51 52 # 輸出訓練後的參數取值。 53 print("\n") 54 print("w1:\n", sess.run(w1)) 55 print("w2:\n", sess.run(w2))
運行顯示結果爲
X: [[ 0.83494319 0.11482951] [ 0.66899751 0.46594987] [ 0.60181666 0.58838408] [ 0.31836656 0.20502072] [ 0.87043944 0.02679395] [ 0.41539811 0.43938369] [ 0.68635684 0.24833404] [ 0.97315228 0.68541849] [ 0.03081617 0.89479913] [ 0.24665715 0.28584862] [ 0.31375667 0.47718349] [ 0.56689254 0.77079148] [ 0.7321604 0.35828963] [ 0.15724842 0.94294584] [ 0.34933722 0.84634483] [ 0.50304053 0.81299619] [ 0.23869886 0.9895604 ] [ 0.4636501 0.32531094] [ 0.36510487 0.97365522] [ 0.73350238 0.83833013] [ 0.61810158 0.12580353] [ 0.59274817 0.18779828] [ 0.87150299 0.34679501] [ 0.25883219 0.50002932] [ 0.75690948 0.83429824] [ 0.29316649 0.05646578] [ 0.10409134 0.88235166] [ 0.06727785 0.57784761] [ 0.38492705 0.48384792] [ 0.69234428 0.19687348] [ 0.42783492 0.73416985] [ 0.09696069 0.04883936]] Y_: [[1], [0], [0], [1], [1], [1], [1], [0], [1], [1], [1], [0], [0], [0], [0], [0], [0], [1], [0], [0], [1], [1], [0], [1], [0], [1], [1], [1], [1], [1], [0], [1]] w1: [[-0.81131822 1.48459876 0.06532937] [-2.4427042 0.0992484 0.59122431]] w2: [[-0.81131822] [ 1.48459876] [ 0.06532937]] After 0 training step(s), loss_mse on all data is 5.13118 After 500 training step(s), loss_mse on all data is 0.429111 After 1000 training step(s), loss_mse on all data is 0.409789 After 1500 training step(s), loss_mse on all data is 0.399923 After 2000 training step(s), loss_mse on all data is 0.394146 After 2500 training step(s), loss_mse on all data is 0.390597 w1: [[-0.70006633 0.9136318 0.08953571] [-2.3402493 -0.14641267 0.58823055]] w2: [[-0.06024267] [ 0.91956186] [-0.0682071 ]]
由神經網絡的實現結果,咱們能夠看出,總共訓練3000輪,每輪從X的數據集和Y的標籤中抽取相對應的從start開始到end結束個特徵值和標籤,喂入神經網絡,用sess.run求出loss,每500輪打印一次loss值。通過3000輪後,咱們打印出最終訓練好的參數w一、w2。
針對上面的代碼,作出以下思考。首先最終的目的是使得loss值減少,那麼:
一、若是增大訓練次數,loss會不會繼續減少?若是減少,會不會一直在減少?
增大了訓練次數後,發現隨着次數增長,loss值確實會慢慢減少,可是減少的幅度愈來愈小,直至訓練了16500次以後,loss值保持不變。
after 3000 training step(s) ,loss on all data is 0.388336 after 3500 training step(s) ,loss on all data is 0.386855 after 4000 training step(s) ,loss on all data is 0.385863 after 4500 training step(s) ,loss on all data is 0.385186 after 5000 training step(s) ,loss on all data is 0.384719 after 5500 training step(s) ,loss on all data is 0.384391 after 6000 training step(s) ,loss on all data is 0.38416 after 6500 training step(s) ,loss on all data is 0.383995 after 7000 training step(s) ,loss on all data is 0.383877 after 7500 training step(s) ,loss on all data is 0.383791 after 8000 training step(s) ,loss on all data is 0.383729 after 8500 training step(s) ,loss on all data is 0.383684 after 9000 training step(s) ,loss on all data is 0.383652 after 9500 training step(s) ,loss on all data is 0.383628 after 10000 training step(s) ,loss on all data is 0.38361 after 10500 training step(s) ,loss on all data is 0.383597 after 11000 training step(s) ,loss on all data is 0.383587 after 11500 training step(s) ,loss on all data is 0.38358 after 12000 training step(s) ,loss on all data is 0.383575 after 12500 training step(s) ,loss on all data is 0.383571 after 13000 training step(s) ,loss on all data is 0.383568 after 13500 training step(s) ,loss on all data is 0.383566 after 14000 training step(s) ,loss on all data is 0.383565 after 14500 training step(s) ,loss on all data is 0.383564 after 15000 training step(s) ,loss on all data is 0.383563 after 15500 training step(s) ,loss on all data is 0.383562 after 16000 training step(s) ,loss on all data is 0.383562 after 16500 training step(s) ,loss on all data is 0.383561 after 17000 training step(s) ,loss on all data is 0.383561 after 17500 training step(s) ,loss on all data is 0.383561 after 18000 training step(s) ,loss on all data is 0.383561
二、既然上面的問題是這樣,那麼隨機梯度降低算法的學習率對loss減少有着怎樣的影響?
我調整了學習率和訓練次數,獲得這樣的規律,目前的學習率爲0.001
當學習率爲0.003時,5500次訓練,loss就能夠降低到0.383561
當學習率爲0.005時,3500次訓練,loss只能降低到0.383562
當學習率爲0.007時,2500次訓練,loss只能降低到0.383563
當學習率爲0.01時,2500次訓練,loss只能降低到0.383566
由此能夠看出,當學習率增大時,優勢是訓練次數較少,缺點是可能參數在最小值附近波動,不收斂
當學習率爲0.0007時,23500次訓練,loss能降低到0.383561
當學習率爲0.0003時,50000次訓練,loss才能降低到0.383563
顯然,學習率太小的缺點就是訓練次數太多
三、若是不用隨機梯度降低算法,換用其餘的優化器,會產生什麼樣的變化?
(1)換用Momentum優化器,能夠發現,當學習率也爲0.001時,2000次訓練,loss值就降低到了0.383561。
after 0 training step(s) ,loss on all data is 5.13118 after 500 training step(s) ,loss on all data is 0.384391 after 1000 training step(s) ,loss on all data is 0.383592 after 1500 training step(s) ,loss on all data is 0.383562 after 2000 training step(s) ,loss on all data is 0.383561 after 2500 training step(s) ,loss on all data is 0.383561 after 3000 training step(s) ,loss on all data is 0.383561
一樣的增長和減少學習率,獲得的現象和上文分析的是同樣的。可是當學習率較大時,出現了loss值增大的現象
因此暫時能夠得出這樣的結論:Momentum優化器的優勢是能夠快速收斂到最小值,相同的學習率,須要的訓練次數較少
(2)換用Adam優化器,能夠發現,當學習率也爲0.001時,3500次訓練,loss值降低到了0.383561
變化學習率,現象和Momentum差很少,也出現loss值增大的現象。
after 0 training step(s) ,loss on all data is 5.20999 after 500 training step(s) ,loss on all data is 0.617026 after 1000 training step(s) ,loss on all data is 0.392288 after 1500 training step(s) ,loss on all data is 0.386432 after 2000 training step(s) ,loss on all data is 0.384254 after 2500 training step(s) ,loss on all data is 0.383676 after 3000 training step(s) ,loss on all data is 0.383573 after 3500 training step(s) ,loss on all data is 0.383561 after 4000 training step(s) ,loss on all data is 0.383561 after 4500 training step(s) ,loss on all data is 0.383561
四、更改batch的值,會不會對結果有影響?
我把batch改成12,訓練了35000次,最後loss值是降低到了0.384388和0.384447,也就是說未收斂
改成15,訓練了50000次,最後仍是降低到某幾個固定的值,仍然未收斂
能夠看得出,batch值增大時,訓練次數增大,不收斂的可能性也增長。
將batch改成7和5,訓練了35000次,也是不收斂。
這地方就很納悶了,爲啥8效果是最好的呢,這地方留點問題吧。之後再來看看
注:以上問題的結論只是暫時性的總結,因爲目前水平有限,不知道結論正確與否。
經過以上的內容,咱們能夠梳理一下搭建簡單神經網絡的步驟:
(1)導入模塊,生成模擬數據集
import
常量定義
生成數據集
(2)前向傳播:定義輸入、參數和輸出
x= y_=
w1= w2=
a= y=
(3)後向傳播:定義損失函數、反向傳播方法
loss=
train_step=
(4)生成會話,訓練STEPS輪
with tf.Session as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
STEPS =
for i in range(STEPS):
start =
end =
sess.run(train_step, feed_dict={ })
以上是搭建簡單神經網絡的筆記
本人初學者,有任何錯誤歡迎指出,謝謝。