目標(biāo):搭建神經(jīng)網(wǎng)絡(luò),總結(jié)搭建八股
一、基本概念
1:基于 Tensorflow 的 NN:
用張量表示數(shù)據(jù),用計(jì)算圖搭建神經(jīng)網(wǎng)絡(luò),用會(huì)話執(zhí)行計(jì)算圖,優(yōu)化線上的權(quán)重(參數(shù)),得到模型。
2:TensorFlow的張量:
張量就是多維數(shù)組(列表),用“階”表示張量的維度。
0 階張量稱作標(biāo)量,表示一個(gè)單獨(dú)的數(shù); 舉例 S=123
1 階張量稱作向量,表示一個(gè)一維數(shù)組; 舉例 V=[1,2,3]
2 階張量稱作矩陣,表示一個(gè)二維數(shù)組,它可以有 i 行 j 列個(gè)元素,每個(gè)元素可以用行號(hào)和列號(hào)共同索引到; 舉例 m=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
判斷張量是幾階的,就通過(guò)張量右邊的方括號(hào)數(shù),0 個(gè)是 0 階,n 個(gè)是 n 階,張 量可以表示 0 階到 n 階數(shù)組(列表); 舉例 t=[ [ [… ] ] ]為 3 階。
3:TensorFlow的數(shù)據(jù)類型:
Tensorflow 的數(shù)據(jù)類型有 tf.float32、tf.int32 等。
舉例 我們實(shí)現(xiàn) Tensorflow 的加法:

可以打印出這樣一句話:Tensor(“add:0”, shape=(2, ), dtype=float32),意思為 result 是一個(gè)名稱為 add:0 的張量,shape=(2,)表示一維數(shù)組長(zhǎng)度為 2, dtype=float32 表示數(shù)據(jù)類型為浮點(diǎn)型。
4:TensorFlow的計(jì)算圖(Graph):
搭建神經(jīng)網(wǎng)絡(luò)的計(jì)算過(guò)程,是承載一個(gè)或多個(gè)計(jì)算節(jié)點(diǎn)的一 張圖,只搭建網(wǎng)絡(luò),不運(yùn)算。
舉例:
在之前我們?cè)岬竭^(guò),神經(jīng)網(wǎng)絡(luò)的基本模型是神經(jīng)元,神經(jīng)元的基本模型其 實(shí)就是數(shù)學(xué)中的乘、加運(yùn)算。我們搭建如下的計(jì)算圖:

x1、x2 表示輸入,w1、w2 分別是 x1 到 y 和 x2 到 y 的權(quán)重,y=x1*w1+x2*w2。 我們實(shí)現(xiàn)上述計(jì)算圖:

可以打印出這樣一句話:Tensor(“matmul:0”, shape(1,1), dtype=float32), 從這里我們可以看出,print 的結(jié)果顯示 y 是一個(gè)張量,只搭建承載計(jì)算過(guò)程的 計(jì)算圖,并沒(méi)有運(yùn)算,如果我們想得到運(yùn)算結(jié)果就要用到“會(huì)話 Session()”了。
5:TensorFlow的會(huì)話(Session):
執(zhí)行計(jì)算圖中的節(jié)點(diǎn)運(yùn)算。
我們用 with 結(jié)構(gòu)實(shí)現(xiàn),語(yǔ)法如下:
with tf.Session() as sess:
print sess.run(y)
舉例:
對(duì)于剛剛所述計(jì)算圖,我們執(zhí)行 Session()會(huì)話可得到矩陣相乘結(jié)果:
可以打印出這樣的結(jié)果:
Tensor(“matmul:0”, shape(1,1), dtype=float32)
[[11.]]
我們可以看到,運(yùn)行Session()會(huì)話前只打印出y是個(gè)張量的提示,運(yùn)行Session() 會(huì)話后打印出了 y 的結(jié)果 1.0*3.0 + 2.0*4.0 = 11.0
②:神經(jīng)網(wǎng)絡(luò)參數(shù)
一:神經(jīng)網(wǎng)絡(luò)的參數(shù):是指神經(jīng)元線上的權(quán)重 w,用變量表示,一般會(huì)先隨機(jī)生成 這些參數(shù)。生成參數(shù)的方法是讓w等于tf.Variable,把生成的方式寫(xiě)在括號(hào)里。
神經(jīng)網(wǎng)絡(luò)中常用的生成隨機(jī)數(shù)/數(shù)組的函數(shù)有:

