1 舊版本代碼常見問題:
首先給出學(xué)習(xí)tensorflow的大致路徑:https://www.jiqizhixin.com/articles/2016-10-17
另外很多書籍和教程都是tensorflow1.0之前的寫的,代碼有很多問題厦瓢,這里總結(jié)一下:
問題1:
tf.initialize_all_variables()
已經(jīng)棄用
使用tf.global_variables_initializer()
代替
tf.select()
已經(jīng)棄用
使用tf.where()
代替
問題2:
module 'tensorflow' has no attribute 'xxx'
這種錯(cuò)誤大概有下面幾種:
tf.sub()
更改為tf.subtract()
tf.mul()
更改為tf.multiply()
注意:tf.multiply是點(diǎn)乘(即相應(yīng)位置乘)提揍,即Returns x * y element-wise.
tf.matmul是矩陣乘法啤月,即Multiplies matrix a by matrix b, producing a * b.
這里需要修改的是點(diǎn)乘。
tf.types.float32
更改為tf.float32
tf.pact()
更改為tf.stact()
tf.neg()
更改為 tf.negative()
問題3:
ValueError: Only call sigmoid_cross_entropy_with_logits with named arguments (labels=…, logits=…, …)
解決方案:
tf.nn.sigmoid_cross_entropy_with_logits(self.D2_logits_,tf.ones_like(self.D2_) * 0.9))
修改為
tf.nn.sigmoid_cross_entropy_with_logits(labels=tf.ones_like(self.D2_) * 0.9, logits=self.D2_logits_))
問題4:
TypeError: Expected int32, got list containing Tensors of type '_Message' instead.
tf.concat函數(shù),tensorflow之前版本(0.x版本:數(shù)字在前劳跃,tensors在后),tensorflow1.0及以后api定義:(數(shù)字在后谎仲,tensors在前)
調(diào)整函數(shù)參數(shù)位置即可,下面是例子刨仑,需要把第一種
t1 = [[1, 2, 3], [4, 5, 6]]
t2 = [[7, 8, 9], [10, 11, 12]]
tf.concat(0郑诺,[t1, t2])
tf.concat(1,[t1, t2])
改為:
t1 = [[1, 2, 3], [4, 5, 6]]
t2 = [[7, 8, 9], [10, 11, 12]]
tf.concat([t1, t2], 0) ==> [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
tf.concat([t1, t2], 1) ==> [[1, 2, 3, 7, 8, 9], [4, 5, 6, 10, 11, 12]]
# tensor t3 with shape [2, 3]
# tensor t4 with shape [2, 3]
tf.shape(tf.concat([t3, t4], 0)) ==> [4, 3]
tf.shape(tf.concat([t3, t4], 1)) ==> [2, 6]
2 tensorflow常用操作
出處:http://blog.csdn.net/han_xiaoyang/article/details/51871068
內(nèi)容來自斯坦福大學(xué)CS224d課程的中文版內(nèi)容筆記整理杉武。
2.1.Tensorflow
首先提提Tensorflow和theano辙诞,它倆都是python封裝的深度學(xué)習(xí)庫,非常容易上手轻抱,說起來Tensorflow還是受Theano啟發(fā)飞涂,借鑒了一部分它的思想。不同之處在于十拣,Tensorflow 對分布式系統(tǒng)支持更好封拧,同時(shí)還是Google提供資金研發(fā)的,而Theano 是一個(gè)學(xué)術(shù)性質(zhì)的項(xiàng)目夭问。
Tensorflow 可以對定義在張量(tensors,你可以先簡單理解成標(biāo)量泽西、向量或者矩陣,一會(huì)兒會(huì)提到)上的函數(shù)自動(dòng)求導(dǎo)缰趋,因此神經(jīng)網(wǎng)絡(luò)中BP算法可以很輕松地實(shí)現(xiàn)捧杉。
在開始Tensorflow之前,需要先讓大家對Tensorflow的過程有個(gè)直觀的理解秘血。
在Tensorflow里:
使用張量(tensor)表示數(shù)據(jù).
使用圖(graph)來表示計(jì)算任務(wù).
在被稱之為會(huì)話(Session)的上下文 (context)中執(zhí)行圖.
通過變量 (Variable)維護(hù)狀態(tài).
使用feed和fetch可以為任意的操作(arbitrary operation)賦值或者從其中獲取數(shù)據(jù)味抖。
嚴(yán)格意義上來說TensorFlow算是一個(gè)編程系統(tǒng),它使用圖來表示計(jì)算任務(wù)灰粮,圖中的節(jié)點(diǎn)被稱之為operation(可以縮寫成op)仔涩,一個(gè)節(jié)點(diǎn)獲得0個(gè)或者多個(gè)張量(tensor,下文會(huì)介紹到)粘舟,執(zhí)行計(jì)算熔脂,產(chǎn)生0個(gè)或多個(gè)張量。TensorFlow的一個(gè)圖描述了一個(gè)計(jì)算過程柑肴,為了進(jìn)行計(jì)算霞揉,圖必須在會(huì)話(Session)里被啟動(dòng),會(huì)話(Session)將圖的op分發(fā)到CPU或GPU之類的設(shè)備上晰骑,同時(shí)提供執(zhí)行op的方法适秩,這些方法執(zhí)行后,將產(chǎn)生的張量(tensor)返回。返回的張量因語言不同而有不同秽荞,在python里是numpy ndarry對象骤公;在C/C++語言中,是tensorflow::Tensor實(shí)例蚂会。
下面咱們來詳細(xì)說說上面提到的概念淋样。
2.1.1 什么是張量
既然Tensorflow里面的定義和運(yùn)算都是基于張量這個(gè)概念,我們就先來看看胁住,什么是張量趁猴。
張量的正式定義:從向量空間到實(shí)數(shù)域的多重現(xiàn)性映射(multilinear maps)
(V是向量空間,V*是對偶空間)
- 標(biāo)量是張量(f: R→R彪见,f(e1) = c)(譯者注: 標(biāo)量是用實(shí)數(shù)表示零維空間的點(diǎn))
- 向量是張量(f: R^n→R儡司,f(ei) = c)(譯者注: 向量是用實(shí)數(shù)表示一維空間的點(diǎn),也即向量中的某個(gè)元素)
- 矩陣是張量(f: R^n * R^ m →R余指,f(ei,ej) = Aij)(譯者注: 矩陣是用實(shí)數(shù)表示二維空間的點(diǎn)捕犬,也即矩陣的某個(gè)元素)
- 通常來說,張量可以用多維數(shù)組來表示酵镜。
2.1.2 Tensorflow 與 Numpy
- 看似差別甚遠(yuǎn)的2個(gè)package碉碉,說起來可能也很少有人把這兩者作對比,但他們“長得”確實(shí)很相似(都是提供N維數(shù)組的庫)
- Numpy 有 Ndarray(N維數(shù)組) 支持淮韭,但不提供創(chuàng)建張量函數(shù)和自動(dòng)求導(dǎo)的方法垢粮,也不提供GPU支持
2.1.3 Numpy 與 Tensorflow 定義與操作對比
# numpy定義與操作
In [23]: import numpy as np
In [24]: a = np.zeros((2,2)); b = np.ones((2,2))
In [25]: np.sum(b, axis=1)
Out[25]: array([ 2., 2.])
In [26]: a.shape
Out[26]: (2, 2)
In [27]: np.reshape(a, (1,4))
Out[27]: array([[ 0., 0., 0., 0.]])
# 對應(yīng)的Tensorflow定義與操作
In [31]: import tensorflow as tf
In [32]: tf.InteractiveSession()
In [33]: a = tf.zeros((2,2)); b = tf.ones((2,2))
In [34]: tf.reduce_sum(b, reduction_indices=1).eval()
Out[34]: array([ 2., 2.], dtype=float32)
In [35]: a.get_shape()
Out[35]: TensorShape([Dimension(2), Dimension(2)])
In [36]: tf.reshape(a, (1, 4)).eval()
Out[36]: array([[ 0., 0., 0., 0.]], dtype=float32)
以上代碼中提到的 session和.eval()將在下文細(xì)述,而關(guān)于TensorShape靠粪,大家可以簡單理解成類似Python中tuple的類型蜡吧。
為了方便記憶,我們把numpy和Tensorflow中的部分定義和操作做成了一張一一對應(yīng)的表格占键,方便大家查看昔善。
Tensorflow的輸出要稍微注意一下,我們需要顯式地輸出(evaluation畔乙,也就是說借助eval()函數(shù))君仆!
In [37]: a = np.zeros((2,2))
In [38]: ta = tf.zeros((2,2))
In [39]: print(a)
[[ 0. 0.]
[ 0. 0.]]
In [40]: print(ta)
Tensor("zeros_1:0", shape=(2, 2), dtype=float32)
In [41]: print(ta.eval())
[[ 0. 0.]
[ 0. 0.]]
上面是一個(gè)示例的代碼,大家可以理解Tensorflow是通過計(jì)算圖(computation graph)定義一個(gè)計(jì)算過程的牲距,這個(gè)過程不產(chǎn)生數(shù)值結(jié)果袖订,那想看到具體內(nèi)容怎么辦呢?我們要借助.eval()函數(shù)輸出嗅虏。
2.1.4 Tensorflow 的計(jì)算圖
用Tensorflow編寫的程序一般由兩部分構(gòu)成,一是構(gòu)造部分上沐,包含了計(jì)算流圖皮服,二是執(zhí)行部分,通過session 來執(zhí)行圖中的計(jì)算,具體可以參考Tensorflow文檔
我們先來看看怎么構(gòu)建圖龄广。構(gòu)件圖的第一步是創(chuàng)建源節(jié)點(diǎn)
(source op)硫眯。源節(jié)點(diǎn)
不需要任何輸入,它的輸出傳遞給其它節(jié)點(diǎn)(op)做運(yùn)算择同。python庫中两入,節(jié)點(diǎn)構(gòu)造器的返回值即當(dāng)前節(jié)點(diǎn)的輸出,這些返回值可以傳遞給其它節(jié)點(diǎn)(op)作為輸入敲才。
TensorFlow Python庫中有一個(gè)默認(rèn)圖
(default graph)裹纳,在默認(rèn)圖的基礎(chǔ)上,節(jié)點(diǎn)構(gòu)造器(op 構(gòu)造器)
可以為其增加節(jié)點(diǎn)紧武。這個(gè)默認(rèn)圖對許多程序來說已經(jīng)足夠用了剃氧,更多管理視圖的細(xì)節(jié)可以閱讀官方Graph類文檔。
我們來看一個(gè)簡單的構(gòu)建圖例子:
import tensorflow as tf
# 創(chuàng)建一個(gè)常量節(jié)點(diǎn)阻星, 產(chǎn)生一個(gè)1x2矩陣朋鞍,這個(gè)op被作為一個(gè)節(jié)點(diǎn)
# 加到默認(rèn)視圖中
# 構(gòu)造器的返回值代表該常量節(jié)點(diǎn)的返回值
matrix1 = tf.constant([[3., 3.]])
# 創(chuàng)建另一個(gè)常量節(jié)點(diǎn), 產(chǎn)生一個(gè)2x1的矩陣
matrix2 = tf.constant([[2.], [2.]])
# 創(chuàng)建一個(gè)矩陣乘法matmul節(jié)點(diǎn),把matrix1和matrix2作為輸入:
product = tf.matmul(matrix1, matrix2)
上面代碼里的默認(rèn)圖現(xiàn)在有三個(gè)節(jié)點(diǎn)妥箕,兩個(gè)constant()節(jié)點(diǎn)和matmul() 節(jié)點(diǎn)滥酥。不過這僅僅是構(gòu)建圖,為了真正進(jìn)行矩陣的乘法畦幢,你必須在會(huì)話(Session坎吻,馬上提到)里啟動(dòng)這個(gè)圖。
2.1.5 Tensorflow與Session對象
上面我們知道了Tensorflow需要先構(gòu)造一個(gè)圖用于計(jì)算呛讲,但是圖怎么啟動(dòng)呢禾怠?啟動(dòng)圖的第一步需要?jiǎng)?chuàng)建一個(gè)Session對象。比如:
# 創(chuàng)建session贝搁,啟動(dòng)默認(rèn)圖
sess = tf.Session()
# 調(diào)用sess的'run()' 方法來執(zhí)行矩陣乘法節(jié)點(diǎn)操作吗氏,傳入'product'作為該方法的參數(shù)。
#'product'代表了矩陣乘法節(jié)點(diǎn)的輸出雷逆,傳入它是告訴方法我們希望取回矩陣乘法節(jié)點(diǎn)的輸出弦讽。
#整個(gè)執(zhí)行過程是自動(dòng)化的,會(huì)話負(fù)責(zé)傳遞節(jié)點(diǎn)所需的全部輸入膀哲。節(jié)點(diǎn)通常是并發(fā)執(zhí)行的往产。
# 函數(shù)調(diào)用'run(product)'會(huì)觸發(fā)圖中三個(gè)節(jié)點(diǎn)
#(上面例子里提到的兩個(gè)常量節(jié)點(diǎn)和一個(gè)矩陣乘法節(jié)點(diǎn))的執(zhí)行。
# 返回值'result'是一個(gè)numpy 'ndarray'對象某宪。
result = sess.run(product)
print result
# 結(jié)果為[[12.]]
# 完成任務(wù)仿村,記得關(guān)閉會(huì)話
sess.close()
Session對象在使用完成后,記得關(guān)閉以釋放資源兴喂,當(dāng)然蔼囊,除了顯式調(diào)用close關(guān)閉外焚志,也可以使用with代碼來自動(dòng)完成關(guān)閉動(dòng)作:
# 用with代碼來自動(dòng)完成session里的圖運(yùn)算并關(guān)閉
with tf.Session() as sess:
result = sess.run([product])
print result
為了便于使用像IPython這樣的python交互環(huán)境,可以使用InteractiveSession代替Session類畏鼓,使用Tensor.eval()和Operation.run()方法代替Session.run()酱酬。這樣做的好處是可以在ipython中保持默認(rèn)session處于打開狀態(tài):
# 進(jìn)入一個(gè)交互式Tensorflow會(huì)話
import tensorflow as tf
sess = tf.InteractiveSession()
x = tf.Variable([1.0, 2.0])
a = tf.constant([3.0, 3.0]);
# 使用初始化器的run()方法初始化x
x.initializer.run()
# 增加一個(gè)減法節(jié)點(diǎn),從x減去a云矫。運(yùn)行減法op膳沽,輸出結(jié)果
sub = tf.subtract(x, a)
print sub.eval()
# 結(jié)果為[-2. -1.]
2.1.6 關(guān)于session和多GPU運(yùn)算
我們一直在說,Tensorflow是支持分布式的深度學(xué)習(xí)框架/包让禀,這是因?yàn)樗軐D定義轉(zhuǎn)換成分布式執(zhí)行的操作挑社,以充分利用可以利用的計(jì)算資源(如CPU或GPU)。不過一般情況下堆缘,你不需要顯式指定使用CPU還是GPU滔灶,Tensorflow能自動(dòng)檢測。如果檢測到GPU吼肥,Tensorflow會(huì)優(yōu)先使用找到的第一個(gè)GPU來執(zhí)行操作录平。
如果機(jī)器上有超過一個(gè)可用的GPU,默認(rèn)狀況下除了第一個(gè)外的其他GPU是不參與計(jì)算的缀皱。為了讓Tensorflow使用這些GPU斗这,你必須將節(jié)點(diǎn)運(yùn)算明確地指派給它們執(zhí)行。其中with…Device語句用來指派特定的CPU或GPU操作:
# 手動(dòng)指定給某個(gè)gpu執(zhí)行
with tf.Session() as sess:
with tf.device("/gpu:1"):
matrix1 = tf.constant([[3., 3.]])
matrix2 = tf.constant([[2.], [2.]])
product = tf.matmul(matrix1, matrix2)
指定設(shè)備的書寫格式如下:
- /cpu:0:機(jī)器的CPU
- /gpu:0:機(jī)器的第一個(gè)GPU啤斗,如果有的話
- /gpu:1:機(jī)器的的第二個(gè)GPU表箭,其他GPU以此類推
2.1.7 Tensorflow的變量(Variables)
我們訓(xùn)練一個(gè)模型的時(shí)候,會(huì)用到Tensorflow中的變量(Variables)钮莲,我們需要它來保持和更新參數(shù)值免钻,和張量一樣,變量也保存在內(nèi)存緩沖區(qū)當(dāng)中崔拥。
有很多同學(xué)會(huì)問极舔,前面不是提到了一個(gè)概念叫做張量,為什么還需要這個(gè)新的變量呢链瓦?需要說明一下的是拆魏,如果大家仔細(xì)看之前的代碼,會(huì)發(fā)現(xiàn)我們所用到的張量都是常值張量(constant tensors)慈俯,而非變量渤刃,而參數(shù)值是需要?jiǎng)討B(tài)調(diào)整的內(nèi)容。
比如下面的代碼里我們設(shè)定了一組權(quán)重為變量:
In [32]: W1 = tf.ones((2,2))
In [33]: W2 = tf.Variable(tf.zeros((2,2)), name="weights")
In [34]: with tf.Session() as sess:
print(sess.run(W1))
sess.run(tf.global_variables_initializer())
print(sess.run(W2))
....:
[[ 1. 1.]
[ 1. 1.]]
[[ 0. 0.]
[ 0. 0.]]
說一個(gè)小細(xì)節(jié)贴膘,注意到上面第34步tf.global_variables_initializer()卖子,我們要預(yù)先對變量初始化(initialization)
Tensorflow 的變量必須先初始化然后才有值!而常值張量是不需要的
再具體一點(diǎn)刑峡,比如下面的代碼揪胃,其實(shí)38和39步璃哟,我們初始化定義初值是可以通過常數(shù)或者隨機(jī)數(shù)等任何一種方式初始化的,但是直到第40步才真正通過Tensorflow的global_variables_initializer()對這些變量賦初值喊递。
In [38]: W = tf.Variable(tf.zeros((2,2)), name="weights")
In [39]: R = tf.Variable(tf.random_normal((2,2)), name="random_weights")
In [40]: with tf.Session() as sess:
....: sess.run(tf.initialize_all_variables())
....: print(sess.run(W))
....: print(sess.run(R))
比如我們來看一個(gè)計(jì)算圖中變量的狀態(tài)更新過程,代碼如下:
In [63]: state = tf.Variable(0, name="counter")
In [64]: new_value = tf.add(state, tf.constant(1))
In [65]: update = tf.assign(state, new_value)
In [66]: with tf.Session() as sess:
sess.run(tf.initialize_all_variables())
print(sess.run(state))
for _ in range(3):
sess.run(update)
print(sess.run(state))
0
1
2
3
上面的代碼定義了一個(gè)如下的計(jì)算圖阳似,同時(shí)其中變量的狀態(tài)是循環(huán)變化的:
2.1.8 Tensorflow的Fetch(獲取)操作
如果想取回定義的計(jì)算圖中的節(jié)點(diǎn)運(yùn)算輸出結(jié)果骚勘,可以在使用Session對象的run()調(diào)用執(zhí)行圖時(shí),傳入一些張量撮奏,這些張量可以幫助你取回結(jié)果俏讹。而且不僅僅是單個(gè)節(jié)點(diǎn)的狀態(tài)或者結(jié)果,可以輸出多個(gè)節(jié)點(diǎn)的結(jié)果畜吊,比如下面這個(gè)簡單例子:
input1 = tf.constant(3.0)
input2 = tf.constant(4.0)
input3 = tf.constant(5.0)
intermed = tf.add(input2, input3)
mul = tf.mul(input1, intermed)
with tf.Session() as sess:
result = sess.run([mul, intermed])
print result
# print
# 輸出最后的乘法結(jié)果泽疆,和之前的加法結(jié)果[27.0, 9.0]
2.1.9 Tensorflow與Feed(傳入)操作
2.1.8里我們提到了在計(jì)算圖中引入張量,以獲取節(jié)點(diǎn)狀態(tài)或者輸出結(jié)果玲献。Tensorflow還提供了feed機(jī)制殉疼,該機(jī)制可以臨時(shí)替代圖中的任意操作中的張量,也就是說捌年,可以對圖中任何操作提交補(bǔ)丁瓢娜,直接插入一個(gè)新的張量。
feed可以使用一個(gè)張量值臨時(shí)替換某個(gè)操作的輸出結(jié)果礼预,你只需要提供feed數(shù)據(jù)作為run()調(diào)用的參數(shù)眠砾。需要說明的是,feed只在調(diào)用它的方法內(nèi)有效托酸,方法結(jié)束則feed就會(huì)消失褒颈。最常見的用例是將某些特殊的操作指定為feed操作,標(biāo)記的方法是使用tf.placeholder()為這些操作創(chuàng)建占位符(可以先想成一個(gè)容器励堡,這個(gè)在之后的內(nèi)容里會(huì)提到谷丸,不要著急)。
input1 = tf.placeholder(tf.types.float32)
input2 = tf.placeholder(tf.types.float32)
output = tf.mul(input1, input2)
# 手動(dòng)提供feed數(shù)據(jù)作為run的參數(shù)
with tf.Session() as see:
print sess.run([output], feed_dict={input:[7.]念秧, input2:[2.]})
# print
# 結(jié)果是[array([ 14.], dtype=float32)]