Tensorflow 搭建神經網路基本流程
cs224d-Day 6: 快速入門 Tensorflow
本文是學習這個視訊課程系列的筆記,課程連結是 youtube 上的,
講的很好,淺顯易懂,入門首選, 而且在github有程式碼,
想看視訊的也可以去他的優酷裡的頻道找。
神經網路是一種數學模型,是存在於計算機的神經系統,由大量的神經元相連線並進行計算,在外界資訊的基礎上,改變內部的結構,常用來對輸入和輸出間複雜的關係進行建模。
神經網路由大量的節點和之間的聯絡構成,負責傳遞資訊和加工資訊,神經元也可以通過訓練而被強化。
這個圖就是一個神經網路系統,它由很多層構成。輸入層就是負責接收資訊,比如說一隻貓的圖片。輸出層就是計算機對這個輸入資訊的認知,它是不是貓。隱藏層就是對輸入資訊的加工處理。
神經網路是如何被訓練的,首先它需要很多資料。比如他要判斷一張圖片是不是貓。就要輸入上千萬張的帶有標籤的貓貓狗狗的圖片,然後再訓練上千萬次。
神經網路訓練的結果有對的也有錯的,如果是錯誤的結果,將被當做非常寶貴的經驗,那麼是如何從經驗中學習的呢?就是對比正確答案和錯誤答案之間的區別,然後把這個區別反向的傳遞回去,對每個相應的神經元進行一點點的改變。那麼下一次在訓練的時候就可以用已經改進一點點的神經元去得到稍微準確一點的結果。
神經網路是如何訓練的呢?每個神經元都有屬於它的啟用函式,用這些函式給計算機一個刺激行為。
在第一次給計算機看貓的圖片的時候,只有部分的神經元被啟用,被啟用的神經元所傳遞的資訊是對輸出結果最有價值的資訊。如果輸出的結果被判定為是狗,也就是說是錯誤的了,那麼就會修改神經元,一些容易被啟用的神經元會變得遲鈍,另外一些神經元會變得敏感。這樣一次次的訓練下去,所有神經元的引數都在被改變,它們變得對真正重要的資訊更為敏感。
**Tensorflow **是谷歌開發的深度學習系統,用它可以很快速地入門神經網路。
它可以做分類,也可以做擬合問題,就是要把這個模式給模擬出來。
這是一個基本的神經網路的結構,有輸入層,隱藏層,和輸出層。
每一層點開都有它相應的內容,函式和功能。
那我們要做的就是要建立一個這樣的結構,然後把資料喂進去。
把資料放進去後它就可以自己執行,TensorFlow 翻譯過來就是向量在裡面飛。
這個動圖的解釋就是,在輸入層輸入資料,然後資料飛到隱藏層飛到輸出層,用梯度下降處理,梯度下降會對幾個引數進行更新和完善,更新後的引數再次跑到隱藏層去學習,這樣一直迴圈直到結果收斂。
tensors_flowing.gif
今天一口氣把整個系列都學完了,先來一段完整的程式碼,然後解釋重要的知識點!
1. 搭建神經網路基本流程
定義新增神經層的函式
1.訓練的資料
2.定義節點準備接收資料
3.定義神經層:隱藏層和預測層
4.定義 loss 表示式
5.選擇 optimizer 使 loss 達到最小
然後對所有變數進行初始化,通過 sess.run optimizer,迭代 1000 次進行學習:
import tensorflow as tf
import numpy as np
# 新增層
def add_layer(inputs, in_size, out_size, activation_function=None):
# add one more layer and return the output of this layer
Weights = tf.Variable(tf.random_normal([in_size, out_size]))
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
Wx_plus_b = tf.matmul(inputs, Weights) + biases
if activation_function is None:
outputs = Wx_plus_b
else:
outputs = activation_function(Wx_plus_b)
return outputs
# 1.訓練的資料
# Make up some real data
x_data = np.linspace(-1,1,300)[:, np.newaxis]
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data) - 0.5 + noise
# 2.定義節點準備接收資料
# define placeholder for inputs to network
xs = tf.placeholder(tf.float32, [None, 1])
ys = tf.placeholder(tf.float32, [None, 1])
# 3.定義神經層:隱藏層和預測層
# add hidden layer 輸入值是 xs,在隱藏層有 10 個神經元
l1 = add_layer(xs, 1, 10, activation_function=tf.nn.relu)
# add output layer 輸入值是隱藏層 l1,在預測層輸出 1 個結果
prediction = add_layer(l1, 10, 1, activation_function=None)
# 4.定義 loss 表示式
# the error between prediciton and real data
loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction),
reduction_indices=[1]))
# 5.選擇 optimizer 使 loss 達到最小
# 這一行定義了用什麼方式去減少 loss,學習率是 0.1
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
# important step 對所有變數進行初始化
init = tf.initialize_all_variables()
sess = tf.Session()
# 上面定義的都沒有運算,直到 sess.run 才會開始運算
sess.run(init)
# 迭代 1000 次學習,sess.run optimizer
for i in range(1000):
# training train_step 和 loss 都是由 placeholder 定義的運算,所以這裡要用 feed 傳入引數
sess.run(train_step, feed_dict={xs: x_data, ys: y_data})
if i % 50 == 0:
# to see the step improvement
print(sess.run(loss, feed_dict={xs: x_data, ys: y_data}))
2. 主要步驟的解釋:
- 之前寫過一篇文章 TensorFlow 入門 講了 tensorflow 的安裝,這裡使用時直接匯入:
import tensorflow as tf
import numpy as np
- 匯入或者隨機定義訓練的資料 x 和 y:
x_data = np.random.rand(100).astype(np.float32)
y_data = x_data*0.1 + 0.3
- 先定義出引數 Weights,biases,擬合公式 y,誤差公式 loss:
Weights = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
biases = tf.Variable(tf.zeros([1]))
y = Weights*x_data + biases
loss = tf.reduce_mean(tf.square(y-y_data))
- 選擇 Gradient Descent 這個最基本的 Optimizer:
optimizer = tf.train.GradientDescentOptimizer(0.5)
- 神經網路的 key idea,就是讓 loss 達到最小:
train = optimizer.minimize(loss)
- 前面是定義,在執行模型前先要初始化所有變數:
init = tf.initialize_all_variables()
- 接下來把結構啟用,sesseion像一個指標指向要處理的地方:
sess = tf.Session()
- init 就被激活了,不要忘記啟用:
sess.run(init)
- 訓練201步:
for step in range(201):
- 要訓練 train,也就是 optimizer:
sess.run(train)
- 每 20 步列印一下結果,sess.run 指向 Weights,biases 並被輸出:
if step % 20 == 0:
print(step, sess.run(Weights), sess.run(biases))
所以關鍵的就是 y,loss,optimizer 是如何定義的。
3. TensorFlow 基本概念及程式碼:
在 TensorFlow 入門 也提到了幾個基本概念,這裡是幾個常見的用法。
- Session
矩陣乘法:tf.matmul
product = tf.matmul(matrix1, matrix2) # matrix multiply np.dot(m1, m2)
定義 Session,它是個物件,注意大寫:
sess = tf.Session()
result 要去 sess.run 那裡取結果:
result = sess.run(product)
- Variable
用 tf.Variable 定義變數,與python不同的是,必須先定義它是一個變數,它才是一個變數,初始值為0,還可以給它一個名字 counter:
state = tf.Variable(0, name='counter')
將 new_value 載入到 state 上,counter就被更新:
update = tf.assign(state, new_value)
如果有變數就一定要做初始化:
init = tf.initialize_all_variables() # must have if define variable
- placeholder:
要給節點輸入資料時用 placeholder,在 TensorFlow 中用placeholder 來描述等待輸入的節點,只需要指定型別即可,然後在執行節點的時候用一個字典來“喂”這些節點。相當於先把變數 hold 住,然後每次從外部傳入data,注意 placeholder 和 feed_dict 是繫結用的。
這裡簡單提一下 feed 機制, 給 feed 提供資料,作為 run()
呼叫的引數, feed 只在呼叫它的方法內有效, 方法結束, feed 就會消失。
import tensorflow as tf
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
ouput = tf.mul(input1, input2)
with tf.Session() as sess:
print(sess.run(ouput, feed_dict={input1: [7.], input2: [2.]}))
4. 神經網路基本概念
- 激勵函式:
例如一個神經元對貓的眼睛敏感,那當它看到貓的眼睛的時候,就被激勵了,相應的引數就會被調優,它的貢獻就會越大。
下面是幾種常見的啟用函式:
x軸表示傳遞過來的值,y軸表示它傳遞出去的值:
激勵函式在預測層,判斷哪些值要被送到預測結果那裡:
TensorFlow 常用的 activation function
- 新增神經層:
輸入引數有 inputs, in_size, out_size, 和 activation_function
import tensorflow as tf
def add_layer(inputs, in_size, out_size, activation_function=None):
Weights = tf.Variable(tf.random_normal([in_size, out_size]))
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
Wx_plus_b = tf.matmul(inputs, Weights) + biases
if activation_function is None:
outputs = Wx_plus_b
else:
outputs = activation_function(Wx_plus_b)
return outputs
- 分類問題的 loss 函式 cross_entropy :
# the error between prediction and real data
# loss 函式用 cross entropy
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction),
reduction_indices=[1])) # loss
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
- overfitting:
下面第三個圖就是 overfitting,就是過度準確地擬合了歷史資料,而對新資料預測時就會有很大誤差:
Tensorflow 有一個很好的工具, 叫做dropout, 只需要給予它一個不被 drop 掉的百分比,就能很好地降低 overfitting。
dropout 是指在深度學習網路的訓練過程中,按照一定的概率將一部分神經網路單元暫時從網路中丟棄,相當於從原始的網路中找到一個更瘦的網路,這篇部落格中講的非常詳細
程式碼實現就是在 add layer 函式里加上 dropout, keep_prob 就是保持多少不被 drop,在迭代時在 sess.run 中被 feed:
def add_layer(inputs, in_size, out_size, layer_name, activation_function=None, ):
# add one more layer and return the output of this layer
Weights = tf.Variable(tf.random_normal([in_size, out_size]))
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1, )
Wx_plus_b = tf.matmul(inputs, Weights) + biases
# here to dropout
# 在 Wx_plus_b 上drop掉一定比例
# keep_prob 保持多少不被drop,在迭代時在 sess.run 中 feed
Wx_plus_b = tf.nn.dropout(Wx_plus_b, keep_prob)
if activation_function is None:
outputs = Wx_plus_b
else:
outputs = activation_function(Wx_plus_b, )
tf.histogram_summary(layer_name + '/outputs', outputs)
return outputs
5. 視覺化 Tensorboard
Tensorflow 自帶 tensorboard ,可以自動顯示我們所建造的神經網路流程圖:
就是用 with tf.name_scope 定義各個框架,注意看程式碼註釋中的區別:
import tensorflow as tf
def add_layer(inputs, in_size, out_size, activation_function=None):
# add one more layer and return the output of this layer
# 區別:大框架,定義層 layer,裡面有 小部件
with tf.name_scope('layer'):
# 區別:小部件
with tf.name_scope('weights'):
Weights = tf.Variable(tf.random_normal([in_size, out_size]), name='W')
with tf.name_scope('biases'):
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1, name='b')
with tf.name_scope('Wx_plus_b'):
Wx_plus_b = tf.add(tf.matmul(inputs, Weights), biases)
if activation_function is None:
outputs = Wx_plus_b
else:
outputs = activation_function(Wx_plus_b, )
return outputs
# define placeholder for inputs to network
# 區別:大框架,裡面有 inputs x,y
with tf.name_scope('inputs'):
xs = tf.placeholder(tf.float32, [None, 1], name='x_input')
ys = tf.placeholder(tf.float32, [None, 1], name='y_input')
# add hidden layer
l1 = add_layer(xs, 1, 10, activation_function=tf.nn.relu)
# add output layer
prediction = add_layer(l1, 10, 1, activation_function=None)
# the error between prediciton and real data
# 區別:定義框架 loss
with tf.name_scope('loss'):
loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction),
reduction_indices=[1]))
# 區別:定義框架 train
with tf.name_scope('train'):
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
sess = tf.Session()
# 區別:sess.graph 把所有框架載入到一個檔案中放到資料夾"logs/"裡
# 接著開啟terminal,進入你存放的資料夾地址上一層,執行命令 tensorboard --logdir='logs/'
# 會返回一個地址,然後用瀏覽器開啟這個地址,在 graph 標籤欄下開啟
writer = tf.train.SummaryWriter("logs/", sess.graph)
# important step
sess.run(tf.initialize_all_variables())
執行完上面程式碼後,開啟 terminal,進入你存放的資料夾地址上一層,執行命令 tensorboard --logdir='logs/' 後會返回一個地址,然後用瀏覽器開啟這個地址,點選 graph 標籤欄下就可以看到流程圖了:
6. 儲存和載入
訓練好了一個神經網路後,可以儲存起來下次使用時再次載入:
import tensorflow as tf
import numpy as np
## Save to file
# remember to define the same dtype and shape when restore
W = tf.Variable([[1,2,3],[3,4,5]], dtype=tf.float32, name='weights')
b = tf.Variable([[1,2,3]], dtype=tf.float32, name='biases')
init= tf.initialize_all_variables()
saver = tf.train.Saver()
# 用 saver 將所有的 variable 儲存到定義的路徑
with tf.Session() as sess:
sess.run(init)
save_path = saver.save(sess, "my_net/save_net.ckpt")
print("Save to path: ", save_path)
################################################
# restore variables
# redefine the same shape and same type for your variables
W = tf.Variable(np.arange(6).reshape((2, 3)), dtype=tf.float32, name="weights")
b = tf.Variable(np.arange(3).reshape((1, 3)), dtype=tf.float32, name="biases")
# not need init step
saver = tf.train.Saver()
# 用 saver 從路徑中將 save_net.ckpt 儲存的 W 和 b restore 進來
with tf.Session() as sess:
saver.restore(sess, "my_net/save_net.ckpt")
print("weights:", sess.run(W))
print("biases:", sess.run(b))
tensorflow 現在只能儲存 variables,還不能儲存整個神經網路的框架,所以再使用的時候,需要重新定義框架,然後把 variables 放進去學習。
[cs224d]
Day 1. 深度學習與自然語言處理 主要概念一覽
Day 2. TensorFlow 入門
Day 3. word2vec 模型思想和程式碼實現
Day 4. 怎樣做情感分析
Day 5. CS224d-Day 5: RNN快速入門
Day 6. 一文學會用 Tensorflow 搭建神經網路
Day 7. 用深度神經網路處理NER命名實體識別問題
Day 8. 用 RNN 訓練語言模型生成文字
Day 9. RNN與機器翻譯
Day 10. 用 Recursive Neural Networks 得到分析樹
Day 11. RNN的高階應用
轉自:https://www.jianshu.com/p/e112012a4b2d
作者:不會停的蝸牛