深度学习
第七章 Tensorflow 概述
一、Tensorflow 简介
1. 什么是 Tensorflow ?
- Tensorflow 由谷歌人工智能团队谷歌大脑(Google Brain)开发和维护的开源深度学习平台,是目前人工智能领域主流的开发平台,在全世界有着广泛的用户群体。
2. Tensorflow 的特点
- 优秀的架构设计,通过“张量流”进行数据传递和计算,用户可以很容易地、可视化地看到张量流动的每一个环节
- 可轻松地在CPU/GPU上部署,进行分布式计算,为大数据分析提供计算能力的支撑
- 跨平台性好,灵活性强。Tensorflow 不仅可在Linux、Mac和Windows系统中运行,甚至还可在移动终端下工作
3. Tensorflow 发展历史
- 2011年,Google公司开发了它的第一代分布式机器学习系统DistBelief。著名计算机科学家杰夫·迪恩(Jeff Dean)和深度学习专家吴恩达(Andrew Y.Ng)都是这个项目的核心成员
- 2015年11月,Google将它的升级版实现正式开源,协议遵循Apache 2.0 并更名为TensorFlow
- 目前,Tensorflow最新版为2.x,此处使用1.14.0
4. Tensorflow 安装
-
在线安装
- 安装 Tensorflow 及依赖包:pip install tf-nightly
- 安装纯净包:pip install tensorflow
- 安装GPU版本:pip install tf-nightly-gpu
-
离线安装
- 下载离线包:https://pypi.org/project/tensorflow/#files 执行安装
-
修改源进行安装。如果安装包time out 错误,则可以修改pip源,重新进行安装,修改方式:
- 编辑或新建pip配置文件(~/.pip/pip.conf),在配置文件下加入:
[global] index-url = http://mirrors.aliyun.com/pypi/simple/ [install] trusted-host = mirrors.aliyun.com
- 安装时将timeout时间设置长一点
sudo pip3 --timeout 600 install tensorflow-1.14.0-cp35-cp35m-manylinux1_x86_64.whl
5. 案例1:快速开始
# tensorflow版本的helloworld
import tensorflow as tf
# TF1.x hello world
# hello = tf.constant("Hello, world!") # 定义一个常量(张量)
# sess = tf.Session() # 创建一个session,用来执行操作
# print(sess.run(hello)) # 调用session的run方法,执行hello操作,并打印结果
# sess.close() # 关闭session
# TF2.x hello world
# msg = tf.constant('Hello, world!')
# tf.print(msg)
# TF2.x -> TF1.x hello world
tf.compat.v1.disable_eager_execution()
msg = tf.constant('Hello, world!')
sess = tf.compat.v1.Session()
print(sess.run(msg))
6. 案例2:张量相加
# 张量相加的示例
import tensorflow as tf
# TF1.x
a = tf.constant(5.0) # 张量a
b = tf.constant(1.0) # 张量b
c = tf.add(a, b) # 张量相加
with tf.Session() as sess:
print(sess.run(c))
# TF2.x -> TF1.x
tf.compat.v1.disable_eager_execution()
a = tf.constant(5.0) # 张量a
b = tf.constant(1.0) # 张量b
c = tf.add(a, b) # 张量相加
with tf.compat.v1.Session() as sess:
print(sess.run(c))
"""
6.0
"""
二、Tensorflow 体系结构
1. 体系结构概述
- TensorFlow 属于“定义”与“运行”相分离的运行机制。从操作层面可以抽象成两种:模型构建和模型运行
- 客户端:用户编程、执行使用
- master:用来与客户端交互,并进行任务调度
- worker process:工作节点,每个worker process可以访问一到多个device
- device:TF的计算核心,执行计算
2. 单机模式与分布式模式
- TF的实现分为“单机实现”和“分布式实现”
3. 后端逻辑层次
三、基本概念
1. 张量
- 张量(Tensor):多维数组或向量,张量是数据的载体,包含名字、形状、数据类型等属性
2. 数据流
- 数据流图(Data Flow Graph)用“结点”(nodes)和“线”(edges)的有向图来描述数学计算
- “节点”一般用来表示数学操作,也可以表示数据输入(feed in)的起点/输出(push out)的终点,或者是读取/写入持久变量(persistent variable)的终点
- “线”表示“节点”之间的输入/输出关系。这些数据“线”可以输运多维数据数组,即“张量”(tensor)
- 一旦输入端的所有张量准备好,节点将被分配到各种计算设备完成异步并行地执行运算
3. 操作
- 操作(Operation,简称op)指专门执行计算的节点,tensorflow函数或API定义的都是操作。常用操作包括:
- 标量运算,向量运算,矩阵运算
- 带状态的运算
- 神经网络组件
- 存储、恢复
- 控制流
- 队列及同步运算
4. 图和会话
- 图(Graph)描述整个程序结构,Tensorflow中所有的计算都构建在图中
- 会话(Session)用来执行图的运算
5. 变量和占位符
- 在Tensorflow中,变量(Variable)是一种操作,变量是一种特殊的张量,能够进行存储持久化(张量不能进行持久化),它的值是张量
- 占位符(placeholder)是变量占位符,当不能确定变量的值时,可以先声明一个占位符,真正执行时再传入变量
第八章 Tensorflow 基本操作
一、图和会话操作
1. 什么是图?
- 图(Graph)描述了计算的过程。Tensorflow 程序通常被组织成一个构建阶段和一个执行阶段。在构建阶段,op 的执行步骤被描述成一个图。在执行阶段,使用会话执行图中的 op。
- Tensorflow Python 库有一个默认图(default graph),op 构造器可以为其增加节点。这个默认图对许多程序来说已经足够用了,也可以创建新的图来描述计算过程。
- 在Tensorflow中,op/session/tensor都有graph属性
2. 案例3:查看图对象
# 查看默认图的属性
import tensorflow as tf
# TF1.x
a = tf.constant(5.0)
b = tf.constant(1.0)
c = tf.add(a, b)
graph = tf.get_default_graph() # 获取默认的图
print(graph)
with tf.Session() as sess:
print(sess.run(c))
print(a.graph) # 打印张量的graph属性
print(c.graph) # 打印c操作的graph属性
print(sess.graph) # 打印session的graph属性
# TF2.x -> TF1.x
tf.compat.v1.disable_eager_execution()
a = tf.constant(5.0)
b = tf.constant(1.0)
c = tf.add(a, b)
graph = tf.compat.v1.get_default_graph() # 获取默认的图
print(graph)
with tf.compat.v1.Session() as sess:
print(sess.run(c))
print(a.graph) # 打印张量的graph属性
print(c.graph) # 打印c操作的graph属性
print(sess.graph) # 打印session的graph属性
"""
<tensorflow.python.framework.ops.Graph object at 0x0000028089CD3850>
6.0
<tensorflow.python.framework.ops.Graph object at 0x0000028089CD3850>
<tensorflow.python.framework.ops.Graph object at 0x0000028089CD3850>
<tensorflow.python.framework.ops.Graph object at 0x0000028089CD3850>
"""
3. 会话及相关操作
- 会话(session)用来执行图中的计算,并且保存了计算张量对象的上下文信息。会话的作用主要有:
- 运行图结构
- 分配资源
- 掌握资源(如变量、队列、线程)
- 一个session只能执行一个图的运算。可以在会话对象创建时,指定运行的图。如果在构造会话时未指定图形参数,则将在会话中使用默认图。如果在同一进程中使用多个图(使用tf.graph()创建),则必须为每个图使用不同的会话,但每个图可以在多个会话中使用。
- 创建会话
- tf.Session() # 使用默认图
- 运行
- session.run(fetches, feed_dict=None)
- 参数:
- fetches 图中的单个操作,或多个操作的列表
- feed_dict 运行传入的参数构成的字典,可以覆盖之前的值
- 关闭
- session.close()
4. 案例4:指定会话运行某个图
# 查看默认图的属性
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
a = tf.constant(5.0)
b = tf.constant(1.0)
c = tf.add(a, b)
graph = tf.compat.v1.get_default_graph() # 获取默认的图
print("graph:", graph)
# 新创建一个图
graph2 = tf.Graph()
print("graph2:", graph2)
with graph2.as_default(): # 设置为默认图
d = tf.constant(11.0) # 操作d属于graph2
with tf.compat.v1.Session() as sess:
print(sess.run(c))
print(sess.run(d)) # 报错,因为d没有在默认的graph中
print(a.graph) # 打印张量的graph属性
print(c.graph) # 打印c操作的graph属性
print(sess.graph) # 打印session的graph属性
"""
ValueError: Argument `fetch` = Tensor("Const:0", shape=(), dtype=float32)
cannot be interpreted as a Tensor. (Tensor Tensor("Const:0", shape=(), dtype=float32)
is not an element of this graph.)
"""
# 查看默认图的属性
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
a = tf.constant(5.0)
b = tf.constant(1.0)
c = tf.add(a, b)
graph = tf.compat.v1.get_default_graph() # 获取默认的图
print("graph:", graph)
# 新创建一个图
graph2 = tf.Graph()
print("graph2:", graph2)
with graph2.as_default(): # 设置为默认图
d = tf.constant(11.0) # 操作d属于graph2
with tf.compat.v1.Session(graph=graph2) as sess: # 指定执行graph2
# print(sess.run(c)) # 报错,因为c没有在默认的graph中
print(sess.run(d))
print(a.graph) # 打印张量的graph属性
print(c.graph) # 打印c操作的graph属性
print(sess.graph) # 打印session的graph属性
"""
graph: <tensorflow.python.framework.ops.Graph object at 0x0000028FEC1F3850>
graph2: <tensorflow.python.framework.ops.Graph object at 0x0000028FA3C0F370>
11.0
<tensorflow.python.framework.ops.Graph object at 0x0000028FEC1F3850>
<tensorflow.python.framework.ops.Graph object at 0x0000028FEC1F3850>
<tensorflow.python.framework.ops.Graph object at 0x0000028FA3C0F370>
"""
5. 会话常见的错误及原因
- 调用run()方法时,可能会出现的错误及原因
- RuntimeError:Session处于无效(如关闭)
- TypeError:fetches或feed_dict的键是不合适的值
- ValueError:fetches或feed_dict的键无效或引用的值不存在
二、张量的属性及基本运算
1. 张量的阶与形状
- 阶:张量的维度(数方括号的层数)
- 形状表示方法
- 0维:()
- 1维:(5),1行5个元素
- 2维:(2,3),2行3列
- 3维:(2,3,4),两个3行4列的矩阵
2. 张量的数据类型
3. 张量常用属性
属性名称 | 说明 |
---|---|
graph | 所属的默认图 |
op | 张量的操作名 |
name | 名称 |
shape | 形状 |
dtype | 元素类型 |
4. 案例5:查看张量属性
# 查看张量属性示例
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
a = tf.constant(5.0) # 标量
with tf.compat.v1.Session() as sess:
print(sess.run(a))
print("name: ", a.name) # name属性
print("dtype: ", a.dtype) # dtype属性
print("shape: ", a.shape) # shape属性
print("op: ", a.op) # op属性
print("graph: ", a.graph) # graph属性
"""
5.0
name: Const:0
dtype: <dtype: 'float32'>
shape: ()
op: name: "Const"
op: "Const"
attr {
key: "dtype"
value {
type: DT_FLOAT
}
}
attr {
key: "value"
value {
tensor {
dtype: DT_FLOAT
tensor_shape {
}
float_val: 5.0
}
}
}
graph: <tensorflow.python.framework.ops.Graph object at 0x00000164681D38B0>
"""
5. 案例6:生成张量
# 创建张量示例
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
# 创建值全为0的张量
tensor_zeros = tf.zeros(shape=[2, 3], # 2行3列
dtype="float32") # 类型
# 创建值全为1的张量
tensor_ones = tf.ones(shape=[2, 3],
dtype="float32")
# 创建正态分布随机张量
tensor_nd = tf.compat.v1.random_normal(shape=[10], # 一维,10个元素
mean=1.7, # 中位数
stddev=0.2,
dtype="float32")
# 创建形状和tensor_ones一样,值全为0的张量
tensor_zeros_like = tf.zeros_like(tensor_ones)
with tf.compat.v1.Session() as sess:
print(tensor_zeros.eval()) # eval表示在session中执行计算
print(tensor_ones.eval())
print(tensor_nd.eval())
print(tensor_zeros_like.eval())
"""
[[0. 0. 0.]
[0. 0. 0.]]
[[1. 1. 1.]
[1. 1. 1.]]
[1.5594195 1.5061207 1.6503117 1.4521958 1.8483374 1.7134072 1.8214194
1.7255555 1.7541615 1.4169383]
[[0. 0. 0.]
[0. 0. 0.]]
"""
6. 张量类型转换
函数名称 | 说明 |
---|---|
tf.string_to_number(string_tensor) | 字符串转换为数字 |
tf.to_double(x) | 转换为64位浮点型 |
tf.to_float(x) | 转换为32位浮点型 |
tf.to_int32(x) | 转换为32位整型 |
tf.to_int64(x) | 转换为64位整型 |
tf.cast(x, dtype) | 将x转换为dtype所指定的类型 |
7. 案例7:张量类型转换
# 张量类型转换示例
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
tensor_ones = tf.ones(shape=[2, 3], dtype="int32")
tensor_float = tf.constant([1.1, 2.2, 3.3])
with tf.compat.v1.Session() as sess:
print(tf.cast(tensor_ones, tf.float32).eval()) # 将tensor_ones转换为浮点型并打印
"""
[[1. 1. 1.]
[1. 1. 1.]]
"""
8. 占位符
- 不确定张量内容情况下,可以使用占位符先占个位置,然后执行计算时,通过参数传入具体数据执行计算(通过feed_dict参数指定)。placeholder节点被声明的时候是未初始化的,也不包含数据,如果没有为它供给数据,则TensorFlow运算的时候会产生错误
- 占位符定义:name = placeholder(dtype, shape=None, name=None)
9. 案例8:占位符使用
# 占位符使用示例:占位符在使用时,必须传入参数
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
# 定义两个占位符
plhd = tf.compat.v1.placeholder(tf.float32, [2, 3]) # 定义2行3列的占位符
plhd2 = tf.compat.v1.placeholder(tf.float32, [None, 3]) # N行3列的占位符
plhd3 = tf.compat.v1.placeholder(tf.float32, [None, 4]) # N行4列的占位符
with tf.compat.v1.Session() as sess:
d = [[1, 2, 3],
[4, 5, 6]]
print(sess.run(plhd, feed_dict={plhd: d})) # 执行占位符操作,需要传入数据
print(sess.run(plhd2, feed_dict={plhd2: d})) # 定义为N行3列,执行时传入2行3列
# print(sess.run(plhd2, feed_dict={plhd3: d})) # 定义为N行4列,执行时传入2行3列
"""
[[1. 2. 3.]
[4. 5. 6.]]
[[1. 2. 3.]
[4. 5. 6.]]
"""
10. 张量形状改变
- 静态形状:在创建一个张量,初始状态的形状
- tf.Tensor.get_shape():获取Tensor对象的静态形状
- tf.Tensor.set_shape():更新Tensor对象的静态形状
- 注意:转换静态形状的时候,1-D到1-D,2-D到2-D,不能跨阶数改变形状;对于已经固定或者设置静态形状的张量/变量,不能再次设置静态形状
- 动态形状:在运行图时,动态形状才是真正用到的,这种形状是一种描述原始张量在执行过程中的一种张量
- tf.reshape(tf.Tensor, shape):创建一个具有不同动态的形状的新张量
- 可以跨维度转换,如1D --> 2D,1D --> 3D
11. 案例9:修改张量形状
# 张量形状改变
# 静态形状:初始形状,只能设置一次,不能跨阶设置
# 动态形状:运行时的形状,可以多次设置,可以跨阶设置,但元素总数要一致
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
pld = tf.compat.v1.placeholder(tf.float32, [None, 3])
pld.set_shape([4, 3]) # 设置静态形状,一旦固定就不能再改变
print(pld)
# pld.set_shape([3, 3]) # 报错
# 设置张量的动态形状,实际是创建一个新的张量
new_pld = tf.reshape(pld, [3, 4]) # 设置动态形状
print(new_pld)
new_pld = tf.reshape(pld, [2, 6]) # 多次设置动态形状
print(new_pld)
# new_pld = tf.reshape(pld, [2, 4]) # 报错,元素个数不匹配
with tf.compat.v1.Session() as sess:
pass
"""
Tensor("Placeholder:0", shape=(4, 3), dtype=float32)
Tensor("Reshape:0", shape=(3, 4), dtype=float32)
Tensor("Reshape_1:0", shape=(2, 6), dtype=float32)
"""
12. 张量数学计算
函数名称 | 说明 |
---|---|
tf.add(x, y) | 张量相加 |
tf.matmul(x, y) | 张量相乘 |
tf.log(x) | 求张量的自然对数 |
tf.reduce_sum(x, axis) | 计算张量指定维度上的总和 |
tf.segment_sum(data, segment_ids) | 计算张量片段总和 |
- 矩阵乘法说明
- 当矩阵A的列数(column)等于矩阵B的行数(row)时,A与B可以相乘
- 矩阵C的行数等于矩阵A的行数,C的列数等于B的列数
- 乘积C的第m行第n列的元素等于矩阵A的第m行的元素与矩阵B的第n列对应元素乘积之和
13. 案例10:张量数学计算
# 张量的数学计算示例
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
x = tf.constant([[1, 2],
[3, 4]], dtype=tf.float32)
y = tf.constant([[4, 3],
[3, 2]], dtype=tf.float32)
x_add_y = tf.add(x, y) # 张量相加
x_mul_y = tf.matmul(x, y) # 张量相乘(按照矩阵相乘的规则)
log_x = tf.compat.v1.log(x) # 求对数
x_sum_1 = tf.reduce_sum(x, axis=[1]) # 1-行方向 0-列方向
# 张量计算片段和
data = tf.constant([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], dtype=tf.float32)
segment_ids = tf.constant([0, 0, 0, 1, 1, 2, 2, 2, 2, 2], dtype=tf.int32)
x_seg_sum = tf.compat.v1.segment_sum(data, segment_ids)
with tf.compat.v1.Session() as sess:
print(x_add_y.eval())
print(x_mul_y.eval())
print(log_x.eval())
print(x_sum_1.eval())
print(x_seg_sum.eval())
"""
[[5. 5.]
[6. 6.]]
[[10. 7.]
[24. 17.]]
[[0. 0.6931472]
[1.0986123 1.3862944]]
[3. 7.]
[ 6. 9. 40.]
"""
14. 变量
- 变量是一种op,它的值是张量
- 变量能够持久化保存,普通张量则不可
- 当定义一个变量时,需要在会话中进行初始化
- 变量创建
- tf.Variable(initial_value=None, name=None)
15. 变量使用
# 变量使用示例
"""
1.变量是一种特殊的张量,变量中存的值是张量
2.变量可以进行持久化保存,张量则不可
3.变量使用之前,要进行显式初始化
"""
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
a = tf.constant([1, 2, 3, 4])
var = tf.Variable(tf.compat.v1.random_normal([2, 3], mean=0.0, stddev=1.0), # 初始值
name="var")
# 变量操作执行之前,需要进行全局初始化(初始化也是一个op,需要在session的run方法中执行)
init_op = tf.compat.v1.global_variables_initializer()
with tf.compat.v1.Session() as sess:
sess.run(init_op)
print(sess.run([a, var]))
"""
[array([1, 2, 3, 4]), array([[ 1.0127357 , 0.8218849 , -0.89877534],
[-0.03486359, -2.0920436 , 1.1781334 ]], dtype=float32)]
"""