舉例:
① w=tf.Variable(tf.random_normal([2,3],stddev=2, mean=0, seed=1))
表示生成正態(tài)分布隨機(jī)數(shù),形狀兩行三列,標(biāo)準(zhǔn)差是 2,均值是 0,隨機(jī)種子是 1。
② w=tf.Variable(tf.Truncated_normal([2,3],stddev=2, mean=0, seed=1))
表示去掉偏離過(guò)大的正態(tài)分布,也就是如果隨機(jī)出來(lái)的數(shù)據(jù)偏離平均值超過(guò)兩個(gè) 標(biāo)準(zhǔn)差,這個(gè)數(shù)據(jù)將重新生成。
③ w=random_uniform(shape=7,minval=0,maxval=1,dtype=tf.int32,seed=1),
表示從一個(gè)均勻分布[minval maxval)中隨機(jī)采樣,注意定義域是左閉右開(kāi),即 包含 minval,不包含 maxval。
④ 除了生成隨機(jī)數(shù),還可以生成常量。
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]。
注意:
①隨機(jī)種子如果去掉每次生成的隨機(jī)數(shù)將不一致。
②如果沒(méi)有特殊要求標(biāo)準(zhǔn)差、均值、隨機(jī)種子是可以不寫(xiě)的。
二、神經(jīng)網(wǎng)絡(luò)的搭建
當(dāng)我們知道張量、計(jì)算圖、會(huì)話和參數(shù)后,我們可以討論神經(jīng)網(wǎng)絡(luò)的實(shí)現(xiàn)過(guò)程了
1:神經(jīng)網(wǎng)絡(luò)的實(shí)現(xiàn)過(guò)程:
1、準(zhǔn)備數(shù)據(jù)集,提取特征,作為輸入喂給神經(jīng)網(wǎng)絡(luò)(Neural Network,NN)
2、搭建 NN 結(jié)構(gòu),從輸入到輸出(先搭建計(jì)算圖,再用會(huì)話執(zhí)行)
( NN 前向傳播算法 ->計(jì)算輸出)
3、大量特征數(shù)據(jù)喂給 NN,迭代優(yōu)化 NN 參數(shù)
( NN 反向傳播算法 ->優(yōu)化參數(shù)訓(xùn)練模型)
4、使用訓(xùn)練好的模型預(yù)測(cè)和分類
由此可見(jiàn),基于神經(jīng)網(wǎng)絡(luò)的機(jī)器學(xué)習(xí)主要分為兩個(gè)過(guò)程,即訓(xùn)練過(guò)程和使用過(guò)程。
訓(xùn)練過(guò)程是第一步、第二步、第三步的循環(huán)迭代,使用過(guò)程是第四步,一旦參數(shù) 優(yōu)化完成就可以固定這些參數(shù),實(shí)現(xiàn)特定應(yīng)用了。 很多實(shí)際應(yīng)用中,我們會(huì)先使用現(xiàn)有的成熟網(wǎng)絡(luò)結(jié)構(gòu),喂入新的數(shù)據(jù),訓(xùn)練相應(yīng)模型,判斷是否能對(duì)喂入的從未見(jiàn)過(guò)的新數(shù)據(jù)作出正確響應(yīng),再適當(dāng)更改網(wǎng)絡(luò)結(jié)構(gòu),反復(fù)迭代,讓機(jī)器自動(dòng)訓(xùn)練參數(shù)找出最優(yōu)結(jié)構(gòu)和參數(shù),以固定專用模型。
③:前向傳播
前向傳播就是搭建模型的計(jì)算過(guò)程,讓模型具有推理能力,可以針對(duì)一組輸入 給出相應(yīng)的輸出。
舉例 假如生產(chǎn)一批零件,體積為 x1,重量為 x2,體積和重量就是我們選擇的特征, 把它們喂入神經(jīng)網(wǎng)絡(luò),當(dāng)體積和重量這組數(shù)據(jù)走過(guò)神經(jīng)網(wǎng)絡(luò)后會(huì)得到一個(gè)輸出。
假如輸入的特征值是:體積 0.7 重量 0.5

