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

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

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

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

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

  以下multipy和reduce_sum都是操作,其实constant也被看成是操作。

  1. #以下是建立计算图,tensorflow建立计算图
  2. #只是定义各个tensor之间的计算关系,并未开始计算
  3. #每个操作都可以带一个名字,操作和张量之间是一对一的关系
  4. #以下是两个常量
  5. a = tf.constant(list(range(1,5)), name="a")
  6. b = tf.constant(list(range(11,15)), name="b")
  7. #将两个形状一样的张量依次按相同位置相乘
  8. #得到一个形状一样的张量
  9. c = tf.multiply(a, b, name="c")
  10. #将张量里所有元素累和
  11. 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)

  1. #使用Session的方法run可以根据计算图计算需要的tensor
  2.  
  3. #1*11+2*12+3*13+4*14=130
  4. #输出130
  5. print(s.run(d))
  6. #可以选择一组tensor
  7. #输出[array([1, 2, 3, 4], dtype=int32), array([11, 12, 13, 14], dtype=int32), array([11, 24, 39, 56], dtype=int32), 130]
  8. print(s.run([a,b,c,d]))
  9. #feed_dict可以修改任何想传入的tensor,此处希望修改a的传入
  10. #31*11+32*12+33*13+34*14=1630
  11. #输出1630
  12. print(s.run(d, feed_dict={a:list(range(31,35))}))
  13. #feed_dict可以一次修改多个tensor
  14. #41*51+42*52+43*53+44*54=8930
  15. #输出8930
  16. print(s.run(d, feed_dict={a:list(range(41,45)), b:list(range(51,55))}))
  17. #不是constant一样可以修改传入
  18. #此时计算c不依赖于a和b
  19. #1+2+3+4+5=10
  20. #输出10
  21. print(s.run(d, feed_dict={c:list(range(1,5))}))
  22. #流图中d依赖于c更短,所以a的传入不影响计算
  23. #输出10
  24. print(s.run(d, feed_dict={a:list(range(11,15)), c:list(range(1,5))}))

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

  1. #引入placeholder,这样此处不需要constant
  2. #以下建立的张量为一阶张量,也就是向量,维度为4
  3. e = tf.placeholder(tf.int32, shape=[4], name="e")
  4. f = tf.constant(list(range(1,5)), name="f")
  5. g = tf.multiply(e, f, name="g")
  6. h = tf.reduce_sum(g, name="h")
  7. #h的计算最终依赖于e这个placeholder
  8. #而如果依赖的placeholder如果不传值,则不可运算
  9. #以下会产生异常
  10. try:
  11. print(s.run(h))
  12. except:
  13. print("EROR HERE!")
  14. #给placeholder传值
  15. #输出10
  16. print(s.run(h, feed_dict={e:list(range(1,5))}))
  17. #a,b,c,d的计算和h的计算是两ge独立的计算连通图
  18. #但依然可以一起计算
  19. #输出[array([1, 2, 3, 4], dtype=int32), array([11, 12, 13, 14], dtype=int32), array([11, 24, 39, 56], dtype=int32), 130, 30]
  20. print(s.run([a,b,c,d,h], feed_dict={e:list(range(1,5))}))

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

  1. #placeholder可以建立多个
  2. e2 = tf.placeholder(tf.int32, shape=[4], name="e2")
  3. f2 = tf.placeholder(tf.int32, shape=[4], name="f2")
  4. g2 = tf.multiply(e2, f2, name="g2")
  5. h2 = tf.reduce_sum(g2, name="h2")
  6. #要计算h2,依赖的两个placeholder必须都传值
  7. #输出30
  8. print(s.run(h2, feed_dict={e2:list(range(1,5)), f2:list(range(1,5))}))

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

  1. #甚至可以只指定placeholder是几阶张量,而不指定维度数
  2. e3 = tf.placeholder(tf.int32, shape=[None], name="e3")
  3. f3 = tf.placeholder(tf.int32, shape=[None], name="f3")
  4. g3 = tf.multiply(e3, f3, name="g3")
  5. h3 = tf.reduce_sum(g3, name="h3")
  6. #输出30
  7. print(s.run(h3, feed_dict={e3:list(range(1,5)), f3:list(range(1,5))}))
  8. #元组当然没有问题
  9. #输出5
  10. print(s.run(h3, feed_dict={e3:(1,2), f3:(1,2)}))

  二阶张量当然也可以,同理三阶、四阶...都是可以得

  1. #一阶张量可以,二阶张量当然没有问题
  2. e4 = tf.placeholder(tf.int32, shape=[None, None], name="e4")
  3. f4 = tf.placeholder(tf.int32, shape=[None, None], name="f4")
  4. g4 = tf.multiply(e4, f4, name="g4")
  5. h4 = tf.reduce_sum(g4, name="h4")
  6. #输出30
  7. print(s.run(h4, feed_dict={e4:[[1,2],[3,4]], f4:[[1,2],[3,4]]}))
  8. #通过名字也可以找到张量
  9. _e4 = tf.get_default_graph().get_tensor_by_name("e4:0")
  10. _f4 = tf.get_default_graph().get_tensor_by_name("f4:0")
  11. _g4 = tf.get_default_graph().get_tensor_by_name("g4:0")
  12. _h4 = tf.get_default_graph().get_tensor_by_name("h4:0")
  13. #输出[array([[ 100, 400],[ 900, 1600]], dtype=int32), 3000]
  14. print(s.run([_g4, _h4], feed_dict={_e4:[[10,20],[30,40]], _f4:[[10,20],[30,40]]}))

  甚至,placeholder不指定张量阶数也是没有问题的。

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

  以上提到的计算图本身不带有记忆,从而可以引入带有记忆的计算图,那就是需要引入变量(variable)概念,也就是可以把一些张量定义为变量。

  1. #引入变量,从而希望在内存中常驻,以便修改
  2. m=tf.Variable(list(range(1,3)), name="m")
  3. n=tf.reduce_sum(m, name="n")
  4. p=tf.add(m, n, name="p")
  5. #把p赋值给变量m
  6. q=tf.assign(m, p, name="q")
  7. #当使用变量的时候,需要利用这个将变量初始化一下
  8. s.run(tf.global_variables_initializer())
  9. #[1,2]求和为3,[1,2]加3得到[4,5],赋值给m
  10. #输出[4 5]
  11. print(s.run(q))
  12. #[4,5]求和为9,[4,5]加9得到[13,14],赋值给m
  13. #输出[13 14]
  14. print(s.run(q))

  变量一旦形状确定,是不能进行调整的。

  1. try:
  2. #concat是把两个张量拼接,从而张量的维度发生了变化
  3. #而m2作为变量,一开始形状就被确定,assign是不能对形状金勋哥调整的
  4. #从而这里会发生异常
  5. m2=tf.Variable([1,2], expected_shape=[None],dtype=tf.int32)
  6. n2=tf.reduce_sum(m2)
  7. p2=tf.add(m2,n2)
  8. r2=tf.concat([m2,p2],0)
  9. q2=tf.assign(m2,r2)
  10. s.run(tf.global_variables_initializer())
  11. s.run(q2)
  12. except:
  13. print("ERROR HERE!")

  或许只能用以下方法?

  1. #我能想到的只好用以下方法来实现改变形状
  2. m3=tf.placeholder(tf.int32, shape=[None], name="m3")
  3. n3=tf.reduce_sum(m3, name="n3")
  4. p3=tf.add(m3, n3, name="p2")
  5. r3=tf.concat([m3,p3], 0, name="r3")
  6. #输出[1 2 4 5]
  7. x=s.run(r3, feed_dict={m3:[1,2]})
  8. print(x)
  9. #输出[1 2 4 5 13 14 16 17]
  10. x=s.run(r3, feed_dict={m3:x})
  11. print(x)

  关于以上变量的维度一旦确定,就无法改变,可能是因为tensorflow一开始就分配好了内存。我就想,如果未来出现那种结构不断调整的AI模型该怎么办,似乎前段时间听说了已经出现了不断在调整尺寸的基于神经网络的AI模型,但不知道是用什么实现的。

