1、神經網絡結構
上次分享了tensorflow的基礎知識,今天我們就通過實現一個簡單的神經網絡來將知識點串聯起來,目標是用神經網絡來預測 一個分類問題:在輸入x1(零件長度)和x2(零件質量)的情況下預測零件是否合格(y=0或1)。
網絡的結構很簡單,輸入層兩個神經元,隱層6個神經元,輸出層1個神經元。
2、實現步驟詳解
(1)定義網絡結構
首先我們來定義網絡的一層,輸入的參數是該層輸入,定義神經網絡前向傳播過程,以及使用的激活函數sigmoid,:
# 定義神經網絡的參數
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) # normol為正態分布,stddev是均值,seed是標准差
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
# 在shape的一個維度上使用None可以方便使用不同的batch大小。在訓練時需要把數據分成比較小的batch,
# 但是在測試時,可以一次性使用全部數據。數據集比較小時可以這樣做,大了可能會導致內存溢出。
# x為輸入,y_為真實值,y為預測輸出,還沒有數據,先放在placeholder里,即用占位符表示
x = tf.placeholder(tf.float32, shape=[None, 2], name='x-input')
y_ = tf.placeholder(tf.float32, shape=[None, 1], name='y-input')
# 定義神經網絡前向傳播過程,matmul為矩陣乘法
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
# 得到的y是一個數,通過sigmoid轉化成一個0-1的數
y = tf.sigmoid(y)
(2)生成訓練數據
這里,我們生成128*2的x,定義一個分類規則來生成y :
# 通過隨機數生成一個模擬數據
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2) # 128組數據,每組兩個x1和x2
# 定義一個Y規則,在這里x1+x2<1的樣例都被認為是正樣本,其他為負。
# 在這里使用0來表示負樣本,1表示正樣本:int里面為真就為1,假則為0
Y = [[int(x1 + x2 < 1)] for (x1, x2) in X]
(3)構建網絡
這里,我們定義輸入層-隱藏層-輸出層的三層神經網絡結構。同時,我們定義我們的損失是平方損失函數,通過自適應優化算法來最小化我們的損失:
# 定義損失函數為交叉熵
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)) + (1-y_)*tf.log(tf.clip_by_value(1-y, 1e-10, 1.0)))
# 定義反向傳播的算法,使得在當前batch下損失函數最小
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
(4)定義Session並訓練
在定義好神經網絡之后,就可以使用Session來進行訓練了,這里要記住還是要先對變量進行初始化。這里我設置每1000步輸出下交叉熵損失,並順便看下訓練前后參數的變化情況:
# 准備工作都做好了,開始運行,創建一個會話Session來運行tf程序
with tf.Session() as sess:
init_op = tf.global_variables_initializer() # 初始化變量,global初始化所有變量
sess.run(init_op)
# 訓練前先輸出看下參數:w1是2*3矩陣,w2是3*1矩陣
print(sess.run(w1))
print(sess.run(w2))
'''
在訓練前神經網絡參數的值:
w1 = [[-0.81131822 1.48459876 0.06532937]
[-2.4427042 0.0992484 0.59122431]]
w2 = [[-0.81131822]
[ 1.48459876]
[ 0.06532937]]
'''
# 定義訓練的輪數
STEPS = 5000
for i in range(STEPS):
# 每次選取batch_size(前面定義了為8)個樣本進行訓練,開始就是0-8,...一直到120-128
start = (i * batch_size) % dataset_size
end = min(start+batch_size, dataset_size)
# 使用選取的這么多個樣本來進行訓練並更新參數,y是訓練出來的預測值(有x給出就能計算y,所有字典里只用給出x和y_的值)
# y_是真實值,feed_dict是一個字典,需要傳值給占位符,如下的cross_entropy需要x和y_的值
sess.run(train_step, feed_dict={x: X[start:end], y_:Y[start:end]})
if i % 1000 == 0:
# 每隔1000輪計算在所有數據上的交叉熵並輸出
total_cross_entropy = sess.run(cross_entropy, feed_dict={x:X, y_:Y})
print("After %d training steps,cross entropy on all data is %s"%(i, total_cross_entropy))
'''
輸出結果:
After 0 training steps,cross entropy on all data is 1.89805
After 1000 training steps,cross entropy on all data is 0.655075
After 2000 training steps,cross entropy on all data is 0.626172
After 3000 training steps,cross entropy on all data is 0.615096
After 4000 training steps,cross entropy on all data is 0.610309
'''
# 訓練之后再次輸出神經網絡的參數值:
print(sess.run(w1))
print(sess.run(w2))
''''
這兩個參數是訓練后更新的結果:
w1:[[ 0.02476984 0.5694868 1.69219422]
[-2.19773483 -0.23668921 1.11438966]]
w2: [[-0.45544702]
[ 0.49110931]
[-0.9811033 ]]
'''
3、完整代碼
import tensorflow as tf
from numpy.random import RandomState
# 用numpy來生成一個模擬的數據集
# 定義訓練數據batch的大小,在這里設置了一批批的
batch_size = 8
# 定義神經網絡的參數
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) # normol為正態分布,stddev是均值,seed是標准差
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
# 在shape的一個維度上使用None可以方便使用不同的batch大小。在訓練時需要把數據分成比較小的batch,
# 但是在測試時,可以一次性使用全部數據。數據集比較小時可以這樣做,大了可能會導致內存溢出。
# x為輸入,y_為預測輸出,還沒有數據,先放在placeholder里,即用占位符表示
x = tf.placeholder(tf.float32, shape=[None, 2], name='x-input')
y_ = tf.placeholder(tf.float32, shape=[None, 1], name='y-input')
# 定義神經網絡前向傳播過程,matmul為矩陣乘法
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
# 得到的y是一個數,通過sigmoid轉化成一個0-1的數
y = tf.sigmoid(y)
# 定義損失函數為交叉熵
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)) + (1-y_)*tf.log(tf.clip_by_value(1-y, 1e-10, 1.0)))
# 定義反向傳播的算法,使得在當前batch下損失函數最小
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
# 通過隨機數生成一個模擬數據
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2) # 128組數據,每組兩個x1和x2
# 定義一個Y規則,在這里x1+x2<1的樣例都被認為是正樣本,其他為負。
# 在這里使用0來表示負樣本,1表示正樣本:int里面為真就為1,假則為0
Y = [[int(x1 + x2 < 1)] for (x1, x2) in X]
# 准備工作都做好了,開始運行,創建一個會話Session來運行tf程序
with tf.Session() as sess:
init_op = tf.global_variables_initializer() # 初始化變量,global初始化所有變量
sess.run(init_op)
# 訓練前先輸出看下參數:w1是2*3矩陣,w2是3*1矩陣
print(sess.run(w1))
print(sess.run(w2))
'''
在訓練前神經網絡參數的值:
w1 = [[-0.81131822 1.48459876 0.06532937]
[-2.4427042 0.0992484 0.59122431]]
w2 = [[-0.81131822]
[ 1.48459876]
[ 0.06532937]]
'''
# 定義訓練的輪數
STEPS = 5000
for i in range(STEPS):
# 每次選取batch_size(前面定義了為8)個樣本進行訓練,開始就是0-8,...一直到120-128
start = (i * batch_size) % dataset_size
end = min(start+batch_size, dataset_size)
# 使用選取的這么多個樣本來進行訓練並更新參數,y是訓練出來的預測值(有x給出就能計算y,所有字典里只用給出x和y_的值)
# y_是真實值,feed_dict是一個字典,需要傳值給占位符,如下的cross_entropy需要x和y_的值
sess.run(train_step, feed_dict={x: X[start:end], y_:Y[start:end]})
if i % 1000 == 0:
# 每隔1000輪計算在所有數據上的交叉熵並輸出
total_cross_entropy = sess.run(cross_entropy, feed_dict={x:X, y_:Y})
print("After %d training steps,cross entropy on all data is %s"%(i, total_cross_entropy))
'''
輸出結果:
After 0 training steps,cross entropy on all data is 1.89805
After 1000 training steps,cross entropy on all data is 0.655075
After 2000 training steps,cross entropy on all data is 0.626172
After 3000 training steps,cross entropy on all data is 0.615096
After 4000 training steps,cross entropy on all data is 0.610309
'''
# 訓練之后再次輸出神經網絡的參數值:
print(sess.run(w1))
print(sess.run(w2))
''''
這兩個參數是訓練后更新的結果:
w1:[[ 0.02476984 0.5694868 1.69219422]
[-2.19773483 -0.23668921 1.11438966]]
w2: [[-0.45544702]
[ 0.49110931]
[-0.9811033 ]]
'''