一、TensorFlow運行模型——會話
1、通過創建會話(session)來執行定義好的運算
# 創建一個會話
sess = tf.Session()
# 使用這個創建好的會話來得到關心的運算的結果。比如可以調用sess.run(result)
sess.run(...)
# 關閉會話使得本次運行中得到的資源可以被釋放
sess.close()
通過Python上下文管理器的機制,只要將所有的計算放在“with”的內部就可以。當上下文管理器退出時候會自動釋放所有資源。這樣既解決了因爲異常退出時資源釋放的問題,同時也解決了忘記調用Session.close函數而產生的資源泄露。
# 創建一個會話,並通過Python中的上下文管理器來管理這個會話。
with tf.Session() as sess:
#使用創建好的會話來計算關心的結果
sess.run(...)
# 不需要再調用“Session.close()”函數來關閉會話
# 當上下文退出時會話關閉和資源釋放也自動完成了
2、通過 tf.InteractiveSession 函數可以省去將產生的會話註冊爲默認會話的過程。
sess = tf.InteractiveSession()
print(result.eval())
sess.close()
3、通過ConfigProto配置會話的方法:
config = tf.ConfigProto(allow_soft_placement=True,log_device_placement=True)
sess1 = tf.InteractiveSession(config=config)
sess2 = tf.Session(config=config)
ConfigProto 參數中第一個是布爾型的參數,當它爲True時,在以下任意一個條件成立時,GPU上的運算可以放到CPU上進行進行:
- 運算無法在GPU上執行。
- 沒有GPU資源(比如運算被指定在第二個GPU上運行,但是機器只有一個GPU)
- 運算輸入包含CPU計算結果的引用
第二個參數也是布爾型參數,在生產環境中將這個參數設置爲False可以減少日誌量。
二、TensorFlow實現神經網絡
1、前向傳播算法
全連接網絡:相鄰兩層之間任意兩個節點之間都有連接。
不同輸入的權重就是神經元的參數。
# 以三層神經網絡結構圖示例
"""
x爲輸入矩陣
w1爲從輸入層到隱藏層的權重矩陣
a爲隱藏層矩陣
w2爲從隱藏層到輸出層的權重矩陣
"""
import tensorflow as tf
sess = tf.Session() # 建立會話
x = tf.constant([[0.7,0.9]],name='x')
w1 = tf.constant([[0.2,0.1,0.4],[0.3,-0.5,0.2]],name='w1')
w2 = tf.constant([[0.6],[0.1],[-0.2]],name='w2')
a = tf.matmul(x,w1) # 矩陣相乘
print(sess.run(a)) # 輸出結果
y = tf.matmul(a,w2)
print(sess.run(y))
sess.close() # 關閉會話
輸出:
[[ 0.41000003 -0.38 0.45999998]] # 隱藏層a
[[ 0.11600002]] # 輸出層y
2、通過TensorFlow訓練神經網絡模型
import tensorflow as tf
from numpy.random import RandomState
# 定義訓練數據batch的大小
batch_size = 8
# 定義神經網絡的參數
"""
tf.Variable:TensorFlow變量的聲明函數
tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))會產生一個2 X 3的矩陣
矩陣中的元素均值爲0,標準差爲1的隨機數
並且通過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作爲存放數據的地方
"""
這裏維度也不一定要定義,但如果維度是確定的,那麼給出維度可以降低出錯的概率
若要改變樣例數據的大小,改變shape
在shape的一個維度上使用None可以方便使用不同的batch大小。
在訓練時需要把數據分成比較小的batch
但是在測試時可以一次性使用全部的數據,當數據集比較小時這樣比較方便測試
但數據集比較大時,將大量數據放入一個batch可能會導致內存溢出
"""
x = tf.placeholder(tf.float32,shape=(None,2),name= 'x_input')
y_ = tf.placeholder(tf.float32,shape=(None,1),name= 'y_input')
# 定義神經網絡前向傳播的過程
"""
tf.matmul :矩陣相乘
"""
a = tf.matmul(x,w1)
y = tf.matmul(a,w2)
# # 常規操作
# sess = tf.Session()
# init_op = tf.global_variables_initializer()
# sess.run(init_op)
# 定義損失函數來刻畫預測值與真實值得差距
"""
使用sigmoid函數將y轉換爲0-1之間的數值。
轉換後y代表預測是正樣本的概率,1-y代表預測是負樣本的概率
"""
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)))
# 定義學習率
learning_rate = 0.001
# 定義反向傳播算法來優化神經網絡中的參數
train_step = \
tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)
# 通過隨機數生成一個模擬數據集
""""
1爲隨機種子,只要隨機種子seed相同,產生的隨機數序列就相同
dataset_size:數據集大小
定義規則來給出樣本的標籤
所有x1+x2<1的樣例都被認爲是正樣本(比如零件合格),而其他爲負樣本(比如零件不合格)。
"""
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size,2)
Y = [[int(x1+x2<1)]for (x1,x2)in X]
# 創建一個會話來運行TensorFlow程序
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
# 初始化變量
sess.run(init_op)
print("w1=")
print(sess.run(w1))
print("w2=")
print(sess.run(w2))
# 設定訓練的輪數
STEPS = 5000
for i in range(STEPS):
# 每次選取batch_size個樣本進行訓練
start = (i*batch_size) % dataset_size
end = min(start+batch_size, dataset_size)
# 通過選取的樣本訓練神經網絡並更新參數
# 指定x y_的取值
sess.run(train_step,
feed_dict={x:X[start:end],y_:Y[start:end]})
if i%1000 ==0:
# 每隔一段時間計算在所有數據上的交叉熵並輸出
"""
通過運行觀察結果可以發現隨着訓練的進行,交叉熵是逐漸變小的。
交叉熵越小說明預測的結果和真實的結果差距越小
"""
# 指定x y_的取值
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))
# 訓練後的神經網絡權值
print("w1=")
print(sess.run(w1))
print("w2=")
print(sess.run(w2))