tensorflow的基本认识的更多相关文章

  1. Tensorflow 官方版教程中文版

    2015年11月9日,Google发布人工智能系统TensorFlow并宣布开源,同日,极客学院组织在线TensorFlow中文文档翻译.一个月后,30章文档全部翻译校对完成,上线并提供电子书下载,该 ...

  2. tensorflow学习笔记二:入门基础

    TensorFlow用张量这种数据结构来表示所有的数据.用一阶张量来表示向量,如:v = [1.2, 2.3, 3.5] ,如二阶张量表示矩阵,如:m = [[1, 2, 3], [4, 5, 6], ...

  3. 用Tensorflow让神经网络自动创造音乐

    #————————————————————————本文禁止转载,禁止用于各类讲座及ppt中,违者必究————————————————————————# 前几天看到一个有意思的分享,大意是讲如何用Ten ...

  4. tensorflow 一些好的blog链接和tensorflow gpu版本安装

    pading :SAME,VALID 区别  http://blog.csdn.net/mao_xiao_feng/article/details/53444333 tensorflow实现的各种算法 ...

  5. tensorflow中的基本概念

    本文是在阅读官方文档后的一些个人理解. 官方文档地址:https://www.tensorflow.org/versions/r0.12/get_started/basic_usage.html#ba ...

  6. kubernetes&tensorflow

    谷歌内部--Borg Google Brain跑在数十万台机器上 谷歌电商商品分类深度学习模型跑在1000+台机器上 谷歌外部--Kubernetes(https://github.com/kuber ...

  7. tensorflow学习

    tensorflow安装时遇到gcc: error trying to exec 'as': execvp: No such file or directory. 截止到2016年11月13号,源码编 ...

  8. 【转】TensorFlow练习20: 使用深度学习破解字符验证码

    验证码是根据随机字符生成一幅图片,然后在图片中加入干扰象素,用户必须手动填入,防止有人利用机器人自动批量注册.灌水.发垃圾广告等等 . 验证码的作用是验证用户是真人还是机器人:设计理念是对人友好,对机 ...

  9. 【转】机器学习教程 十四-利用tensorflow做手写数字识别

    模式识别领域应用机器学习的场景非常多,手写识别就是其中一种,最简单的数字识别是一个多类分类问题,我们借这个多类分类问题来介绍一下google最新开源的tensorflow框架,后面深度学习的内容都会基 ...

  10. 【转】Ubuntu 16.04安装配置TensorFlow GPU版本

    之前摸爬滚打总是各种坑,今天参考这篇文章终于解决了,甚是鸡冻\(≧▽≦)/,电脑不知道怎么的,安装不了16.04,就安装15.10再升级到16.04 requirements: Ubuntu 16.0 ...

随机推荐

  1. Hive的原理

    阅读目录 一.Hive内部表和外部表 1.Hive的create创建表的时候,选择的创建方式: - create table - create external table 2.特点: ● 在导入数据 ...

  2. 【原】无脑操作:Centos 7后台运行及终止jar包程序

    1.后台运行jar包程序,输入:nohup java -jar /路径/程序.jar & 2.后台终止jar包程序,输入:ps -ef | grep java,查看使用java命令的进程,再输 ...

  3. Scanner类详解

    Scanner类用于获取键盘输入(是一个基于正则表达式的文本扫描器),它可以从文件.字符串.输入流中解析出基本类型值和字符串值.Scanner类提供了多个构造器,不同的构造器可以接收文件.字符串和输入 ...

  4. Exception: Exception caught in workbook destructor. Explicit close() may be required for workbook. 错误解决办法

    # 写入表格 writer = pd.ExcelWriter('data.xlsx') new_df.to_excel(writer, sheet_name='sheet', index=True) ...

  5. Java数据结构和算法 - 链表

    Q: 为什么要引入链表的概念?它是解决什么问题的? A: 数组作为数据存储结构有一定的缺陷,在无序数组中,搜索是低效的:而在有序数组中,插入效率又很低:不管在哪一个数组中删除效率都很低:况且一个数组创 ...

  6. Spring之旅第五篇-AOP详解

    一.什么是AOP? Aspect oritention programming(面向切面编程),AOP是一种思想,高度概括的话是“横向重复,纵向抽取”,如何理解呢?举个例子:访问页面时需要权限认证,如 ...

  7. AndroidManifest设置android:allowBackup="false"报错

    概述 设置android:allowBackup="false"的必要性 Android API Level 8及其以上Android系统提供了为应用程序数据的备份和恢复功能,此功 ...

  8. centos安装rabbitmq

    RabbitMQ是流行的开源消息队列系统,是AMQP(Advanced Message Queuing Protocol高级消息队列协议)的标准实现,用erlang语言开发.RabbitMQ据说具有良 ...

  9. unity中ScriptableObject在assetbundle中的加载

    转载请标明出处:http://www.cnblogs.com/zblade/ 以前都是写一些个人的调研博客,从今天开始,也写一些个人在开发中遇到的一些可以分享的趟坑博客,为后续的开发人员提供一些绵薄之 ...

  10. 从B站的代码泄露事件中,我们能学到些什么?

    先声明一下,本文不聊ISSUE中的七七八八,也不聊代码是否写的好,更不聊是不是跟蔡徐坤有关之类的吃瓜内容.仅站在技术人的角度,从这次的代码泄露事件,聊聊在代码的安全管理上,通常都需要做哪些事来预防此类 ...