TensorFlow学习笔记(一)

蒋子阳《TensorFlow深度学习算法原理与编程实战》的学习笔记(一)
环境:
Windows
TensorFlow 1.12
GPU:1660ti

TensorFlow 基础知识

tf以计算图为基础,整个计算过程包括 ① 构建图 ②执行图
TensorFlow首先创建一个骨架图,里面包含所有组件,此时没有数据和计算的产生,只有当会话执行时,数据进入图中进行流动,才有实际的结果产生。

计算图 -- 计算模型

图:是相互连接的实体的集合,通常称为节点node,节点通过边edge连接

TensorFlow中的图的每一个节点表示一个操作,并可应用在某个输入或生成传递给其他节点的输出

依赖关系:一个节点的输入取值于另一个节点的输出,那么这两个节点具有依赖关系。存在依赖关系的节点通过边相互连接。

张量(tensor)就是在边中流动(flow)的数据,这也是TensorFlow名称的由来。此外,存在一种不流动数据的边,它们起着依赖控制(control dependencies)作用,让起始节点执行完后才执行下一个目标节点,但中间没有数据传输。

创建图

eg.定义一个简单的graph。 a b相乘得到c, d等于c的正弦,e等于b d的商。(《TensorFlow学习指南》的例题3.1)

import tensorflow as tf
a = tf.constant(5,tf.float32)  # 定义常量
b = tf.constant(10,tf.float32)
print(b) # Tensor("Const_1:0", shape=(), dtype=float32) 名称为const_1:0的tensor对象,类型是float32
c = b*a  # c = tf.mul(a,b)    c定义了这个乘法操作
d = tf.sin(c)
e = b / d

with tf.Session() as sess: # 使用with语句打开会话可以保证计算完成后将会话自动关闭,否则使用sess.close()操作
    fetches = [a,b,c,d,e]
    out1 = sess.run(fetches) # sess.run可以同时计算多个节点列表 sess.run参数称为fetches(提取),将节点传入参数,用来计算该节点的值
    # TensorFlow仅利用依赖关系的集合来计算节点 例如,e依赖 b和d,则通过b d计算e
    outs = sess.run(e)
print(out1,type(out1),out1[0])
TensorFlow学习笔记(一)_第1张图片
计算图

tf的计算图

导入tf的时候,会自动生成一个空白图,后续的操作都与该默认图关联。

可以通过tf.Graph()创建一个新的空白图,并可以自定义操作与它关联。任何一个节点都可以通过graph属性查看是否属于某个图

import tensorflow as tf
print(tf.get_default_graph()) #默认空白图
g = tf.Graph()
print(g)
a = tf.constant(5)
print(a.graph is tf.get_default_graph()) # 结果是true
print(a.graph is g) #结果是false

多个计算图的管理

with语句可以用于上下文管理,它设置了enter块和exit块,因此可以用它管理某个计算图,使用with语句和as_default()返回上下文管理器,指定某个计算图成为该部分的默认图,同时在该部分定义的计算关联与该图

g1 = tf.get_default_graph()
g2 = tf.Graph()
print(g1 is tf.get_default_graph())  # True

with g2.as_default():
    print(g1 is tf.get_default_graph()) # False

print(g1 is tf.get_default_graph())  # true

张量 -- 数据模型

张量tensor类似于数组array,但是张量只保存了运算结果的属性,而没有保存它的具体数值。

import tensorflow as tf
a = tf.constant([1.0, 2.0],name = 'a' , dytpe= tf.float32)  # 定义常量
print(a) # Tensor(""Const_1:0", shape=(2,), dtype=float32")

每一个张量都具有操作op、维度shape和数据类型dtype三种属性。

操作op

op是一个张量的名字,也算它的唯一标识符。计算图的每个节点都是一个运算,张量保存的是运算的属性,命名规则是“ node:src_output”。node是节点名称,如const、add、mul等,src_output表示该张量是节点的第几个输出,从0开始编号。

维度shape

类似array的维度,一维标量scalar、二维向量vector.....直至n维数组

数据类型dtype

tf支持十四种类型 int8/16/32/64 、uint8、float32/64、布尔bool、复数complex64/128、字符串string和qint8/32、quint8

会话 -- 运行模型

完成数据和计算图的定义后需要使用会话session执行。

两种开启会话的方式:with语句更方便,自动关闭。

sess = tf.Session() # 开启
sess.run() # 执行
sess.close() # 关闭
with tf.Session() as sess:
    sess.run()

placeholder与变量Variable

