tensorflow的小回顾

好久不用了,回顾了一下,就当记个笔记吧

首先是看了这为朋友的博客https://blog.csdn.net/Jerr__y/article/details/78114452

然后呢,这是TensorFlow的官方文档  http://wiki.jikexueyuan.com/project/tensorflow-zh/get_started/basic_usage.html

1.  关于tensor数据类型的一些操作

tensor (也就是通常说的张量)是tf中所特有的一种数据类型,我们知道图像处理其实很大程度上可以看做矩阵之间的运算,这个tensor类型我们也可以将其看做是tensorflow是中参与计算的n维矩阵。

我们对于tensor的刻画往往基于它的三个属性,维数(也就是阶)、形状和数据类型。

关于阶的定义我们很好理解,和我们常见的数组(一阶)和矩阵(二阶)其实是一样的,

1    #维度为0的标量
[1,2,3]   #维度为1,一维向量
[[1,2],[3,4]]   #维度为2, 二维矩阵
[[[1,2],[3,4]],[[1,2],[3,4]]]   #维度为3,3维空间矩阵

关于形状(也就是常见的shape)的描述稍微有些模糊,和阶有些相似。我们看一下:

关于他们两个人的区别也只能是意会了,哈哈。

1    # 形状为[]
[1,2,3]   # 形状为[3]
[[1,2],[3,4]]   # 形状为[2,2]
[[[1,2],[3,4]],[[1,2],[3,4]]]   # 形状为[2,2,2]

第三个描述tensor的属性是它的数据类型,我们常见的绝大多数类型都能在这里找到,只不过要在前面加上tf.

数据类型       Python 类型       描述
DT_FLOAT    tf.float32    32 位浮点数.
DT_DOUBLE    tf.float64    64 位浮点数.
DT_INT64    tf.int64    64 位有符号整型.
DT_INT32    tf.int32    32 位有符号整型.
DT_INT16    tf.int16    16 位有符号整型.
DT_INT8    tf.int8    8 位有符号整型.
DT_UINT8    tf.uint8    8 位无符号整型.
DT_STRING    tf.string    可变长度的字节数组.每一个张量元素都是一个字节数组.
DT_BOOL    tf.bool    布尔型.
DT_COMPLEX64    tf.complex64    由两个32位浮点数组成的复数:实数和虚数.
DT_QINT32    tf.qint32    用于量化Ops的32位有符号整型.
DT_QINT8    tf.qint8    用于量化Ops的8位有符号整型.
DT_QUINT8    tf.quint8    用于量化Ops的8位无符号整型.
--------------------- 
 

OK,经过上面的介绍,我们现在已经可以自由的定义参与计算的数据了。所谓的tensorflow,不仅有tensor 还要让他flow起来,那么它要如何flow呢?,我们来看

这张图所要表达的就是将我们之前定义的各个tensor类型的数组送到相应的操作当中来完成计算,这样就构成了tensorflow的一张完整的计算图,表达的貌似不太明确,我们来看一下实例

a = tf.constant(1, dtype=tf.int8)
b = tf.constant(2, dtype=tf.int8)
res= a + b

这就是一个简单的计算图的构建过程,他包括了tensor的构建与图的形成(所谓图的形成就是定义一种方法,能够你的tensor按照你定义的方法来进行运算)。

定义好了之后便是对计算图的执行了,TensorFlow中图的构建与执行是分开来的,也就是说你如果仅仅写了上面的三行代码

就开始运行,你是得不到输出的,就是因为你只是定义了计算图,并没有执行。那么我们图的执行要怎么做呢?

首先,我们需要创建一个会话(也就是session),

然后选择你要执行的计算图

最后你还要关闭你刚刚所创建的会话。

我们来看一段代码

import tensorflow as tf

#  上面的计算图的定义
a = tf.constant(1, dtype=tf.int8)
b = tf.constant(2, dtype=tf.int8)
res= a + b

#  开始执行你所定义的计算图
sess = tf.Session()
sess.run(res)
sess.close()   #手动关闭session

当然了,在python当中涉及到类似文件读取这种先打开在关闭的操作,你可以使用with。。as。。的方法来做个简化,

这样一来便不需要你来手动进行关闭了。

import tensorflow as tf
a = tf.constant(1, dtype=tf.int8)
b = tf.constant(2, dtype=tf.int8)
res= a + b
with tf.Session() as sess:  #运算结束后session自动关闭
    sess.run(res)

2.  关于常量,变量和占位符的一些操作

在上面的例子中仅仅是定义了一些常量,在TensorFlow中,我们同样可以将tensor定义为一个变量。方法有如下两种:

