博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
tensorflow的基本认识
阅读量:7001 次
发布时间:2019-06-27

本文共 5264 字,大约阅读时间需要 17 分钟。

  版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖。如要转贴,必须注明原文网址  http://www.cnblogs.com/Colin-Cai/p/10741013.html   作者:窗户  QQ/微信:6679072  E-mail:6679072@qq.com

  tensorflow是一个很流行的计算框架,目前主要用来做深度学习。但实际上,tensorflow不仅仅可以做深度学习,理论上说任何算法都可以用tensorflow来描述,就在于它做了计算流图这样的抽象,而tensorflow这个名字实际上很自然流。其实提到计算流图,这样的抽象并不是tensorflow首作,计算模型中经常会有图计算,编译器中离开了这玩意玩不转,乃至我们平时的工程涉及到大的规模乃至需要需求模板化的时候,可能都离不开计算流图或者类似这样的模型。所以,其实它对于我们每个人并不是什么新鲜的玩意。 

  以下代码包括其注释说明了计算流图的建立以及使用,包含了对tensorflow的最基本概念认识。

#先要导入库import tensorflow as tf#建立session才可以进行图运算#实际上session只需要在计算前建立即可#但此处为了方便就先建立了s = tf.Session()

 

  建立计算图,包含了操作和张量。tensorflow内部带有各种操作,甚至自己也可以用C++来添加新的操作。

  以下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,表示要临时赋值的张量。

  以下s.run(d)其实等同于s.run(fetches=d)

#使用Session的方法run可以根据计算图计算需要的tensor#1*11+2*12+3*13+4*14=130#输出130print(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#输出1630print(s.run(d, feed_dict={a:list(range(31,35))}))#feed_dict可以一次修改多个tensor#41*51+42*52+43*53+44*54=8930#输出8930print(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#输出10print(s.run(d, feed_dict={c:list(range(1,5))}))#流图中d依赖于c更短,所以a的传入不影响计算#输出10print(s.run(d, feed_dict={a:list(range(11,15)), c:list(range(1,5))}))

 

  实际上,大多情况下,总是会有一些张量要在计算开始指定的,那么这些张量为constant已经失去意义,从而引入placeholder。

#引入placeholder,这样此处不需要constant#以下建立的张量为一阶张量,也就是向量,维度为4e = 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传值#输出10print(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))}))

 

  一个计算图中可以有多个placeholder

#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必须都传值#输出30print(s.run(h2, feed_dict={e2:list(range(1,5)), f2:list(range(1,5))}))

 

  上面placeholder在shape参数中定死了张量的形状,实际上可以不定死维数

#甚至可以只指定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")#输出30print(s.run(h3, feed_dict={e3:list(range(1,5)), f3:list(range(1,5))}))#元组当然没有问题#输出5print(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")#输出30print(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)#输出10s.run(y,feed_dict={x:[[1,2],[3,4]]})#输出36s.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赋值给变量mq=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模型,但不知道是用什么实现的。

转载于:https://www.cnblogs.com/Colin-Cai/p/10741013.html

你可能感兴趣的文章
2014最新open***搭建实例
查看>>
WinAPI: midiOutCachePatches - 预装音色
查看>>
finally执行顺序
查看>>
TWebBrowser 与 MSHTML(2): 获取 window 对象的时机
查看>>
【博客话题】IT人,你肿么了? ——除了IT,你还能选择什么?
查看>>
docker初步入门
查看>>
Outlook提示:无法安装或装载加载项vpmsece.dll
查看>>
使用Apache开源POI和jXLS两种API生成报表
查看>>
oracle控制台OEM无法启动
查看>>
haproxy负载均衡
查看>>
clink 让cmd像ubuntu gnome-terminal一样
查看>>
初识Java模板引擎Beetl之简单示例
查看>>
Oracle UNDO表空间的管理
查看>>
canal.deployer-1.1.0版本,当监听到数据库变动时,server端报异常,docker单核引起的问题...
查看>>
JAVA并发编程:干掉 Synchronized
查看>>
JAVA .class 文件防止反编译
查看>>
iOS-<UITabBarControllerDelegate> 代理不执行
查看>>
easyui实现datagrid列标题拖动
查看>>
CentOS 6.5系统安装配置LAMP(Apache+PHP5+MySQL)服务器环境
查看>>
在Websphere上修改项目的web.xml中的配置后不起作用
查看>>