由搭建的神經(jīng)網(wǎng)絡(luò)可得,隱藏層節(jié)點(diǎn) a11=x1* w11+x2*w21=0.14+0.15=0.29,同理算得節(jié)點(diǎn) a12=0.32,a13=0.38,最終計(jì)算得到輸出層 Y=-0.015,這便實(shí)現(xiàn)了前向傳播過(guò)程。
推導(dǎo):
第一層
X 是輸入為 1X2 矩陣
用 x 表示輸入,是一個(gè) 1 行 2 列矩陣,表示一次輸入一組特征,這組特征包含了 體積和重量?jī)蓚€(gè)元素。
對(duì)于第一層的 w 前面有兩個(gè)節(jié)點(diǎn),后面有三個(gè)節(jié)點(diǎn) w 應(yīng)該是個(gè)兩行三列矩陣, 我們這樣表示:

神經(jīng)網(wǎng)絡(luò)共有幾層(或當(dāng)前是第幾層網(wǎng)絡(luò))都是指的計(jì)算層,輸入不是計(jì)算層, 所以 a 為第一層網(wǎng)絡(luò),a 是一個(gè)一行三列矩陣。
我們這樣表示:

第二層:
參數(shù)要滿足前面三個(gè)節(jié)點(diǎn),后面一個(gè)節(jié)點(diǎn),所以 W (2) 是三行一列矩陣。
我們這樣表示:

我們把每層輸入乘以線上的權(quán)重 w,這樣用矩陣乘法可以計(jì)算出輸出 y 了。
a= tf.matmul(X, W1)
y= tf.matmul(a, W2)
由于需要計(jì)算結(jié)果,就要用 with 結(jié)構(gòu)實(shí)現(xiàn),所有變量初始化過(guò)程、計(jì)算過(guò)程都 要放到 sess.run 函數(shù) 中 。 對(duì)于 變 量 初始 化 , 我們 在 sess.run 中 寫(xiě) 入 tf.global_variables_initializer 實(shí)現(xiàn)對(duì)所有變量初始化,也就是賦初值。對(duì) 于計(jì)算圖中的運(yùn)算,我們直接把運(yùn)算節(jié)點(diǎn)填入 sess.run 即可,比如要計(jì)算輸出 y,直接寫(xiě) sess.run(y) 即可。
在實(shí)際應(yīng)用中,我們可以一次喂入一組或多組輸入,讓神經(jīng)網(wǎng)絡(luò)計(jì)算輸出 y,可以先用 tf.placeholder 給輸入占位。如果一次喂一組數(shù)據(jù) shape 的第一維位置寫(xiě)1,第二維位置看有幾個(gè)輸入特征;如果一次想喂多組數(shù)據(jù),shape 的第一維 位置可以寫(xiě) None 表示先空著,第二維位置寫(xiě)有幾個(gè)輸入特征。這樣在 feed_dict 中可以喂入若干組體積重量了。
前向傳播過(guò)程的 tensorflow 描述:
舉例 :
這是一個(gè)實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)前向傳播過(guò)程,網(wǎng)絡(luò)可以自動(dòng)推理出輸出 y 的值。
①用 placeholder 實(shí)現(xiàn)輸入定義(sess.run 中喂入一組數(shù)據(jù))的情況
第一組喂體積 0.7、重量 0.5


④:反向傳播
反向傳播:訓(xùn)練模型參數(shù),在所有參數(shù)上用梯度下降,使 NN 模型在訓(xùn)練數(shù)據(jù) 上的損失函數(shù)最小。
損失函數(shù)(loss):計(jì)算得到的預(yù)測(cè)值 y 與已知答案 y_的差距
損失函數(shù)的計(jì)算有很多方法,均方誤差 MSE 是比較常用的方法之一。
均方誤差 MSE:求前向傳播計(jì)算結(jié)果與已知答案之差的平方再求平均。

