tensorflow的基本認識

  版權申明:本文爲博主窗戶(Colin Cai)原創,歡迎轉帖。如要轉貼,必須註明原文網址

  http://www.cnblogs.com/Colin-Cai/p/10741013.html 

  做者:窗戶

  QQ/微信:6679072

  E-mail:6679072@qq.com

  tensorflow是一個很流行的計算框架,目前主要用來作深度學習。但實際上,tensorflow不只僅能夠作深度學習,理論上說任何算法均可以用tensorflow來描述,就在於它作了計算流圖這樣的抽象,而tensorflow這個名字實際上很天然流。其實提到計算流圖,這樣的抽象並非tensorflow首做,計算模型中常常會有圖計算,編譯器中離開了這玩意玩不轉,乃至咱們平時的工程涉及到大的規模乃至須要需求模板化的時候,可能都離不開計算流圖或者相似這樣的模型。因此,其實它對於咱們每一個人並非什麼新鮮的玩意。 html

  如下代碼包括其註釋說明了計算流圖的創建以及使用,包含了對tensorflow的最基本概念認識。算法

#先要導入庫
import tensorflow as tf

#創建session才能夠進行圖運算
#實際上session只須要在計算前創建便可
#但此處爲了方便就先創建了
s = tf.Session()

 

  創建計算圖,包含了操做和張量。tensorflow內部帶有各類操做,甚至本身也能夠用C++來添加新的操做。sql

  如下multipy和reduce_sum都是操做,其實constant也被當作是操做。微信

#如下是創建計算圖,tensorflow創建計算圖
#只是定義各個tensor之間的計算關係,並未開始計算
#每一個操做均可以帶一個名字,操做和張量之間是一對一的關係
#如下是兩個常量
a = tf.constant(list(range(1,5)), name="a")
b = tf.constant(list(range(11,15)), name="b")
#將兩個形狀同樣的張量依次按相同位置相乘
#獲得一個形狀同樣的張量
c = tf.multiply(a, b, name="c")
#將張量裏全部元素累和
d = tf.reduce_sum(c, name="d")

 

  不要被名字所誤導,以上並不產生計算,只是佈置流圖,或許tf.place(tf.multiply, a, b)這樣的名字可能更好一點^_^網絡

  在session裏使用run方法纔會產生真實的計算,run帶有兩個參數,一個是fetches,表示要計算的張量,一個是feed_dict,表示要臨時賦值的張量。session

  如下s.run(d)其實等同於s.run(fetches=d)框架

#使用Session的方法run能夠根據計算圖計算須要的tensor

#1*11+2*12+3*13+4*14=130
#輸出130
print(s.run(d))
#能夠選擇一組tensor
#輸出[array([1, 2, 3, 4], dtype=int32), array([11, 12, 13, 14], dtype=int32), array([11, 24, 39, 56], dtype=int32), 130]
print(s.run([a,b,c,d]))
#feed_dict能夠修改任何想傳入的tensor,此處但願修改a的傳入
#31*11+32*12+33*13+34*14=1630
#輸出1630
print(s.run(d, feed_dict={a:list(range(31,35))}))
#feed_dict能夠一次修改多個tensor
#41*51+42*52+43*53+44*54=8930
#輸出8930
print(s.run(d, feed_dict={a:list(range(41,45)), b:list(range(51,55))}))
#不是constant同樣能夠修改傳入
#此時計算c不依賴於a和b
#1+2+3+4+5=10
#輸出10
print(s.run(d, feed_dict={c:list(range(1,5))}))
#流圖中d依賴於c更短,因此a的傳入不影響計算
#輸出10
print(s.run(d, feed_dict={a:list(range(11,15)), c:list(range(1,5))}))

 

  實際上,大多狀況下,老是會有一些張量要在計算開始指定的,那麼這些張量爲constant已經失去意義,從而引入placeholder。學習

#引入placeholder,這樣此處不須要constant
#如下創建的張量爲一階張量,也就是向量,維度爲4
e = tf.placeholder(tf.int32, shape=[4], name="e")
f = tf.constant(list(range(1,5)), name="f")
g = tf.multiply(e, f, name="g")
h = tf.reduce_sum(g, name="h")
#h的計算最終依賴於e這個placeholder
#而若是依賴的placeholder若是不傳值,則不可運算
#如下會產生異常
try:
    print(s.run(h))
except:
    print("EROR HERE!")
#給placeholder傳值
#輸出10
print(s.run(h, feed_dict={e:list(range(1,5))}))
#a,b,c,d的計算和h的計算是兩ge獨立的計算連通圖
#但依然能夠一塊兒計算
#輸出[array([1, 2, 3, 4], dtype=int32), array([11, 12, 13, 14], dtype=int32), array([11, 24, 39, 56], dtype=int32), 130, 30]
print(s.run([a,b,c,d,h], feed_dict={e:list(range(1,5))}))

 

  一個計算圖中能夠有多個placeholderfetch

