Tensorflow实现简单神经网络
1. 神經(jīng)網(wǎng)絡(luò)參數(shù)與tensorflow變量
在tensorflow中使用tf.variable定義變量,變量作用是保存和更新神經(jīng)網(wǎng)絡(luò)中的參數(shù)。并且要給變量初始化一個(gè)初始值:
weights=tf.Variable(tf.random_normal([2, 3], stddev=2))這里定義了一個(gè)2x3的矩陣,矩陣中的元素是均值為0,標(biāo)核差為2的隨機(jī)數(shù),這是因?yàn)閠f.random_normal函數(shù)通過(guò)參數(shù)mean來(lái)指定平均值,在沒(méi)有指定時(shí)默認(rèn)為0,而且通常是定義一個(gè)滿足正態(tài)分布的隨機(jī)數(shù)來(lái)初始化神經(jīng)網(wǎng)絡(luò)的參數(shù),目前支持的有:
- tf.random_normal:正態(tài)分布(平均值、標(biāo)準(zhǔn)差、取值類(lèi)型)
- tf.truncated_normal:正態(tài)分布,但如果隨機(jī)出來(lái)的值偏離平均值超過(guò)2個(gè)標(biāo)準(zhǔn)差,那么這個(gè)數(shù)將會(huì)被重新隨機(jī)。(平均值、標(biāo)準(zhǔn)差、取值類(lèi)型)
- tf.random_uniform:平均分布(最小、最大取值、取值類(lèi)型)
- tf.random_gamma:gamma分布 (形狀參數(shù)alpha、尺度參數(shù)、取值類(lèi)型)
tensorflow還支持初始化一個(gè)常數(shù)變量。
- tf.zeros:產(chǎn)生全0的數(shù)組
- tf.ones:產(chǎn)生全1的數(shù)組
- tf.fill:產(chǎn)生一個(gè)全部為給定數(shù)字的數(shù)組(tf.fill([2,3],9)->[[9,9,9],[9,9,9]])
- tf.constant:產(chǎn)生一個(gè)給定值的常量(tf.constant([1,2,3])->[1,2,3])
1.1 在tensorflow中一個(gè)變量的值在使用之前必須被初始化。
示例:
import tensorflow as tf #這里通過(guò)seed參數(shù)設(shè)定了隨機(jī)種子,這樣可以保證每次運(yùn)行的結(jié)果是一樣的 w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) w2= tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1)) # 這里暫時(shí)將輸入的特征向量定義為一個(gè)常量 x = tf.constant([[0.7, 0.9]]) # 前向傳播:1x2的輸入->和隱層的2x3的權(quán)重矩陣相乘得到1x3矩陣->和輸出層的3x1矩陣 # 相乘得到輸出 a = tf.matmul(x, w1) y = tf.matmul(a, w2) # 打開(kāi)會(huì)話 sess = tf.Session() # 這里是對(duì)變量為w1、w2的初始化 sess.run(w1.initializer) sess.run(w2.initializer) # 在通過(guò)以下進(jìn)行y值的獲取之前必須進(jìn)行變量的初始化,而常量則不需要 print(sess.run(y)) sess.close()結(jié)果:
[[3.957578]]這里要注意的兩點(diǎn)是:
- 在所有的變量被定義時(shí)給出了初始化的方法,但并沒(méi)有真正的運(yùn)行,但通過(guò)運(yùn)行w1.initializer才被真正賦初值。
- 變量的真正計(jì)算是通過(guò)會(huì)話才完成的。
- 在實(shí)際的使用中一般通過(guò)tf.initialize_all_variable()來(lái)初始化所有的變量,這樣就不會(huì)有漏掉的變量忘了初始化,而且省了很大的力氣。
1.2 變量的管理
這里簡(jiǎn)單說(shuō)下變量和張量的區(qū)別:
所有的數(shù)據(jù)都是通過(guò)張量的形式來(lái)組織的。而 tf.Variable運(yùn)算的結(jié)果就是一個(gè)張量,所以變量是一種特殊的張量。
- 在tensorflow中有一個(gè)集合的概念,就是所有的變量都會(huì)自動(dòng)加入到graphKeys.VARIABLES這個(gè)集合。這個(gè)集合主要是為了管理變量,可以通過(guò)tf.all_variables函數(shù)拿到所有的當(dāng)前計(jì)算圖上的變量,這有助于持久化整個(gè)計(jì)算圖的運(yùn)行狀態(tài)。
- 在構(gòu)建機(jī)器學(xué)習(xí)模型時(shí),可以通過(guò)變量聲明函數(shù)中的trainable參數(shù)來(lái)區(qū)分需要優(yōu)化的參數(shù)(比如神經(jīng)網(wǎng)絡(luò)中的參數(shù),很重要)和其他的以一些參數(shù)(比如迭代輪數(shù)),如果在聲明變量時(shí)參數(shù)trainable為true,那么這個(gè)變量將會(huì)被加入graphKeys.TRAINABLE_VARIABLES集合,然后通過(guò)tf.trainable_variables函數(shù)得到所有需要優(yōu)化的參數(shù),而tensorflow也會(huì)把graphKeys.TRAINABLE_VARIABLES集合中的變量作為默認(rèn)的優(yōu)化參數(shù)。
此外關(guān)于變量(維度、類(lèi)型)還要注意:
- 變量的維度在運(yùn)行中是可以更改的,但是需要通過(guò)參數(shù)設(shè)置,validate_shape=False
實(shí)際中其實(shí)用的很少。。。
- 變量的類(lèi)型在構(gòu)建之后是不允許再改變的,比如w1,w2初始類(lèi)型不同,在運(yùn)行中執(zhí)行如下就會(huì)報(bào)錯(cuò):
2. 神經(jīng)網(wǎng)絡(luò)訓(xùn)練模型示例
2.1 常量數(shù)據(jù)的表達(dá)
這里首先說(shuō)下在進(jìn)行反向傳播的過(guò)程中的第一步是使用tensorflow表達(dá)一個(gè)batch的數(shù)據(jù),如果這時(shí)用普通的常量來(lái)定義,也就是說(shuō)和普通編程一樣,把輸入數(shù)據(jù)定義為常量,這時(shí)會(huì)造成每來(lái)一個(gè)batch的數(shù)據(jù),就需要定義一個(gè)batch的常量,而每生成一個(gè)常量,tensorflow都會(huì)在圖中增加一個(gè)節(jié)點(diǎn),這樣的話在整個(gè)神經(jīng)網(wǎng)絡(luò)的訓(xùn)練過(guò)程中將產(chǎn)生很大的計(jì)算圖,這樣肯定是不行的,所以就有了placeholder機(jī)制,用于提供數(shù)據(jù)。placehlder其實(shí)相當(dāng)于定義了一個(gè)位置,而這個(gè)位置的數(shù)據(jù)是在程序運(yùn)行時(shí)再指定,這樣就不用生成大量的常量來(lái)提供輸入數(shù)據(jù),而只需要將數(shù)據(jù)輸入到placeholder來(lái)進(jìn)行計(jì)算圖的計(jì)算。
注意:placeholder在定義時(shí),需要指定維度和數(shù)據(jù)類(lèi)型,而數(shù)據(jù)類(lèi)型是不能改變的,但是數(shù)據(jù)的維度可以根據(jù)提供的數(shù)據(jù)推導(dǎo)出來(lái),所以不一定要給出。
這里需要注意的是在所有是初始化和輸入都定義好了以后,在sess運(yùn)行前向傳播的時(shí)候需要提供一個(gè)feed_dict字典,也就是需要喂給模型數(shù)據(jù)才能跑起來(lái),而且需要指定每一個(gè)placeholder的取值,否則會(huì)報(bào)錯(cuò)。
在得到前向傳播的數(shù)值后,需要定義一個(gè)損失函數(shù)來(lái)刻畫(huà)當(dāng)前的預(yù)測(cè)值和真實(shí)值之間的差距,常用的就是交叉熵?fù)p失函數(shù)。
# 損失函數(shù) cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)) # 反向傳播優(yōu)化神經(jīng)網(wǎng)絡(luò)參數(shù) train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)注意:目前tensorflow支持7種不同的優(yōu)化器,比較常用的三種:
tf.train.gradientdescentoptimizer tf.train.adamoptimizer tf.train.momentumoptimizer在定義好反向傳播后就可以通過(guò)運(yùn)行sess.run(train_step)就可以對(duì)所有在graphKeys.TRAINABLE_VARIABLES集合中的變量進(jìn)行優(yōu)化,以使得當(dāng)前batch下?lián)p失函數(shù)更小。
下面是完整代碼:
import tensorflow as tf from numpy.random import RandomState# 定義神經(jīng)網(wǎng)絡(luò)的參數(shù),輸入和輸出節(jié)點(diǎn)。 batch_size = 8 w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) # 這里是一個(gè)隱層,并且是3個(gè)節(jié)點(diǎn) w2= tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1)) x = tf.placeholder(tf.float32, shape=(None, 2), name="x-input") # 輸入是個(gè)節(jié)點(diǎn),即是每個(gè)樣本2個(gè)特征 y_= tf.placeholder(tf.float32, shape=(None, 1), name='y-input') # 輸出是2分類(lèi)# 定義前向傳播過(guò)程,損失函數(shù)及反向傳播算法 a = tf.matmul(x, w1) y = tf.matmul(a, w2) y = tf.sigmoid(y) # 邏輯回歸2分類(lèi) 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))) train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)# 生成模擬數(shù)據(jù)集 rdm = RandomState(1) X = rdm.rand(128,2) Y = [[int(x1+x2 < 1)] for (x1, x2) in X] print('Y:',Y)# 創(chuàng)建一個(gè)會(huì)話來(lái)運(yùn)行TensorFlow程序 with tf.Session() as sess:# 初始化所有的變量init_op = tf.global_variables_initializer()sess.run(init_op)# 輸出目前(未經(jīng)訓(xùn)練)的參數(shù)取值,這里是tensorflow中顯示輸出的方法print(sess.run(w1))print(sess.run(w2))print("\n")# 訓(xùn)練模型。STEPS = 5000for i in range(STEPS):# 每次選擇batch_size個(gè)樣本進(jìn)行訓(xùn)練start = (i*batch_size) % 128end = (i*batch_size) % 128 + batch_size# 通過(guò)選取的batch_size訓(xùn)練樣本訓(xùn)練網(wǎng)路并更新sess.run([train_step, y, y_], feed_dict={x: X[start:end], y_: Y[start:end]})if i % 1000 == 0:# 每1000次迭代后,使用全部的樣本進(jìn)行計(jì)算交叉熵,并輸出total_cross_entropy = sess.run(cross_entropy, feed_dict={x: X, y_: Y})print("After %d training step(s), cross entropy on all data is %g" % (i, total_cross_entropy))# 輸出訓(xùn)練后的參數(shù)取值。print("\n 訓(xùn)練結(jié)果:")print(sess.run(w1))print(sess.run(w2))運(yùn)行結(jié)果:
Y: [[0], [1], [1], [1], [1], [0], [0], [1], [1], [1], [0], [0], [0], [1], [0], [1], [0], [0], [0], [1], [0], [0], [1], [0], [1], [1], [1], [1], [1], [0], [1], [0], [1], [0], [0], [0], [1], [1], [0], [0], [0], [0], [0], [0], [0], [0], [0], [1], [0], [1], [1], [0], [0], [1], [0], [1], [0], [1], [0], [1], [1], [1], [0], [0], [1], [0], [1], [0], [0], [0], [1], [1], [1], [1], [1], [0], [1], [1], [1], [0], [1], [0], [1], [1], [0], [0], [1], [0], [1], [1], [1], [1], [0], [1], [0], [1], [0], [0], [1], [0], [0], [0], [1], [0], [0], [0], [1], [1], [1], [1], [1], [1], [0], [0], [0], [0], [0], [0], [1], [0], [0], [1], [0], [1], [0], [1], [0], [0]] [[-0.8113182 1.4845988 0.06532937][-2.4427042 0.0992484 0.5912243 ]] [[-0.8113182 ][ 1.4845988 ][ 0.06532937]]After 0 training step(s), cross entropy on all data is 1.89805 After 1000 training step(s), cross entropy on all data is 0.655075 After 2000 training step(s), cross entropy on all data is 0.626172 After 3000 training step(s), cross entropy on all data is 0.615096 After 4000 training step(s), cross entropy on all data is 0.610309訓(xùn)練結(jié)果: [[ 0.02476983 0.56948674 1.6921941 ][-2.1977348 -0.23668921 1.1143895 ]] [[-0.45544702][ 0.49110925][-0.98110336]]這里要注意:
- 從運(yùn)行結(jié)果可以看出,隨著訓(xùn)練的迭代,交叉熵是逐漸變小的,交叉熵越小說(shuō)明預(yù)測(cè)的結(jié)果和實(shí)際的差距越小。
- 從中可以看出打印變量值必須在sess中,也就是說(shuō)關(guān)閉會(huì)話,打印輸出只是一個(gè)引用
- 從最后的運(yùn)行結(jié)果可以看出,訓(xùn)練完成后權(quán)重矩陣發(fā)生了很大的變化
參考:《Tensorflow實(shí)戰(zhàn)Google深度學(xué)習(xí)框架》
與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Tensorflow实现简单神经网络的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 外汇 期货 股票的区别
- 下一篇: 借款利息怎么算公式