用 tensorflow 函數(shù)表示為:
loss_mse = tf.reduce_mean(tf.square(y_ - y))
反向傳播訓(xùn)練方法:以減小 loss 值為優(yōu)化目標(biāo),有梯度下降、momentum 優(yōu)化 器、adam 優(yōu)化器等優(yōu)化方法。
這三種優(yōu)化方法用 tensorflow 的函數(shù)可以表示為:
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)
三種優(yōu)化方法區(qū)別如下:
①tf.train.GradientDescentOptimizer()使用隨機(jī)梯度下降算法,使參數(shù)沿著 梯度的反方向,即總損失減小的方向移動(dòng),實(shí)現(xiàn)更新參數(shù)

其中,??(??)為損失函數(shù),??為參數(shù),??為學(xué)習(xí)率。
②tf.train.MomentumOptimizer()在更新參數(shù)時(shí),利用了超參數(shù),參數(shù)更新公式是

其中,??為學(xué)習(xí)率,超參數(shù)為??,??為參數(shù),??(?????1 )為損失函數(shù)的梯度。
③tf.train.AdamOptimizer()是利用自適應(yīng)學(xué)習(xí)率的優(yōu)化算法,Adam 算法和隨 機(jī)梯度下降算法不同。隨機(jī)梯度下降算法保持單一的學(xué)習(xí)率更新所有的參數(shù),學(xué) 習(xí)率在訓(xùn)練過(guò)程中并不會(huì)改變。而 Adam 算法通過(guò)計(jì)算梯度的一階矩估計(jì)和二 階矩估計(jì)而為不同的參數(shù)設(shè)計(jì)獨(dú)立的自適應(yīng)性學(xué)習(xí)率。
學(xué)習(xí)率:決定每次參數(shù)更新的幅度。
優(yōu)化器中都需要一個(gè)叫做學(xué)習(xí)率的參數(shù),使用時(shí),如果學(xué)習(xí)率選擇過(guò)大會(huì)出現(xiàn)震 蕩不收斂的情況,如果學(xué)習(xí)率選擇過(guò)小,會(huì)出現(xiàn)收斂速度慢的情況。我們可以選 個(gè)比較小的值填入,比如 0.01、0.001。
三、搭建神經(jīng)網(wǎng)絡(luò)的八股
我們最后梳理出神經(jīng)網(wǎng)絡(luò)搭建的八股,神經(jīng)網(wǎng)絡(luò)的搭建課分四步完成:準(zhǔn)備工作、 前向傳播、反向傳播和循環(huán)迭代。

舉例
隨機(jī)產(chǎn)生 32 組生產(chǎn)出的零件的體積和重量,訓(xùn)練 3000 輪,每 500 輪輸出一次損 失函數(shù)。下面我們通過(guò)源代碼進(jìn)一步理解神經(jīng)網(wǎng)絡(luò)的實(shí)現(xiàn)過(guò)程:
0.導(dǎo)入模塊,生成模擬數(shù)據(jù)集;

1:定義神經(jīng)網(wǎng)絡(luò)的輸入、參數(shù)和輸出,定義前向傳播過(guò)程;

2:定義損失函數(shù)及反向傳播方法

3.生成會(huì)話,訓(xùn)練 STEPS 輪


由神經(jīng)網(wǎng)絡(luò)的實(shí)現(xiàn)結(jié)果,我們可以看出,總共訓(xùn)練 3000 輪,每輪從 X 的數(shù)據(jù)集 和 Y 的標(biāo)簽中抽取相對(duì)應(yīng)的從 start 開(kāi)始到 end 結(jié)束個(gè)特征值和標(biāo)簽,喂入神經(jīng) 網(wǎng)絡(luò),用 sess.run 求出 loss,每 500 輪打印一次 loss 值。經(jīng)過(guò) 3000 輪后,我 們打印出最終訓(xùn)練好的參數(shù) w1、w2。

這樣四步就可以實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)的搭建了。