# -*- coding:utf-8 -*-
import tensorflow as tf
'''
出現(xiàn)以下 Warning
Your CPU supports instructions that this TensorFlow binary was not compiled to use: SSE4.1 SSE4.2 AVX
原因
tensorflow 覺得你電腦 cpu 還行,支持 AVX(Advanced Vector Extensions)涕俗,運(yùn)算速度還可以提升愉阎,所以可以開啟更好更快的模式
解決方案
Just disables the warning, doesn’t enable AVX/FMA
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
'''
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
'''
主要 3 種類型的張量
tf.constant
常數(shù), 值不可改變, 會(huì)在圖中創(chuàng)建節(jié)點(diǎn), 不依賴于其他節(jié)點(diǎn), 可被其他節(jié)點(diǎn)依賴
一般作為輸入節(jié)點(diǎn)
tf.Variable
變量, 值可變, 會(huì)在圖中創(chuàng)建節(jié)點(diǎn), 可依賴其他節(jié)點(diǎn), 也可被其他節(jié)點(diǎn)依賴, 需要初始化值
一般用于可訓(xùn)練的參數(shù), 比如 w 和 b, 運(yùn)行過程中(包括訓(xùn)練前和訓(xùn)練后), 這些值一直存在
tf.placeholder
占位符, 值不可改變, 不會(huì)在圖中創(chuàng)建節(jié)點(diǎn), 不需要初始化, 可在運(yùn)行時(shí)再賦值
一般用于臨時(shí)數(shù)據(jù), 比如學(xué)習(xí)速度, 這個(gè)參數(shù)不需要在圖中有節(jié)點(diǎn)表示, 而且訓(xùn)練結(jié)束后就不再使用, 又比如樣本數(shù)據(jù)
Graph 圖
有默認(rèn)圖,也可以自己創(chuàng)建圖揉抵,張量都是在圖里面創(chuàng)建的,不同的圖可以有相同名字的張量
使用默認(rèn)圖創(chuàng)建張量
c = tf.Variable(tf.fill([2], 2.0))
自己創(chuàng)建圖忍疾,并創(chuàng)建張量
g1 = tf.Graph()
with g1.as_default():
v = tf.get_variable("v", initializer=tf.zeros_initializer()(shape=[3]))
獲取默認(rèn)圖
g = tf.get_default_graph()
運(yùn)行 Session
通過會(huì)話 session 執(zhí)行定義好的運(yùn)算, session 擁有并管理 TensorFlow 運(yùn)行時(shí)的所有資源
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = a + b
直接運(yùn)行
sess = tf.Session()
print sess.run(result) ## 輸出計(jì)算結(jié)果
print result.eval(session=sess) ## 結(jié)果一樣
sess.close()
或
with tf.Session() as sess:
print sess.run(result)
print result.eval(session=sess)
設(shè)置默認(rèn)會(huì)話
sess = tf.Session()
with sess.as_default():
print result.eval()
或
sess = tf.InteractiveSession()
print result.eval()
sess.close()
session 使用默認(rèn)圖裁赠,也可以自己指定圖
sess = tf.Session(graph=g1)
變量管理
## 下面兩個(gè)定義等價(jià)
## 區(qū)別: Variable 的 name 是可選的, 而 get_variable 是必須指定的
## get_variable 如果發(fā)現(xiàn)已有同名變量存在, 會(huì)報(bào)錯(cuò), 而 Variable 不會(huì)
v = tf.get_variable("v", shape=[1], initializer=tf.constant_initializer(1.0))
v = tf.Variable(tf.constant(1.0, shape=[1]), name="v")
## 在名字為 foo 的空間內(nèi)創(chuàng)建 v 變量, 如果該空間已存在 v 變量則報(bào)錯(cuò)
with tf.variable_scope("foo"):
v = tf.get_variable("v", shape=[1], initializer=tf.constant_initializer(1.0))
## 將 reuse 設(shè)為 True, 這樣 get_variable 只獲取已經(jīng)創(chuàng)建過的變量, 如果變量不存在則報(bào)錯(cuò)
with tf.variable_scope("foo", reuse=True):
v1 = tf.get_variable("v", [1])
print v == v1
## 使用變量管理的一個(gè)好處是不用在函數(shù)間傳遞大量參數(shù)
初始化變量
需要初始化所有的 Variable
tf.global_variables_initializer().run(session=sess)
如果有指定默認(rèn) session 則
tf.global_variables_initializer().run()
舊函數(shù)
tf.initialize_all_variables()
'''
sess = tf.Session()
hello = tf.constant('Hello, TensorFlow!')
print sess.run(hello)
a = tf.constant(10)
b = tf.constant(32)
print sess.run(a + b)
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = a + b
print result ## 顯示 Tensor("add_1:0", shape=(2,), dtype=float32)
print sess.run(result) ## 顯示 [3. 5.]
c = tf.Variable(tf.fill([2], 2.0)) ## diff with tf.fill([1, 2], 2.0)
d = tf.Variable(tf.fill([1,2], 2.0))
tf.global_variables_initializer().run(session=sess) ## need to init all var
print sess.run(result - c)
print sess.run(result - d)
print a.graph is tf.get_default_graph() ## 獲取張量 a 所在的 graph, 并判斷其是否默認(rèn)圖
sess.close()
g1 = tf.Graph()
with g1.as_default():
v = tf.get_variable("v", initializer=tf.zeros_initializer()(shape=[3]))
g2 = tf.Graph()
with g2.as_default():
v = tf.get_variable("v", initializer=tf.ones_initializer()(shape=[3]))
with tf.Session(graph=g1) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope("", reuse=True):
print sess.run(tf.get_variable("v"))
with tf.Session(graph=g2) as sess:
tf.global_variables_initializer().run()
with tf.variable_scope("", reuse=True):
print tf.get_variable("v").eval() ## 似乎 with 語句自動(dòng)把 sess 設(shè)為默認(rèn)會(huì)話所以可以直接使用 eval()
sess = tf.InteractiveSession()
x = tf.Variable(tf.random_normal([5,3]))
w = tf.Variable(tf.random_normal([3,2]))
b = tf.Variable(tf.fill([1,2], 0.5))
y = tf.matmul(x,w) + b
tf.global_variables_initializer().run()
print y.eval()
sess.close()
'''
w = tf.Variable(tf.fill([2,3], 3.0)) ## 產(chǎn)生全 3 的 2*3 矩陣作為變量
w2 = tf.Variable(w.initialized_value())
w3 = tf.Variable(w.initialized_value()*2) ## 用其他變量來初始化新的變量
w5 = w2.assign(w3) ## 將 w3 賦給 w2, 運(yùn)行 w5 后才生效
'''
'''
## 指定計(jì)算設(shè)備
g = tf.Graph()
with g.device('/gpu:0'):
result = a + b
'''
'''
## 通過集合管理不同資源如張量, 變量, 隊(duì)列資源等
tf.add_to_collection
tf.get_collection
'''
############
## 神經(jīng)網(wǎng)絡(luò)
############
from numpy.random import RandomState
batch_size = 8 ## 訓(xùn)練數(shù)據(jù) batch 的大小
## 定義權(quán)值
## w1 是輸入層和隱藏層之間的權(quán)值
## w2 是隱藏層和輸出層之間的權(quán)值
## 輸入有 2 個(gè)特征
## 隱藏層有 3 個(gè)節(jié)點(diǎn)
## 輸出層有 1 個(gè)節(jié)點(diǎn)
w1 = tf.Variable(tf.random_normal([2,3], stddev=1))
## tf.random_normal([3,1], stddev=1) 產(chǎn)生 3*1 矩陣, 元素是均值為 0, 標(biāo)準(zhǔn)差為 1 的隨機(jī)數(shù)
## 如果加上 seed=1 會(huì)導(dǎo)致每次的隨機(jī)數(shù)一樣
w2 = tf.Variable(tf.random_normal([3,1], stddev=1))
## 偏移值, 產(chǎn)生全為 0.5 的 1*3 矩陣作為變量
b1 = tf.Variable(tf.fill([3], 0.5))
b2 = tf.Variable(tf.fill([1], 0.5))
## 定義輸入
## 由于輸入是常量表示, 如果每輪迭代選取的數(shù)據(jù)都要通過常量來表示, 那么 TensorFlow 的計(jì)算圖將會(huì)太大
## 為避免這個(gè)問題, TensorFlow 提供了 placeholder
## placeholder 相當(dāng)于定義了一個(gè)位置, 這個(gè)位置中的數(shù)據(jù)在程序運(yùn)行時(shí)再指定, 所以不會(huì)產(chǎn)生太多的圖
x = tf.placeholder(tf.float32, shape=(None, 2), name='x-input')
## 賦值的時(shí)候可以自動(dòng)判斷 shape
y_ = tf.placeholder(tf.float32, shape=(None, 1), name='y-input')
## 定義神經(jīng)網(wǎng)絡(luò)前向傳播, 假設(shè)激活函數(shù)是 f(x) = x
a = tf.matmul(x, w1) + b1
y = tf.matmul(a, w2) + b2
## 定義損失函數(shù)(交叉熵)
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
## 定義反向傳播
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
## 隨機(jī)生成有兩個(gè)特征值的輸入數(shù)據(jù)
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)
Y = [[int(x1+x2<1)] for (x1,x2) in X]
print "X=\n" + str(X)
print "Y=\n" + str(Y)
with tf.Session() as sess:
tf.global_variables_initializer().run() ## 一次性初始化所有變量
print "\n"
print sess.run(w1) ## 訓(xùn)練之前神經(jīng)網(wǎng)絡(luò)的參數(shù)值
print sess.run(w2)
print sess.run(b1)
print sess.run(b2)
print "\n"
STEPS = 5000 ## 迭代次數(shù)
for i in range(STEPS):
start = (i*batch_size) % dataset_size
end = min(start+batch_size, dataset_size)
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})
## 隔一段時(shí)間計(jì)算所有數(shù)據(jù)的交叉熵輸出, 理想情況是最終變成 0, 但有時(shí)似乎不行
print("after " + str(i) + " training step(s), cross entropy on all data is " + str(total_cross_entropy))
print "\n"
print sess.run(w1) ## 訓(xùn)練之后神經(jīng)網(wǎng)絡(luò)的參數(shù)值
print sess.run(w2)
print sess.run(b1)
print sess.run(b2)
print "\n"
result = sess.run(y, feed_dict={x: X})
print result
print result - Y