1、定义:TensorFlow可以认为是一种编程工具,使用TensorFlow来实现具体的业务需求,所以我们可以认为TensorFlow就是一个“工具箱”,然后我们使用TensorFlow这个“工具箱”中的各种“工具”(方法/API)来实现各种功能。TensorFlow程序一般可以分为两个阶段:构建阶段和执行阶段
2、特性
- 高度灵活性:只要能够将计算表示成一个数据流图,就可以使用TensorFlow。
- 可移植性:TensorFlow支持CPU和GPU运算,可以运行在台式机、服务器、手机移动设备等。
- 自动求微分:TensorFlow内部提供各种对给定的目标函数的求导公式。
- 支持多种语言:Python,C++
- 性能高度化
3、基本概念
- 图(Graph):图描述了计算过程,TensorFlow使用图来表示计算任务。
- 张量(Tensor):TensorFlow使用Tensor表示数据,每个Tensor是一个类型化的多维数组。
- 操作(op):图中的节点被称作op,一个op获得/输入0个或多个Tensor,执行计算,产生0个或多个Tensor。
- 会话(Session):图必须在会话中执行,会话会将op分发到CPU/GPU设备执行。
- 变量(Variable):运行过程中可以被改变的量。
4、节点的操作
节点代表一个操作,一般用来对数字进行运算,也可以作为数据输入点或者读取数据的终点。
5、基本用法
- 使用图来表示计算任务
- 在会话的上下文中执行图
- 使用tensor表示数据
- 通过变量来维护状态
- 使用feed和fetch可以为任意操作赋值或获取数据
6、图的构建
TensorFlow库中有一 个默认图(default graph), op构造器可以直接为其添加节点,一般情况下,使用默认的Graph即可完成程序代码的实现。不过TensorFlow也支持通过Graph类管理多个图。
# 一、默认图
# 两个矩阵相乘运算并输出
import tensorflow as tf
# 1.定义矩阵a和b
a = tf.constant([[1,2],[3,4]],dtype=tf.int32)
b = tf.constant([5,6,7,8],dtype=tf.int32,shape=[2,2])
# 2.以a和b作为输入,进行矩阵的乘法操作
c = tf.matmul(a,b)
# 3.将a与c进行相加操作
d = tf.add(a,c)
# 查看是否在 默认图中
# print(f'a矩阵是否在默认图中:{a.graph is tf.get_default_graph()}')
# 二、 用户自定义图
# 构建新的图
# graph = tf.Graph()
# 使用新的图
with graph.as_default():
d = tf.constant(5.2)
print(f'变量d是否在新图graph中:{d.graph is graph}')
note:不同图之间的节点不能连接
7、会话
当执行图构建完成后,才能给启动图,进入到执行阶段;启动图的第一步就是创建一个Session对象,如果无任何参数的情况下,会话构造器将启动默认图。
# 会话的启动
sess = tf.Session()
# 1.调用session的run方法 运行,得到两个矩阵相乘的结果
# run方法:不需要考虑中间的运算,在运行的时候只需要关注最终的结果对应对象以及所需要输入的参数值
# 只需要传递进去所需要得到结果的对象,程序会自动根据图中的依赖关系来触发所有相关的op操作执行
result = sess.run(c)
result1 = sess.run(d)
# 关闭会话
sess.close()
还可以使用with 自动完成关闭会话操作
with tf.Session() as sess1:
result =sess1.run(c)
print(result)
交互式会话
在TensorFlow中,除了可以使用Session表示这个会话外,还可以通过InteractiveSession来表示会话,使用交互式会话可以降低代码的复杂度,使用Tensor.eval()或者Operation.run()来代替Session.run()方法,这样可以避免一个变量来维持会话。
import tensorflow as tf
# 进入交互式会话
sess = tf.InteractiveSession()
# 定义变量和常量
x = tf.constant([1.0,2.0])
a = tf.constant([2.0,4.0])
# 计算x-a
sub = tf.subtract(x,a)
# 输出结果:两种输出方式
print(sub.eval())
print(sess.run(sub))
note:Session也可以使用eval()
import tensorflow as tf
# 构建图
a = tf.constant(3)
b = tf.constant(4)
c = tf.multiply(a,b)
# 执行
with tf.Session():
print(c.eval())
8、变量
变量(Variables)是维护图执行过程中的状态信息。在训练模型过程中,可以通过变量来存储和更新参数。变量包含张量(Tensor)存放于内存的缓存区。建模的时候变量必须被明确的初始化,模型训练后变量必须被存储到磁盘。这些变量的值可以在之后的模型训练和分析中被加载。
9、Fetch一次运行获取多个值。
input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
add = tf.add(input2, input3)
mul = tf.multiply(input1, add)
with tf.Session() as sess:
result = sess.run([mul, add])
print(result)
[21.0, 7.0]
10、Feed--填充机制
feed使用一个tensor值临时替换一个操作的输出结果,在获取数据的时候必须给定对应的feed数据作为参数。feed只有在调用它的方法内有效,方法结束,feed就消失了。
feed可以使placeholder类型的API创建占位符,常见API: tf.placeholder、tf.placeholder_with_default。
# 构建一个矩阵乘法,但是矩阵在运行时给定
import tensorflow as tf
m1 = tf.placeholder(dtype=tf.float32,shape=[2,3],name='m1')
m2 = tf.placeholder(dtype=tf.float32,shape=[3,2],name='m2')
m3 = tf.matmul(m1,m2)
with tf.Session() as sess:
a = [[1,2,3],[4,5,6]]
b = [[2,1],[4,3],[6,5]]
# 方法1
result = sess.run([m3],feed_dict={m1:a,m2:b})
# 方法2
result1 = m3.eval(feed_dict={m1:a,m2:b})
print(result)
print(result1)
11、更新操作
feed使用一个tensor值临时替换一个操作的输出结果,在获取数据的时候必须给定对应的feed数据作为参数。feed只有在调用它的方法内有效,方法结束,feed就消失了。
import tensorflow as tf
# 1. 定义一个变量
x = tf.Variable(1, dtype=tf.int32, name='v_x')
# 2. 变量的更新
assign_op = tf.assign(ref=x, value=x + 1)
# 3. 变量初始化操作
x_init_op = tf.global_variables_initializer()
# 3. 运行
with tf.Session() as sess:
# 变量初始化
sess.run(x_init_op)
# 模拟迭代更新累加器
for i in range(5):
# 执行更新操作
r_x = sess.run(x)
sess.run(assign_op)
print(r_x)
# 问题:求1~100的偶数和
import tensorflow as tf
# 定义一个变量x 初始值为1
x = tf.Variable(0,dtype=tf.int32)
# 变量更新
assign_op = tf.assign(ref=x,value=x + 2)
# 变量初始化
x_init_op = tf.global_variables_initializer()
# 运行
with tf.Session() as sess:
sum = 0
#变量初始化
sess.run(x_init_op)
# 偶数求和
for i in range(51):
r_x = sess.run(x)
# 100以内偶数
print(r_x)
sum += r_x
# 更新
sess.run(assign_op)
print("100以内偶数和为:",sum)
12、控制依赖
我们可以通过Variable和assign完成变量的定义和更新,但是如果在更新变量之前需要更新其它变量,那么会导致一个比较严重的问题:也就是需要多次调用sess.run方法来进行变量的更新。通过这种方式,代码复杂程度上升,同时也没有执行效率。
解决该问题的方案就是:控制依赖。通过TensorFlow中提供的一组函数来处理不完全依赖的情况下的操作排序问题(即给定哪个操作先执行的问题),通tf.control_dependencies API完成。
# 求阶乘
import tensorflow as tf
# # 定义一个变量 sum
sum = tf.Variable(1,dtype=tf.int32)
# 定义一个占位符
i = tf.placeholder(dtype=tf.int32)
# 更新操作
tem_sum = tf.multiply(sum,i)
assign_op = tf.assign(sum,tem_sum)
# 控制依赖:在获取sum之前先更新sum的值
with tf.control_dependencies([assign_op]):
# 如果需要执行这个代码块中的内容,必须先执行control中给定的操作/tensor
sum = tf.Print(sum,data=[sum,sum.read_value()],message='sum =')
# 初始化
sum_init_op = tf.global_variables_initializer()
# 运行
with tf.Session() as sess:
sess.run(sum_init_op)
for j in range(1,10):
# 通过control_dependencies可以指定依赖关系,这样的话,就不用管内部的更新操作了
sum1 = sess.run(sum, feed_dict={i: j})
print("10! = ",sum1)