好久不用了,回顾了一下,就当记个笔记吧
首先是看了这为朋友的博客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()
要配合reuse
和tf.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() 生成的变量会被复用,但值是第一次赋值的那个值。