01  tf.Variable()

# variable的简单的构造函数
# 可以看出是用于生成一个初始值为initial-value的变量。必须指定初始化值

tf.Variable(<initial-value>, name=<optional-name>)

02  tf.get_variable() 


#  获取已存在的变量(要求不仅名字,而且初始化方法等各个参数都一样),如果不存在,就新建一个。 
#  可以用各种初始化方法,不用明确指定值。

tf.get_variable()
W = tf.get_variable(name, shape=None, dtype=tf.float32, initializer=None,
       regularizer=None, trainable=True, collections=None)

二者的都可以用来创建变量,但是不同之处在于前者(tf.Variable())仅仅是用来创建一个变量;

后者可以是创建或者获取一个变量,(首先是获取,如果不存在则会创建:这句话有些争议,理性对待)多了获取两个字就意味着我们可以通过其实现参数的共享。tf.get_variable() 会检查当前命名空间下是否存在同样name的变量,可以方便共享变量。而tf.Variable 每次都会新建一个变量。需要注意的是tf.get_variable() 要配合reusetf.variable_scope() 使用。(如何共享后面会提到)

二者最直观的区别可能是在使用tf.Variable时,如果检测到命名冲突,系统会自己处理。


import tensorflow as tf
w_1 = tf.Variable(3,name="w_1")
w_2 = tf.Variable(1,name="w_1")
print(w_1.name)
print w_2.name)

#输出 (注意输出的两个值的name均为w_1)
#w_1:0
#w_1_1:0

如果使用get_varialbe 来定义,则会出现错误 

import tensorflow as tf
 
w_1 = tf.get_variable(name="w_1",initializer=1)
w_2 = tf.get_variable(name="w_1",initializer=2)

#错误信息
#ValueError: Variable w_1 already exists, disallowed. Did
#you mean to set reuse=True in VarScope?

--------------------------------------------------------------------------------------------------------------------------------------------------------------

除此之外,tensorflow还支持占位符(placeholder),就是在这个位置有一个变量的位置,但是没有具体的变量存在(类似于这里是个停车位,但是却没有车)。只有在具体操作的时候,这个位置才会传入实际值,是通过使用feed_dict{}的方法传入的。实例如下:

x1 = tf.Variable(2.0,name="x1")
x2 = tf.placeholder(tf.float32,name="x2")
# 注意x2定义时的方法,是定义了一个placeholder,而不是variable
#不要定义成这样 → x2 = tf.Variable(tf.placeholder,name="x2")
result = x1 + x2

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print(sess.run(result,feed_dict={x2: 3.0}))
注意placeholder在定义的时候,最好将下面的这三个变量都传进来
dtype:数据类型。常用的是tf.float32,tf.float64等数值类型 
shape:数据形状。默认是None,就是一维值,也可以是多维,比如[2,3], [None, 3] 
name:名称。

3.  关于命名空间的一些操作  

如果已经存在的变量没有设置为共享变量,TensorFlow 运行到第二个拥有相同名字的变量的时候,就会报错。

为了解决这个问题,TensorFlow 提出了 tf.variable_scope 函数;  它的主要作用是,在一个命名空间(scope )内实现一些变量间的共享。

首先我们来看一下关于命名空间的简单应用:

with tf.variable_scope("foo"):
    v = tf.get_variable("v", [1]) 

# 输出 → v.name == "foo/v:0"
简单来说就是给变量名前再加了个变量空间名。

接下来看看怎么用tf.get_variable()实现共享变量:

根据在tensorflow命名空间内是否开启自动变量复用 , (reuse=tf.AUTO_REUSE)分为两种情况:

如果不开启变量复用:

with tf.variable_scope("scope0"):
    var1 = tf.get_variable("var", initializer=tf.constant(0.0))
    var2 = tf.get_variable("var", initializer=tf.constant(1.0))

# 输出的时候就会出现错误

所以,我们需要开启变量复用,也就是reuse,样例如下:

with tf.variable_scope("scope1", reuse=tf.AUTO_REUSE):
    var1 = tf.get_variable("var", initializer=tf.constant(0.0))
    var2 = tf.get_variable("var", initializer=tf.constant(1.0))
    print(var1.name)
    print(var2.name)
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        print(var1.eval())
        print(var2.eval())

scope1/var:0
scope1/var:0
0.0
0.0  # 还是0.0,还是第一次声明的值

综上,我们可知在开启复用后,tf.get_variable() 生成的变量会被复用,但值是第一次赋值的那个值。

猜你喜欢

转载自blog.csdn.net/Pierce_KK/article/details/88753172
今日推荐