TensorFlow:实战Google深度学习框架(二)实现简单神经网络
- 3.4 TensorFlow實現神經網絡
- 3.4.1 TensorFlow游樂場
- 3.4.2 前向傳播
- 3.4.3 神經網絡參數與TensorFlow變量
- 變量和張量的關系
- 變量的三個屬性:張量、維度、類型
- 變量和張量的關系
- 3.4.4通過TensorFlow訓練神經網絡模型
- 3.4.5 完整的神經網絡樣例程序
- 從程序中總結生成神經網絡的步驟
- 第三章小結
- 3.4 TensorFlow實現神經網絡
3.4 TensorFlow實現神經網絡
3.4.1 TensorFlow游樂場
https://playground.tensorflow.org3.4.2 前向傳播
神經網絡的輸出是通過前向傳播的方法得到的,前向傳播需要三部分信息:
其一,神經網絡的輸入(從實體中提取的特征向量)
其二,神經網絡的連接結構(不同神經元間輸入輸出的連接關系)
其三,神經網絡中每個神經元的參數(網絡層數、權值、偏置、節點數等)
前向傳播算法可以表示為矩陣的乘法
TensorFlow矩陣的乘法實現:tf.matmul
a = tf.matmul(x, w1) y = tf.matmul(a, w2)3.4.3 神經網絡參數與TensorFlow變量
- tf.Variable —>保存和更新神經網絡中的參數
TensorFlow中的變量也需要指定初始值,一般使用隨機數給其中的變量初始化
#聲明一個2*3矩陣變量 import tensorflow as tf weights=tf.Variable(tf.random_normal([2,3],stddev=2)) #2*3的矩陣,矩陣中元素為均值為0,標準差為2的隨機數,可以用mean指定平均值,默認為0(正態分布) <tf.Variable 'Variable:0' shape=(2, 3) dtype=float32_ref>- TensorFlow目前支持的所有隨機數生成器
| tf.random_normal | 正態分布 | 平均值、標準差、取值類型 |
| tf.truncated_normal | 正態分布,如果隨機出來的值偏離均值超過2個標準差,重新隨機 | 平均值、標準差、取值類型 |
| tf.random_uniform | 平均分布 | 最小、最大取值、取值類型 |
| tf.random_gamma | Gamma分布 | 形狀參數alpha、尺度參數beta、取值類型 |
函數完整介紹:
1)tf.random_normal使用方法
tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)解釋:
從正態分布中輸出隨機值。
參數:
shape: 一維的張量,也是輸出的張量。mean: 正態分布的均值。 stddev: 正態分布的標準差。dtype: 輸出的類型。seed: 一個整數,當設置之后,每次生成的隨機數都一樣。name: 操作的名字。2)tf.truncated_normal使用方法
tf.truncated_normal(shape,mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name=None)解釋:
從截斷的正態分布中輸出隨機值。
生成的值服從具有指定平均值和標準偏差的正態分布,如果生成的值大于平均值2個標準偏差的值則丟棄重新選擇。
在tf.truncated_normal中如果x的取值在區間(μ-2σ,μ+2σ)之外則重新進行選擇。這樣保證了生成的值都在均值附近。
代碼示例:
a = tf.Variable(tf.random_normal([2,2],seed=1)) b = tf.Variable(tf.truncated_normal([2,2],seed=2)) # 變量初始化 init = tf.global_variables_initializer() with tf.Session() as sess:sess.run(init)print(sess.run(a))print(sess.run(b))輸出: [[-0.81131822 1.48459876][ 0.06532937 -2.44270396]][[-0.85811085 -0.19662298][ 0.13895047 -1.22127688]]TensorFlow支持通過常數初始化變量,下表列出了常用常數聲明方法
表3-3 TensorFlow常數生成函數| tf.zeros | 產生全0數組 | tf.zeros([2,3],int32)–>[[0,0,0],[0,0,0]] |
| tf.ones | 產生全1數組 | tf.ones(2,3],int32)–>[[1,1,1],[1,1,1]] |
| tf.fill | 產生一個給定值的數組 | tf.fill([2,3],9)–>[[9,9,9],[9,9,9]] |
| tf.constant | 產生一個給定值常量 | tf.constant([1,2,3])–>[1,2,3] |
注意:
c1 = tf.constant([3]) #代表向量,shape=(1, )的一維constant c2 = tf.constant([[3]]) #代表1*1的矩陣,shape=(1, 1)的二維constant偏置項(bias):
偏置項通常會使用常數來設定初始值
biases=tf.Variable(tf.zeros([3])) <tf.Variable 'Variable_1:0' shape=(3,) dtype=float32_ref>除過使用隨機數或者常數,TensorFlow也支持其他變量的初始值來初始化新變量
import tensorflow as tf weights=tf.Variable(tf.random_normal([2,3],stddev=2)) w2=tf.Variable(weights.initialized_value()) w3=tf.Variable(weights.initialized_value()*2.0) #w2的初始值設置成了與weights變量相同,w3的初始值是weights初始值的兩倍 #TensorFlow中一個變量的值被使用之前,該變量的值需要被明確的調用 <tf.Variable 'Variable_1:0' shape=(2, 3) dtype=float32_ref> <tf.Variable 'Variable_2:0' shape=(2, 3) dtype=float32_ref>簡單的神經網絡
import tensorflow as tf # 聲明w1和w2兩個變量,這里還通過seed設定了隨機種子,保證每次運行的結果一樣 w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1)) w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))#暫時將輸入的特征向量定義為一個常量,x是一個1*2的矩陣 x=tf.constant([[0.7,0.9]]) #通過前向傳播算法獲得神經網絡的輸出 a=tf.matmul(x,w1) y=tf.matmul(a,w2)#調用會話輸出結果 sess=tf.Session() #初始化w1和w2(未初始化不能直接獲取值) sess.run(w1.initializer) #初始化w1 sess.run(w2.initializer) #初始化w2 #輸出 print(sess.run(y)) sess.close() # 也可以使用下面的初始化和會話方法 init=tf.global_variables_initializer() # with tf.Session() as sess: # sess.run(init) # print(sess.run(y)) [[ 3.95757794]]程序解析:
- 第一步:定義TensorFlow計算圖中的所有計算,但這些被定義的運算并不需要真正的運行
- 第二步:聲明一個會話,并通過會話計算結果,但在計算y之前,需要將所有用到的變量初始化,也就是說在定義的時候給出了變量初始化的方法,但并沒有真正運行。
- 但當變量數目增多或存在依賴關系時,可以用更加快捷的方法來初始化過程
- tf.global_variables_initializer(),【原始tf.initialize_all_variables()會報錯】
變量和張量的關系
變量的三個屬性:張量、維度、類型
1.張量
TensorFlow中所有的數據都是通過張量的形式來組織的,變量聲明函數tf.Variable()是一個運算,該運算會產生一個張量,該張量也就是本節所介紹的變量,所以變量就是特殊的張量。
構建機器學習模型時,可以通過變量聲明函數中的trainable函數來區分需要優化的參數(神經網絡的參數)和其他參數(如迭代次數),如果trainable為True,則變量會被加入 集合 GraphKeys.TRAINBALE_VARIABLES中,TensorFlow可以通過tf.variable_variables來得到所有需要優化的參數,TensorFlow的神經網絡優化算法將tf.variable_variables集合中的變量默認為優化對象。
2.維度
維度在程序運行過程中是可變的,但需要通過設置參數:validate_shape=False
import tensorflow as tf # 聲明w1和w2兩個變量,這里還通過seed設定了隨機種子,保證每次運行的結果一樣 w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1)) w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1)) #下面會報錯:維度不匹配 tf.assign(w1,w2) #下面會正確執行 tf.assign(w1,w2,validate_shape=False) #tf.assign(A, new_number): 這個函數的功能主要是把A的值變為new_number3.類型
變量的類型不可變,一個變量構建之后類型已經固定。
3.4.4通過TensorFlow訓練神經網絡模型
本節主要介紹使用監督學習的方式更合理的設置參數的取值
設置神經網絡參數的過程就是神經網絡的訓練過程,只有經過有效訓練的神經網絡才能真正的解決分類或者回歸問題。
使用監督學習的方式設置神經網絡參數需要有一個標注好的訓練數據集
監督學習的思想:
在已知答案的標注數據集上,模型給出的預測結果要盡可能的接近真實的答案,通過調整神經網絡中的參數對訓練數據進行擬合,可以使得模型對未知樣本提供預測能力。
通過反向傳播算法訓練神經網絡:
反向傳播過程實現了一個迭代的過程:
通過TensorFlow實現反向傳播:
1.實現一個樣例(batch)的前向傳播
表達一個batch的數據:placeholder
已知可以利用常量來表達選取的數據,但是這樣一來計算圖會太大,因為每生成一個常量,TensorFlow都會在計算圖中增加一個節點,所以TensorFlow引入placeholder機制用于提供數據。
placeholder:定義一個位置,該位置的數據在程序運行時再指定,只需要將數據通過placeholder來傳入計算圖中,而不用大量的常量來提供輸入數據。
placeholder: 中文意思是占位符,在tensorflow中類似于函數參數,運行時必須傳入值,經常會有一些待輸入的參數,但是在建立模型時,需要使用到它,那么就需要使用占用符的方式來寫入計算公式里,也就是建立到模型里的關系。
import tensorflow as tf# 聲明w1和w2兩個變量,這里還通過seed設定了隨機種子,保證每次運行的結果一樣 w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1)) w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))#定義placeholder作為存放輸入數據的地方,維度不一定要定義,但如果是確定的維度,可以降低出錯概率 x=tf.placeholder(tf.float32,shape=(1,2),name="input") a=tf.matmul(x,w1) y=tf.matmul(a,w2)sess=tf.Session() init_op=tf.global_variables_initializer() sess.run(init_op) print(sess.run(y,feed_dict={x:[[0.7,0.9]]})) [[ 3.95757794]]程序中替換了原理通過常量定義的輸入x,計算前向傳播時需要提供一個feed_dict來指定x的取值,feed_dict是一個字典,字典中需要給出每個用到的placeholder的取值。
2.實現n個樣例的前向傳播
將上述輸入的1?2?1?2矩陣改為n?2?n?2矩陣,其中每一行都為一個樣例數據,這樣得到的前向傳播結果為n?1?n?1的矩陣。
import tensorflow as tf # 聲明w1和w2兩個變量,這里還通過seed設定了隨機種子,保證每次運行的結果一樣 w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1)) w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1)) #定義placeholder作為存放輸入數據的地方,維度不一定要定義,但如果是確定的維度,可以降低出錯概率 x=tf.placeholder(tf.float32,shape=(3,2),name="input") a=tf.matmul(x,w1) y=tf.matmul(a,w2)sess=tf.Session() init_op=tf.global_variables_initializer() sess.run(init_op) print(sess.run(y,feed_dict={x:[[0.7,0.9],[0.1,0.4],[0.5,0.8]]})) [[ 3.95757794][ 1.15376544][ 3.16749239]]上面例子中,一次性計算多個batch的前向傳播結果,運行時需要將3個樣例[0.7,0.9],[0.1,0.4],[0.5,0.8]組成一個3*2的矩陣傳入placeholder中,計算得到3*1的矩陣。
3. 定義損失函數來刻畫當前預測值和真實答案的差距
cross_entropy=-tf.reduce_mean(y_ *tf.log(tf.clip_by_value(y,1e-10,1.0))) #定義學習率 learning_rate=0.001 #定義反向傳播算法來優化神經網絡中的參數 train_step=tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)cross_entropy:定義了真實值和預測值之間的交叉熵(分類中的常用損失函數)
train_step:定義了反向傳播的優化算法
代碼中的交叉熵損失函數解釋:
交叉熵用于衡量原始分布p(x)?p(x)和預測分布q(x)?q(x)之間的距離,CH(p,q)=?∑?x?p(x)logq(x)?CH(p,q)=?∑xp(x)logq(x)。
p(x)?p(x):就是真實的標簽y?y
q(x) q(x):就是預測的值y?^??y^
logq(x)?logq(x):tf.log(tf.clip_by_value(y, 1e-10, 1.0))
常用優化算法:
tf.train.GradientDescentOptimizer
tf.train.AdamOptimizer
tf.train.MomentumOptimizer
3.4.5 完整的神經網絡樣例程序
# 3.5.5 神經網絡樣例程序 import tensorflow as tf from numpy.random import RandomState# 定義訓練數據batch的大小 batch_size = 8# 定義神經網絡參數 # random_normal 產生一個正態隨機矩陣,shape=[2,3],stddev是正太分布的標準差,seed隨機數種子,設置后每次產生的數字都相同 w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))# 在shape的一個維度上使用None可以方便使用不大的batch大小, # 在訓練時需要將數據分成較小的batch,但在測試時,可以一次性使用全部的數據, # 數據集較小時方便測試,但是數據集較大時,大量的數據放入一個batch可能會導致數據溢出。 # placeholder占位符,執行時,在通過feed_dict將值傳入,dtype:數據類型,shape:數據形狀,name:名稱 # 如果在定義占位符時,不能確定值的形狀時,用None表示 x = tf.placeholder(tf.float32, shape=[None, 2], name='x-input') y_ = tf.placeholder(tf.float32, shape=[None, 1], name='y-input')# 定義前向傳播的過程 a = tf.matmul(x, w1) y = tf.matmul(a, w2)# 定義損失函數和反向傳播算法 # cross_entropy是交叉熵 # tf.clip_by_value(A, min, max):輸入一個張量A,把A中的每一個元素的值都壓縮在min和max之間。小于min的讓它等于min,大于max的元素的值等于max # reduce_mean 求均值 cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))) # train_step 就是每次可訓練出一組w就是一次反向傳播 # 下面給出里三種反向傳播的算法傳入的是學習率 # train_step = tf.train.AdamOptimizer(0.001).minimise(cross_entropy) # train_step=tf.train.GradientDescentOptimizer(0.001).minimize(cross_entropy) train_step = tf.train.MomentumOptimizer(0.001, 0.9).minimize(cross_entropy)# 通過隨機數生成一個模擬數據集rdm = RandomState(1) # 1為偽隨機數產生的種子 dataset_size = 128 X = rdm.rand(dataset_size, 2)# 此處使用0表示負樣本,1表示正樣本 Y = [[int(x1 + x2 < 1)] for (x1, x2) in X]# 創建一個會話來運行Tensorflow程序,反復運行反向傳播 # tf中運行必須放在session對象中,且運行過后,要關閉session with tf.Session() as sess:init_op = tf.global_variables_initializer()# 初始化變量,也就是上面的Variable變量sess.run(init_op)print(sess.run(w1))print(sess.run(w2))# 設定訓練的輪數STEPS = 5000for i in range(STEPS):# 每次選取batch_size個樣本進行訓練start = (i * batch_size) % dataset_sizeend = min(start + batch_size, dataset_size)# 通過選取的樣本訓練神經網絡并進行參數更新# feed_dict的作用是給使用placeholder創建出來的tensor賦值sess.run(train_step, feed_dict={x: X[start: end], y_: Y[start:end]})if i % 1000 == 0:total_cross_entropy = sess.run(cross_entropy, feed_dict={x: X, y_: Y})print("After %d training steps,cross entropy on all data is %g" % (i, total_cross_entropy))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]]輸出結果: After 0 training steps,cross entropy on all data is 0.0677127 After 1000 training steps,cross entropy on all data is 0.0299578 After 2000 training steps,cross entropy on all data is 0.0226611 After 3000 training steps,cross entropy on all data is 0.0178286 After 4000 training steps,cross entropy on all data is 0.0143322 訓練之后神經網絡的參數: w1=[[-1.14571726 1.92318034 0.107902 ][-2.79355311 0.57146555 0.63480443]] w2=[[-1.77604687],[ 2.00357008],[ 0.25552016]]從程序中總結生成神經網絡的步驟
訓練神經網絡過程可以分為以下三個步驟:
第三章小結
TensorFlow計算模型——計算圖
TensorFlow數據模型——張量
TensorFlow運算模型——會話
總結
以上是生活随笔為你收集整理的TensorFlow:实战Google深度学习框架(二)实现简单神经网络的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 他真的很忙!雷军站公司门口给小米员工挨个
- 下一篇: TensorFlow:实战Google深