【TensorFlow学习笔记】5:variable_scope和name_scope,图的基本操作

news/2024/9/28 19:44:34

学习《深度学习之TensorFlow》时的一些实践。


variable_scope

一般的嵌套

上节有学到在嵌套scope中的变量,一般是:

import tensorflow as tf

# with tf.variable_scope("scopeA") as spA:
#     var1 = tf.get_variable("v1", [1])

with tf.variable_scope("scopeB"):
    with tf.variable_scope("scopeA"):
        var3 = tf.get_variable("v3", [1])

print(var3.name)
scopeB/scopeA/v3:0

使不受外层影响

如果在其前便定义了内层scope,并将其传入tf.variable_scope中,即:

import tensorflow as tf

with tf.variable_scope("scopeA") as spA:
    var1 = tf.get_variable("v1", [1])

with tf.variable_scope("scopeB"):
    with tf.variable_scope(spA):
        var3 = tf.get_variable("v3", [1])

print(var3.name)
scopeA/v3:0

此时不受外层variable_scope的影响。

name_scope

运算结点既受到name_scope限制,也受到variable_scope限制,而Variable仅受到variable_scope限制。

注意,变量和运算结点虽然都是Tensor,但它们分别是:

<class 'tensorflow.python.ops.variables.Variable'>
<class 'tensorflow.python.framework.ops.Tensor'>

输出其type就能查看到,所以它们才会对不同的scope有不同的表现。

一般使用

with tf.variable_scope("v"):
    with tf.name_scope("n1"):
        a = tf.get_variable("a", [1])  # Variable
        x = 1.0 + a  # Op
        with tf.name_scope("n2"):
            y = 1.0 + a  # Op
print(a.name, x.op.name, y.op.name, sep='\n')
v/a:0
v/n1/add:0
v/n1/n2/add:0

返回顶层

当为name_scope指定空字符串时,其行为是使其作用域回到顶层,这个比较特殊。

with tf.variable_scope("v"):
    with tf.name_scope("n1"):
        a = tf.get_variable("a", [1])  # Variable
        x = 1.0 + a  # Op
        with tf.name_scope(""):
            y = 1.0 + a  # Op
            b = tf.get_variable("b", [1])  # Variable仅受到variable_scope的限制
print(a.name, x.op.name, y.op.name, b.name, sep='\n')
v/a:0
v/n1/add
add
v/b:0

因为b是一个Variable,仅受到variable_scope的限制,所以这个“回到顶层”对它不奏效。

图的基本操作

图即是一个计算任务,每个T程序默认就带一个计算图。

建立图

import tensorflow as tf

# 在TF默认的图上建立的常量Tensor
c = tf.constant(0.0)
print(c.graph)
<tensorflow.python.framework.ops.Graph object at 0x00000000032B99B0>
# 建立图g,并在它上面建立个常量Tensor
g = tf.Graph()
with g.as_default():
    c1 = tf.constant(0.0)
print(c1.graph)  # 可以通过变量的graph属性获取所在的图
print(g)
<tensorflow.python.framework.ops.Graph object at 0x000000000A611588>
<tensorflow.python.framework.ops.Graph object at 0x000000000A611588>
# 获取默认图,看看默认图是哪个
g2 = tf.get_default_graph()
print(g2)
<tensorflow.python.framework.ops.Graph object at 0x00000000032B99B0>
# 重置默认图,相当于重新建立了一个图
tf.reset_default_graph()  # 使用该函数时必须保证当前图的资源已经全部释放
g3 = tf.get_default_graph()
print(g3)
<tensorflow.python.framework.ops.Graph object at 0x000000000A611550>

获取图中的Tensor

这里是获取其中的常量Tensor,只要根据它的名称就可以将它取出。

import tensorflow as tf

g = tf.Graph()
with g.as_default():
    c = tf.constant(0.0)

print(c.name)
# 通过名称得到对应元素:通过Tensor的名称得到图中的c
t = g.get_tensor_by_name(name="Const:0")
print(c is t)
Const:0
True

不过我暂时还是不理解这样做有什么意义,可能是在某些情形下能访问到图却无法直接得到里面的变量吧。

获取图中的op

注意op是op包下的Tensor的属性,而不是Tensor本身!

import tensorflow as tf

# 两个常量Tensor
a = tf.constant([[1.0, 2.0]])
b = tf.constant([[1.0], [3.0]])
# 定义它们做矩阵乘法的操作
mymul = tf.matmul(a, b, name='mymul')
print(mymul.op.name)  # 注意这里是.op.name
# 因为这个op在默认图里,先获取到默认图
dft_g = tf.get_default_graph()
# 再从默认图里取出来
mymul_op = dft_g.get_operation_by_name(name="mymul")  # 注意这里没有':0'
mymul_tensor = dft_g.get_tensor_by_name(name="mymul:0")
print(mymul is mymul_op)
print(mymul_op is mymul_tensor)
print(mymul is mymul_tensor)
mymul
False
False
True