tf.constant定义的是计算图中的常量,可变数据则是通过placeholder和变量来定义。

palceholder机制

placeholder相当于在计算图中指定了一个位置,数据在程序运行时才给出。placeholder机制用于解决数据量过大的问题,可以将数据分批次传入节点,在编程时只需要传入holder位置即可,这样在有限的节点高效传入大量的数据。

函数原型 placeholder(dtype, shape=None, name=None)

a = tf.placeholder(tf.float32,shape=(None,2),name = "input")
b = tf.placeholder(tf.float32,shape=(None,2),name = "input")
ans =a + b
with tf.Session() as sess:
    sess.run(ans, feed_dict={a:[1.0,2.0],
                             b:[2.0,3.0]})
print(ans)

定义placeholder时,数据类型dtype必须给出且不可改变,shape若是给出时不确定可以用None,不给出的时候程序自动推断。

运行时通过sess.run的feed_dict参数传入holder的取值,它是一个字典数据,传入时的数据类型必须与placeholder定义时的类型一致,否则会报错。

TensorFlow的变量

变量的作用是保存网络中的参数,对参数的更新就是对相应变量值的更新,使用Variable()声明变量,同时需要提供初始值。通常是采用随机分布赋初值。tf提供了正态分布、平均分布、伽马分布等多种类型。

此外变量的初值还可以是常量、其他变量的初值计算而来。z

# 声明一个变量并随机赋值,返回大小3×4 均值0 标准差1 满足正态分布的随机矩阵
weights = tf.Variable(tf.random_normal([3,4], stddev=1))

几种随机分布和常量初始化

函数名 功能 函数名 功能
random_normal 正态分布 zeros 全0数组
truncate_normal 正态分布 ones 全1数组
random_uniform 平均分布 fill 全为给定值的数组
random_gamma 伽马分布 constant 给定值的常量

获取一个变量的值通过initialized_value()方法

bias = tf.Variable(tf.zeros([3])) #全为1的一维数组,长度3
b1 = tf.Variable(bias.initialized_value()*3) # 使用bias的值乘3初始化bl

批量初始化:

tf.global_variables_initializer() # 初始化全部变量
tf.initialize_all_variables() # 较早版本tf的写法,1.12中仍存在,和上面的方法功能一样

变量和张量

变量在TensorFlow中是一个运算,对应tensorboard里面计算图的一个节点,这个运算的输出结果就是一个具有name、shape和type属性的张量。

变量在构建后数据类型就不能更改,但shape可以发生变化,需要设置validate_shape=False

tf.assign(w1,w2,validate_shape=False) # 将w2赋给w1,若是shape不一致,仍旧可以进行赋值

变量空间

除了Variable()外,可以通过get_variable()创建或者获取变量,该函数的使用类似Variable,但有所不同。name参数此时必须指明,同时通过initializer参数指明初始化方法。

a = tf.get_variable(name= "a", shape=[1],initializer=tf.constant_initializer(1.0))

initializer参数的取值也包括常量和随机分布等初始化方法。

初始化函数 初始化为指定常量
constant_initializer 正态分布初始化
random_normal_initializer 正态分布初始化
truncate_uniform_initializer 平均分布初始化
random_uint_scaling_initialize 平均分布但不影响输出数量级
random_gamma_initialize 伽马分布
zeros_initialize 全零初始化
ones_initialize 全1初始化

variable_scope() 与name_scope(): 在变量空间使用get_variable获取已经创建过的变量

可以通过variable_scope指定一个变量空间,在该空间定义两个name相同的变量会报错。

with tf.variable_scope("one"):
    a1 = tf.get_variable("a",[1],initializer=tf.constant_initializer(1.0))
    
with tf.variable_scope("one"): #报错 因为one空间已经存在一个name=a的变量,错误信息提示是否将reuse设置True
    a2 = tf.get_variable("a",[1])    
with tf.variable_scope("one",reuse=True):# 不报错,因为reuse=True,可以重复使用,get_variable将获取one空间的name=a的变量赋值给a2
    a3 = tf.get_variable("a",[1])
    print(a1.name,a3.name) # 输出是 one/a:0 one/a:0 变量空间内的变量name通常会带上空间名字作为前缀
with tf.variable_scope("two",reuse=True): # 报错,尽管reuse=True,但这是在变量空间two,函数只能在该对应空间选择定义过的变量,two空间没有name为a的变量
    a4 = tf.get_variable("a",[1])

你可能感兴趣的:(TensorFlow学习笔记(一))