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模型,但不知道是用什么实现的。

相关文章
相关标签/搜索