#placeholder能夠創建多個
e2 = tf.placeholder(tf.int32, shape=[4], name="e2")
f2 = tf.placeholder(tf.int32, shape=[4], name="f2")
g2 = tf.multiply(e2, f2, name="g2")
h2 = tf.reduce_sum(g2, name="h2")
#要計算h2,依賴的兩個placeholder必須都傳值
#輸出30
print(s.run(h2, feed_dict={e2:list(range(1,5)), f2:list(range(1,5))}))

 

  上面placeholder在shape參數中定死了張量的形狀,實際上能夠不定死維數spa

#甚至能夠只指定placeholder是幾階張量,而不指定維度數
e3 = tf.placeholder(tf.int32, shape=[None], name="e3")
f3 = tf.placeholder(tf.int32, shape=[None], name="f3")
g3 = tf.multiply(e3, f3, name="g3")
h3 = tf.reduce_sum(g3, name="h3")
#輸出30
print(s.run(h3, feed_dict={e3:list(range(1,5)), f3:list(range(1,5))}))
#元組固然沒有問題
#輸出5
print(s.run(h3, feed_dict={e3:(1,2), f3:(1,2)}))

 

  二階張量固然也能夠,同理三階、四階...都是能夠得

#一階張量能夠,二階張量固然沒有問題
e4 = tf.placeholder(tf.int32, shape=[None, None], name="e4")
f4 = tf.placeholder(tf.int32, shape=[None, None], name="f4")
g4 = tf.multiply(e4, f4, name="g4")
h4 = tf.reduce_sum(g4, name="h4")
#輸出30
print(s.run(h4, feed_dict={e4:[[1,2],[3,4]], f4:[[1,2],[3,4]]}))
#經過名字也能夠找到張量
_e4 = tf.get_default_graph().get_tensor_by_name("e4:0")
_f4 = tf.get_default_graph().get_tensor_by_name("f4:0")
_g4 = tf.get_default_graph().get_tensor_by_name("g4:0")
_h4 = tf.get_default_graph().get_tensor_by_name("h4:0")
#輸出[array([[ 100,  400],[ 900, 1600]], dtype=int32), 3000]
print(s.run([_g4, _h4], feed_dict={_e4:[[10,20],[30,40]], _f4:[[10,20],[30,40]]}))

 

  甚至,placeholder不指定張量階數也是沒有問題的。

x = tf.placeholder(tf.int32)
y = tf.reduce_sum(x)
#輸出10
s.run(y,feed_dict={x:[[1,2],[3,4]]})
#輸出36
s.run(y,feed_dict={x:[[[1,2],[3,4]], [[5,6],[7,8]]]})

 

  以上提到的計算圖自己不帶有記憶,從而能夠引入帶有記憶的計算圖,那就是須要引入變量(variable)概念,也就是能夠把一些張量定義爲變量。

#引入變量,從而但願在內存中常駐,以便修改
m=tf.Variable(list(range(1,3)), name="m")
n=tf.reduce_sum(m, name="n")
p=tf.add(m, n, name="p")
#把p賦值給變量m
q=tf.assign(m, p, name="q")
#當使用變量的時候,須要利用這個將變量初始化一下
s.run(tf.global_variables_initializer())
#[1,2]求和爲3,[1,2]加3獲得[4,5],賦值給m
#輸出[4 5]
print(s.run(q))
#[4,5]求和爲9,[4,5]加9獲得[13,14],賦值給m
#輸出[13 14]
print(s.run(q))

 

  變量一旦形狀肯定,是不能進行調整的。

try:
    #concat是把兩個張量拼接,從而張量的維度發生了變化
    #而m2做爲變量,一開始形狀就被肯定,assign是不能對形狀金勳哥調整的
    #從而這裏會發生異常
    m2=tf.Variable([1,2], expected_shape=[None],dtype=tf.int32)
    n2=tf.reduce_sum(m2)
    p2=tf.add(m2,n2)
    r2=tf.concat([m2,p2],0)
    q2=tf.assign(m2,r2)
    s.run(tf.global_variables_initializer())
    s.run(q2)
except:
    print("ERROR HERE!")

 

  或許只能用如下方法?

#我能想到的只好用如下方法來實現改變形狀
m3=tf.placeholder(tf.int32, shape=[None], name="m3")
n3=tf.reduce_sum(m3, name="n3")
p3=tf.add(m3, n3, name="p2")
r3=tf.concat([m3,p3], 0, name="r3")
#輸出[1 2 4 5]
x=s.run(r3, feed_dict={m3:[1,2]})
print(x)
#輸出[1 2 4 5 13 14 16 17]
x=s.run(r3, feed_dict={m3:x})
print(x)

 

 

  關於以上變量的維度一旦肯定,就沒法改變,多是由於tensorflow一開始就分配好了內存。我就想,若是將來出現那種結構不斷調整的AI模型該怎麼辦,彷佛前段時間據說了已經出現了不斷在調整尺寸的基於神經網絡的AI模型,但不知道是用什麼實現的。

相關文章
相關標籤/搜索