从这个例子中可以看到,前面定义的mymul看似是一个操作,其实它是一个Tensor而不是op,必须要访问其op属性得到的才是op,而get_operation_by_name得到的就是op,get_tensor_by_name得到的却是Tensor,这不一样,很容易弄混。

获取元素列表

import tensorflow as tf

g = tf.Graph()
with g.as_default():
    c = tf.constant(0.0)
    d = tf.constant(1.1)

ops = g.get_operations()
print(ops)
[<tf.Operation 'Const' type=Const>, <tf.Operation 'Const_1' type=Const>]

得到的是图g中的所有元素。

通过对象获取元素

前面是通过名字获取元素,这里是通过传入对象本身来获取元素,这就更搞不懂为什么了。。不过书上说这个函数有验证和转换的功能,在多线程中有时会用到。

g = tf.Graph()
with g.as_default():
    c1 = tf.constant(0.0)

c1_cpoy = g.as_graph_element(c1)
print(c1 is c1_cpoy)
True

相关学习资源

name_scope 与 variable_scope详解


http://www.niftyadmin.cn/n/1662881.html

相关文章

WPF中的资源(二) - 二进制资源

原文:WPF中的资源&#xff08;二&#xff09; - 二进制资源WPF中的二进制资源&#xff0c;就是类似于MFC中在对话框程序中添加的图片、字符串等资源&#xff0c;程序在运行时将其转换成二进制&#xff0c;以供程序使用。下面以将字符串转换成二进制为例来说明&#xff0c;二进制…

【Vue.js学习笔记】3:数据绑定,事件绑定

数据绑定 使用Vue时在Vue对象的el字段中要指定一下根容器&#xff0c;这里用id选择器。这个例子同时学习了data和methods的基本用法。 数据绑定&#xff08;data-binding&#xff09;可以将Vue对象中的data的值绑定到HTML标签中的某些位置&#xff0c;则修改时只需要修改对象…

Python的映射类型介绍

dict类型是Python语言的基石&#xff0c;至关重要。Python对它做了高度优化&#xff0c;散列表是字典类型性能出众个跟本原因。 collection.abc 模块里面有Mapping和MutableMapping这两个抽象基类&#xff0c;他们的作用为dict和类似的类型提供形式接口。其他的映射类型&#…

零基础入门MATLAB(一篇十分钟)

目录 一、复数 二、取整函数 三、无穷量&#xff08;Inf&#xff09;和非数值量&#xff08;NaN&#xff09; 四、逻辑类型 五、字符和字符串 六、函数句柄 七、结构体 八、数组类型 九、单元数组 十、map容器类型 参考《MATLAB R2020a 完全自学一本通》 一、复数 …

【Vue.js学习笔记】4:事件修饰符,键盘事件,键值修饰符

事件修饰符 在Vue的官方文档中给出了引入v-on:的事件修饰符的理念是&#xff0c;不希望在方法中去处理DOM细节。 事件冒泡 事件在事件源上发生&#xff0c;处理事件的方法并未绑定在该事件源上&#xff0c;事件就要向外或者向内传播&#xff08;propagation&#xff09;&…

(C/C++)线程基本概念、如何创建多线程

目录 一、线程基本概念 二、为什么使用多线程 1.避免阻塞 2.避免CPU空转 3.提升效率 三、创建线程函数 1.CreateThread 2._beginthreadex 四、简单多线程示例 一、线程基本概念 线程是在进程中产生的一个执行单元&#xff0c;是CPU调度和分配的最小单元&#xff0c;其…

【Vue.js学习笔记】5:双向数据绑定,计算属性

双向数据绑定 双向数据绑定往往会用到input、select、textarea等表单标签上&#xff0c;因为总是涉及一个数据数据的地方和输出数据的地方。 当数据发生变化的时候&#xff0c;视图也就发生变化&#xff0c;当视图发生变化的时候&#xff0c;数据也会跟着同步变化。 数据双向绑…

Python字典的setdefault()方法来处理找不到的键:统计记录每个单词出现的次数和坐标

字典的setdefault()方法&#xff0c;来处理找不到的键。 此方法总会让字典返回key对应的value&#xff0c;如果字典中有对应的key就从字典中取值&#xff0c;如果没有对应的key就会把value设置default&#xff0c;然后再返回。注意&#xff0c;这样字典中已经增加了新的键值对…