什么是TensorBoard?
这篇文章主要讲讲TensorBoard的基本使用以及name_scope和variable_scope
的区别
一、入门TensorBoard
首先来讲讲TensorBoard是什么吧,我当时是在官方文档里学习的,官网也放出了介绍TensorBoard的视频。我在b站搜了一把,发现也有,大家可以先去看看视频了解一下(其实已经说得很好了):
为了更方便 TensorFlow 程序的理解、调试与优化,于是就有了TensorBoard 这样的的可视化工具
因为我们编写出来的TensorFlow程序,建好一个神经网络,其实我们也不知道神经网络里头具体细节到底做了什么,要人工调试十分困难(就好比你无法想象出递归的所有步骤一样)。有了TensorBoard,可以将TensorFlow程序的执行步骤都显示出来,非常直观。并且,我们可以对训练的参数(比如loss值)进行统计,用图的方式来查看变化的趋势。
1.1 name_scope和variable_scope
在视频中其实也有提到,我们想要TensorBoard的图能够更好地展示(更加有条理),那一般我们需要对其用name_scope
取名。
那除了name_scope
,还有一个叫做variable_scope
。那他们有什么区别呢?顾名思义,name_scope
是一个名称作用域,variable_scope
是变量作用域。
在前面文章中,创建变量有两种方式,一种是用tf.get_variable()
来创建,一种是用tf.Variable()
来创建。这两种创建方式也是有区别的。
- 在
tf.name_scope
下时,tf.get_variable()
创建的变量名不受name_scope
的影响,而且在未指定共享变量时,如果重名就会报错。tf.Variable()
会自动检测有没有变量重名,如果有则会自行处理(自动创建一个)
比如下面的代码:
with tf.name_scope('name_sp1') as scp1: with tf.variable_scope('var_scp2') as scp2: with tf.name_scope('name_scp3') as scp3: a = tf.Variable('a') b = tf.get_variable('b')
等同于:
with tf.name_scope('name_sp1') as scp1: with tf.name_scope('name_sp2') as scp2: with tf.name_scope('name_scp3') as scp3: a = tf.Variable('a') with tf.variable_scope('var_scp2') as scp2: b = tf.get_variable('b')
这里体现的是如果用get_variable
的方式来创建对象,是不受name_scope
所影响的。
要注意的是,下面的代码会报错。因为在scp作用域下压根就没有a这个变量,同时又设置成reuse=True
。这里因为的是找不到共享变量而出错!
with tf.variable_scope('scp', reuse=True) as scp: a = tf.get_varialbe('a') #报错
同样地,下面的代码也会报错,因为明明已经有共享变量了,但设置成reuse=false
。所以就会报错。
with tf.variable_scope('scp', reuse=False) as scp: a = tf.get_varialbe('a') a = tf.get_varialbe('a') #报错
最后,我们再来看这个例子,应该就可以看懂了。
with tf.variable_scope('variable_scope_y') as scope: var1 = tf.get_variable(name='var1', shape=[1], dtype=tf.float32) scope.reuse_variables() # 设置共享变量 var1_reuse = tf.get_variable(name='var1') var2 = tf.Variable(initial_value=[2.], name='var2', dtype=tf.float32) var2_reuse = tf.Variable(initial_value=[2.], name='var2', dtype=tf.float32) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print(var1.name, sess.run(var1)) print(var1_reuse.name, sess.run(var1_reuse)) print(var2.name, sess.run(var2)) print(var2_reuse.name, sess.run(var2_reuse)) # 输出结果: # variable_scope_y/var1:0 [-1.59682846] # variable_scope_y/var1:0 [-1.59682846] 可以看到变量var1_reuse重复使用了var1 # variable_scope_y/var2:0 [ 2.] # variable_scope_y/var2_1:0 [ 2.]
参考资料:
1.2 TensorBoard例子
下面我们来看一个TensorBoard简单的入门例子,感受一下:
def learn_tensor_board_2(): # prepare the original data with tf.name_scope('data'): x_data = np.random.rand(100).astype(np.float32) y_data = 0.3 * x_data + 0.1 ##creat parameters with tf.name_scope('parameters'): with tf.name_scope('weights'): weight = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) tf.summary.histogram('weight', weight) with tf.name_scope('biases'): bias = tf.Variable(tf.zeros([1])) tf.summary.histogram('bias', bias) ##get y_prediction with tf.name_scope('y_prediction'): y_prediction = weight * x_data + bias ##compute the loss with tf.name_scope('loss'): loss = tf.reduce_mean(tf.square(y_data - y_prediction)) tf.summary.scalar('loss', loss) ##creat optimizer optimizer = tf.train.GradientDescentOptimizer(0.5) # creat train ,minimize the loss with tf.name_scope('train'): train = optimizer.minimize(loss) # creat init with tf.name_scope('init'): init = tf.global_variables_initializer() ##creat a Session sess = tf.Session() # merged merged = tf.summary.merge_all() ##initialize writer = tf.summary.FileWriter("/Users/zhongfucheng/tensorboard/loss-2", sess.graph) sess.run(init) ## Loop for step in range(201): sess.run(train) rs = sess.run(merged) writer.add_summary(rs, step) if __name__ == '__main__': learn_tensor_board_2() # 启动完了之后,要在命令行上运行tensor_board的命令,指定其目录,最后我们就可以通过6006的默认端口访问我们的图。
(例子来源网络,我改动了一下,出处我忘了,侵删~)
接下来,我们启动一下TensorBoard,看看图是怎么样的,启动命令如下:
tensorboard --logdir=/Users/zhongfucheng/tensorboard/loss-2
启动成功的图:
通过6006端口我们去访问一下,首先我们可以检测到loss值的变更:
我们也可以查看TensorFlow程序大概的执行步骤:
参数w和b的直方图:
总之,TensorBoard可以方便地查看我们参数的变化,以便更好理解我们写的代码。
文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
大数据专业适合考研吗?
我们教授说,大数据这个专业注重于实战,除非想做理论专家,就不建议考研。所以,究竟是不是这样呢?" 哪个专业不重视实战呢? 所谓纯理论的专业, 工作后也是实战啊。 但是... 大数据专业目前是构架在计算机、统计学、数学之上的应用学科不假,但是其本身也有很多值得提升的地方,是大学四年所不能完全cover的,即便是cover到的地方,也不够精深。 大数据处理,停留在模型应用上是比较初级的,不熟识模型原理是不可能做出高质量成果来的。其实我并不主张在本科开设大数据专业,基础课程容易面面俱到而不牢固,容易搞成大杂烩。 所以既然在本科学了大数据专业,比较理想的方式是再到研究生以上层面进行专项精深的修炼,选择一个方向比如图像识别、自然语言理解等等,磨出刀尖来。 数据科学与大数据技术 这个专业名称,听起来就有点把采矿、冶炼、机械三合一的感觉。以如下课程设置为例: C程序设计、数据结构、数据库原理与应用、计算机操作系统、计算机网络、Java语言程序设计、Python语言程序设计,大数据算法、人工智能、应用统计(统计学)、大数据机器学习、数据建模、大数据平台核心技术、大数据分析与处理,大数据管理、大数据...
- 下一篇
左神算法、牛客网算法、剑指java、Java后台面试宝典----个人总结(实习、春招、秋招)
第一节课 第一题:题意与leetcode354的问题相同算法原型 最长递增子序列问题 * 题意:求出给定序列的最长递增子序列的长度,给定序列不是有序的,子序列不是子数组,元素在原数组中不必是连续的 * */ /* * solutions1: 时间复杂度O(n^2),空间复杂度O(n) * 新建一个辅助数组h,h[i]表示以nums[i]结尾的最长递增子序列的长度 * h[i]值的确定,需要nums[i]与nums[j](0<=j<i)做比较,h[i] = h[j] + 1 (when nums[j] < nums[i]),找出这些值中的最大值即最终的nums[i] * 如果nums[i]最小的话,则h[i] = 1; * 因为h[i]值的确定需要nums[i]进行最多i-1次比较,所以时间复杂度为O(n^2) */ /* * solution2: 时间复杂度O(n*log(n)),空间复杂度O(n) * 新建一个辅助数组h,h[i]表示遍历到当前nums[j]位置时长度为i+1的递增子序列的最小末尾 * h填入值的部分称作有效区,还未填入值的部分称作无效区 * h[i...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果