一、Tensorflow基本知识
1、使用tensorflow重要的几个点:
1.1 tensor对象初始化的时候指定 数据类型(eg :tf.float64)
1.2 tensor对象初始化的时候指定 名称(eg:API属性 name = ?)
1.3 tensorflow 中numpy的大多数API均可使用,numpy中切片等操作在tensor中同样适用。
1.4 TensorFlow 不允许不同的图的tensor对象之间互相运算
使用TensorFlow必须理解下列概念:
• 使用图(graph)来表示计算任务;
• 在会话(session)的上下文中执行图;
• 使用tensor表示数据; ---- tensor对象可以获取属性,类似ndarray,即 tensor对象.name、tensor对象.dtype ...
• 通过变量(Variable)来维护状态 ;
• 使用feed和fetch可以为任意的操作(Operation/op)赋值或者从其中获取数据。
import tensorflow as tf
# 执行图的创建
with tf.Graph().as_default():
# 构建参数
a = tf.constant(value = [1,2,3,4],dtype=tf.float64,shape = [4,1],name='constant_a')
b = tf.constant(value=[9,10,11,12],dtype=tf.float64,shape = [1,4],name='constant_b')
result = tf.multiply(a,b) # 矩阵的数乘,或者是标量的数乘
result1 = tf.matmul(a,b) # 矩阵的点乘
print(result)
print(result1)
print(result1[1:-1,1:-1])
# 结果:仅仅构建图,执行图并不会运行
'''
Tensor("Mul:0", shape=(4, 4), dtype=float64) ----- tensor对象可以获取属性,类似ndarray,即 tensor对象.name、tensor对象.dtype ...
Tensor("MatMul:0", shape=(4, 4), dtype=float64)
'''
# 执行图的执行
with tf.Session() as sess:
result_run,result1_run = sess.run(fetches=[result,result1])
'''
会话 Session 运行的 API .run(self, fetches, feed_dict=None, options=None, run_metadata=None)
注意: 运行的结果的变量尽量不要与构建执行图的变量相同,以防止会话再循环执行时出现错误。
'''
print(result_run,result1_run)
# ... 机器学习的步骤
0、TensorFlow的基础知识
• 图(Graph):图描述了计算的过程,TensorFlow使用图来表示计算任务。
• 张量(Tensor):TensorFlow使用tensor表示数据。每个Tensor是一个类型化的 多维数组。
• 操作(op):图中的节点被称为op(opearation的缩写),一个op获得/输入0 个或多个Tensor,执行计算,产生0个或多个
Tensor。
• 会话(Session):图必须在称之为“会话”的上下文中执行。会话将图的op分发 到诸如CPU或GPU之类的设备上执行。
• 变量(Variable):运行过程中可以被改变,用于维护状态。
• 使用feed和fetch可以为任意的操作(Operation/op)赋值或者从其中获取数据。
(1) 线 与 节点
线:数据流,即tensor对象
点:数学操作(通常包括操作后的结果)
(2)tensor对象 ------ 数据,张量
• TensorFlow使用Tensor数据结构来代表所有数据,计算图中, 操作间传递的数据都是Tensor。Tensor可以看作是一个n维的
数组或者列表,一个Tensor主要由一个静态数据类型和动态类型的 维数(Rank、Shape)组成。Tensor可以在图中的节点之
间流通
(3)边
• TensorFlow的边即有两种连接关系:
• 数据依赖
• 控制依赖
• 实线边表示数据依赖,代表数据,即张量。任意维度的数据统称为张量。 在机器学习算法中,张量在数据流图中从前往后流动一遍
就完成一次前向传 播,而残差从后向前流动一遍就完成一次反向传播。
• 虚线边表示控制依赖,可以用于控制操作的运行,这被用来确保happensbefore关系,这类边上没有数据流过,但源节点必须在目的节
点开始执行前 完成。 ------------ 控制依赖没有数据流通
控制依赖详情见下文
(4)数据属性
(5)节点计算API
1、TensorFlow 创建图、多个图管理
1.4 TensorFlow 不允许不同的图的tensor对象之间互相运算
(1)创建图的API ------- tf.Graph()
1、tf.Graph() ------- 创建图,通常用with关键字使用
eg:
make_graph = tf.Graph()
print(make_graph)
with make_graph.as_default(): ------ 将上图更改为默认图
(2)with 关键字创建图 ------- with tf.Graph().as_default():
1、with关键字下的代码均是该执行图的代码
import tensorflow as tf
# 执行图的创建
with tf.Graph().as_default():
print('获取当前的默认图为:{}'.format(tf.get_default_graph()))
a = tf.constant(value = [1,2,3,4],dtype=tf.float64,shape = [4,1],name='constant_a')
print('a 的所属图为默认图:{}'.format(a.graph))
# 执行图的执行
with tf.Session() as sess:
pass
结果:
获取当前的默认图为:<tensorflow.python.framework.ops.Graph object at 0x00000275021BE2B0>
a 的所属图为默认图:<tensorflow.python.framework.ops.Graph object at 0x00000275021BE2B0>
- 多个 with 创建的执行图是多张图
import tensorflow as tf
--------------------------- 第一张图
with tf.Graph().as_default():
print('获取当前的默认图为:{}'.format(tf.get_default_graph()))
a = tf.constant(value = [1,2,3,4],dtype=tf.float64,shape = [4,1],name='constant_a')
print('a 的所属图为默认图:{}'.format(a.graph))
# 执行图的执行
with tf.Session() as sess:
pass
--------------------------- 第二张图
with tf.Graph().as_default():
print('获取当前的默认图为:{}'.format(tf.get_default_graph()))
a = tf.constant(value = [1,2,3,4],dtype=tf.float64,shape = [4,1],name='constant_a')
print('a 的所属图为默认图:{}'.format(a.graph))
# 执行图的执行
with tf.Session() as sess1:
pass
结果:
获取当前的默认图为:<tensorflow.python.framework.ops.Graph object at 0x00000275021BE2B0>
a 的所属图为默认图:<tensorflow.python.framework.ops.Graph object at 0x00000275021BE2B0>
获取当前的默认图为:<tensorflow.python.framework.ops.Graph object at 0x00000275021CB470>
a 的所属图为默认图:<tensorflow.python.framework.ops.Graph object at 0x00000275021CB470>
2、TensorFlow执行会话Session API
(1)会话的创建API ------ tf.Session()
1、单独使用:
tf.Session() --------- 创建会话,通常用with关键字使用,with关键字自动关闭会话
'''
def __init__(self, target='', graph=None, config=None):
target='', --------- 给定连接的url,只有当分布式运行的时候需要给定
graph=None, --------- 给定当前Session对应的图,默认为TensorFlow中的默认图
(tf.get_default_graph());
config=None -------- 给定当前Session的相关参数,一般不给定。
'''
2、通过with关键字创建会话:
with tf.Graph().as_default():
print('执行图的创建')
# 执行图的执行
with tf.Session() as sess1:
print('执行图会话创建')
with tf.Session(config=tf.ConfigProto(allow_soft_placement=True,
log_device_placement=True)) as sess:
(2)会话的运行 ------- Session对象.run()
Session也可以使用 Tensor.eval()和Operation.run()获取数据/执行操作(只要明确当前 会话)。
--------- 会话运行单个值 ----- 单个tensor对象用 .eval()方法,操作对象用 .run()方法
1、会话运行多个值 .run() ------ 可以获得多个tensor对象和操作的数据
sess.run()
'''
def run(self, fetches, feed_dict=None, options=None, run_metadata=None):
fetches ----- 获取的 tensor对象和操作对象,可以获取多个,获取多个时是一个列表。
feed_dict=None, ----- 执行图运行时占位符传入的参数字典
'''
注意:上下两个 .run()语句,每一次都会从头将图运行一遍,因此如果图中有随机数的模块时两次运行的结果不一致。
例:
print(sess.run(a))
print(sess.run(a)) ----- 加入a是包含随机数模块,上下两次运行的结果不同
解决方案:① 设定随机数种子 ② 用一个 .run([a,a]) 语句
2、会话运行单个值 ----- 单个tensor对象用 .eval()方法,操作对象用 .run()方法
eg:
print('执行图中获取单个tensor对象数据为:{}'.format(tensor对象.eval()))
3、基于Tensor对象的名称获取tensor对象值
tmp = tf.get_default_graph().get_tensor_by_name(name='n2/t1/w1222:0')
print(tmp)
------------------------------------------------------------------------------------------
4、注意操作名 与 tensor对象 name属性 的区别。
predict_ = sess.run([predict],feed_dict={input_x:X}) ----- predict、input_x 都是操作名,
且input_x 不用加 ' '
input_x = tf.get_default_graph().get_tensor_by_name('X:0') ---- 'X:0' 是tensor 的name属性
(3)InteractiveSession() 交互式会话
import tensorflow as tf
a = tf.constant([111,22,3,3,34,5],dtype=tf.float64,shape=[2,3],name='test')
tf.InteractiveSession()
print(a.eval())
3、TensorFlow变量( .Variable() 、get_variable() )
彻底弄懂tf.Variable、tf.get_variable、tf.variable_scope以及tf.name_scope异同
• 变量(Variables)是维护图执行过程中的状态信息。在训练模型过程中, 可以通过变量来存储和更新参数。
变量包含张量(Tensor)存放于内存的缓存区。建模的时候变量必须被明确的初始化,模型训练后变量必须被存 储到磁盘。
这些变量的值可以在之后的模型训练和分析中被加载。
• 在构建变量的时候,必须将一个张量或者可以转化为张量的Python对象 作为初始值传入构造函数Variable中。
----------------- 即变量必须有初始值且Session必须初始化
• 特别注意:变量的全局初始化(tf.initialize_all_variables())是并行执行的, 如果存在变量之间的依赖关系的时候,再
进行初始化的时候要特别注意(1.4版本后无需考虑)。
# 定义变量初始值
w_initial_value = tf.random_normal(shape=[feature,1], mean=0.0, stddev=0.1, dtype=tf.float32)
'''
注意:这些随机数生成API默认数据是 tf.float32,如果变量用的是tf.float64,那么随机数dtype属性需要更改,否则报错;例:
w = tf.Variable(
initial_value=tf.random_normal(shape=[feature,1], mean=0.0, stddev=0.1,
dtype=tf.float64) ,
dtype=tf.float64, name='w')
'''
w = tf.Variable(
initial_value=w_initial_value,
dtype=tf.float32, name='w') ----- 定义变量
# 变量的初始化
with tf.Session() as sess:
# NOTE: 一般情况下,建议大家在进行遍历初始化之后,尽量不要再创建变量。
# 获取全局变量初始化的操作对象
init_op = tf.global_variables_initializer() ------ 这是获取全局变量初始化的操作
# 进行变量初始化操作
init_op.run() 或 sess.run(init_op) ------ 会话执行该操作进行变量初始化
===================================== API ======================================
tf.Variable()
'''
def __init__(self,
initial_value=None, ------- 初始化值,它是一个值,区别于get_variable()中参数 initializer
trainable=True,
collections=None,
validate_shape=True,
caching_device=None,
name=None,
variable_def=None,
dtype=None,
expected_shape=None,
import_scope=None,
constraint=None):
功能:创建一个新的变量对象,变量的值设置为initial_value
参数:
initial_value: 给定这个变量的初始化的值
trainable: 指定这个变量是否参数模型训练,默认是参与。
validate_shape:指定对于该变量更新前后是否考虑形状大小一致的情况,设置为True表示要求更新前后的内容
要求格式一致。
dtype:给定数据类型
'''
w1 = tf.get_variable(name='w1', shape=[2], dtype=tf.float32,
initializer=tf.random_normal_initializer(mean=0.0, stddev=1.0))
'''
def get_variable(name, ---------- 给定tensor对象操作op名(注意不是 .name属性),存在获
取,不存在创建(注意变量作用域的概念,下文讲解)
shape=None,
dtype=None,
initializer=None, ----------- 初始化器,接收的是一个对象
regularizer=None,
trainable=True,
collections=None,
caching_device=None,
partitioner=None,
validate_shape=True,
use_resource=None,
custom_getter=None,
constraint=None):
功能:基于给定的name参数从TensorFlow内部获取名称对应的变量对象,如果变量存在,直接返回对应的变量,如果变量不
存在,进行创建操作,通常和变量作用域 with tf.variable_scope('t1',
reuse=tf.AUTO_REUSE): 一起使用有效。
'''
4、TensorFlow Fetch
• 为了取回操作的输出内容,可以在使用Session对象的run方法调用执行图的 时候,传入一些tensor,通过run方法就可以获取
这些tensor对应的结果值。
• 如果需要获取多个tensor的值,那么尽量一次运行就获取所有的结果值,而 不是采用逐个获取的方式。
for step in range(800):
train_op1,loss1 = sess.run(fetches=[train_op,loss],feed_dict={input_x:X,input_y:Y})
'''注意: 运行的结果的变量尽量不要与构建执行图的变量相同,以防止会话再循环执行时出现错误。'''
print('原损失函数值为{},第{}步迭代后的损失函数的值为{}'.format(loss1,step+1,train_op1))
5、TensorFlow Feed
• Tensorflow还提供了填充机制(feed),可以在构建图时使用 placeholder类型的API临时替代任意操作的张量(占位符),在调
用Session对象的run()方法去执行图时,使用填充数据作为调用的参数, 调用结束后,填充数据就消失了。
• feed使用一个tensor值临时替换一个操作的输出结果,在获取数据的时 候必须给定对应的feed数据作为参数。feed只有在
调用它的方法内有效, 方法结束,feed就消失了。
• feed可以使用placeholder类型的API创建占位符,常见API: tf.placeholder、tf.placeholder_with_default(这
个是带有默认值的占位符)
for step in range(800):
train_op1,loss1 = sess.run(fetches=[train_op,loss],feed_dict={input_x:X,input_y:Y})
'''注意: 运行的结果的变量尽量不要与构建执行图的变量相同,以防止会话再循环执行时出现错误。'''
print('原损失函数值为{},第{}步迭代后的损失函数的值为{}'.format(loss1,step+1,train_op1))
============================ 占位符 API =========================================
x = tf.placeholder(dtype=tf.float32, shape=[4, 3], name='x')
def placeholder(dtype, shape=None, name=None):
c = tf.placeholder_with_default(input=1.0, shape=[], name='c') -------- 带有默认值的占未符
def placeholder_with_default(input, shape, name=None):
=================================================================================
x = tf.placeholder(dtype=tf.float32, shape=[None, 3], name='x') ------- None代表横向维度不限制
6、TensorFlow控制依赖
(1)TensorFlow变量更新(.assign()、assign_add、assign_sub )
TensorFlow更新变量不能直接赋值更新(直接赋值( sum = tf.add(sum,i) )会生成一个新的名字相同的tensor对象,并不是
赋值更新变量的值)
# a. 定义一个占位符,表示一个数字
input_x = tf.placeholder(dtype=tf.float32, shape=None)
# b. 创建一个变量,用于存储累加值
sum = tf.Variable(dtype=tf.float32, initial_value=0.0, name='sum')
print(sum)
# c. 做一个累加操作
tmp = tf.add(input_x, sum)
# ref: 给定需要更新的tensor对象值
# value: 给定更新的具体value值
# 下面这行代码的意思是:将tmp的值赋值给sum对象
assign_op = tf.assign(sum, tmp) ----- assign_op 是赋值操作(可以直接fetch更新后的值),将临时值tmp更新至
变量sum中。也可直接用 assign_add() , 如:assign_op = tf.a
ssign_add(sum,input_x)
实现以下两个功能 (变量更新)
• 1. 实现一个累加器,并且每一步均输出累加器的结果值。
• 2. 编写一段代码,实现动态的更新变量的维度数目
============================= 更新变量(累加和) ===========================================
import tensorflow as tf
#1. 图构建
with tf.Graph().as_default():
# 定义占位符
input_x = tf.placeholder(dtype=tf.float32,shape=None,name='i_x')
print(input_x)
# 定义加和变量
sum = tf.Variable(initial_value=0.0,dtype=tf.float32,name='s_m')
# 更新变量值
assign_op = tf.assign_add(sum,input_x,name='assign_adddddd')
# 2. 运行
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# 0. 加载数据
datas = [1,2,4,66,7,8]
for data in datas:
print(data)
assign_op_,sum_ = sess.run([assign_op,sum],feed_dict={input_x:data})
'''
---- feed_dict 传入参数的字典key是操作OP名,而不是属性 name 值;
'''
print('更新操作的值:{}'.format(assign_op_))
print('更新变量的值:{}'.format(sum_))
=============================== 2. ===============================================
'''
• 2. 编写一段代码,实现动态的更新变量的维度数目
'''
# 图构建
with tf.Graph().as_default():
# 定义变量
x = tf.Variable(initial_value=[[0]],
dtype=tf.float32,
name='ndarray_Var',
validate_shape=False)
'''
validate_shape 为False表示不会进行维度校验
'''
# 合并数组(合并数的临时值)
concat_tmp = tf.concat([x,[[1.0,2.0,3.0]]],axis=1)
# 更新数组
concat_op = tf.assign(x,concat_tmp,validate_shape=False)
'''
validate_shape 为False表示不会进行维度校验
'''
# 图运行
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(5):
output = sess.run(concat_op)
print('运行的结果是:{}'.format(output))
(2)控制依赖( tf.control_dependencies( [操作OP] ) )
• 我们可以通过Variable和assign API完成变量的定义和更新,但是如果在更 新变量之前需要更新其它变量,那么会导致一个比较严
重的问题:也就是需 要多次调用sess.run方法来进行变量的更新。通过这种方式,代码复杂程度 上升,同时也没有执行效率。
• 解决该问题的方案就是:控制依赖。通过TensorFlow中提供的一组函数来 处理不完全依赖的情况下的操作排序问题(即给定哪个操作
先执行的问题), 通过tf.control_dependencies API完成。
========================================= 3. =====================================
'''
• 3. 实现一个求解阶乘的代码(构建一个控制依赖的代码)
'''
with tf.Graph().as_default():
# 一、图的构建
# a. 定义一个占位符,表示一个数字
input_x = tf.placeholder(dtype=tf.float32, shape=None)
# b. 创建一个变量,用于存储累加值
sum = tf.Variable(dtype=tf.float32, initial_value=1.0, name='sum')
# c. 做一个累加操作
tmp = input_x * sum
assign_op = tf.assign(sum, tmp)
# d. 加一个控制依赖 ----------- 添加控制依赖
with tf.control_dependencies([assign_op]): ----------- 控制依赖:with下面所有的语句执行前必须要将
assign_op这个操作执行一遍
sum = tf.Print(sum, data=[sum], message="数据为:") ------------ 打印日志的API
y = sum + 0.1
# 二、图的执行
with tf.Session() as sess:
# 初始化变量
sess.run(tf.global_variables_initializer())
# 迭代计算累加值
n = 5
for data in range(1, n + 1):
r = sess.run([y], feed_dict={input_x: data})
print(r)
# 结果:
[1.1]
[2.0999999]
[6.0999999]
[24.1]
[120.1]
2019-07-25 16:36:25.421756: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] 数据为:[1]
2019-07-25 16:36:25.422536: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] 数据为:[2]
2019-07-25 16:36:25.423245: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] 数据为:[6]
2019-07-25 16:36:25.423877: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] 数据为:[24]
2019-07-25 16:36:25.424524: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] 数据为:[120]
------------------------------ 上述代码如果不加控制依赖 ---------------------------
即:
assign_op = tf.assign(sum, tmp)
sum = tf.Print(sum, data=[sum], message="数据为:")
y = sum + 0.1
# 结果:
[1.1]
[1.1]
[1.1]
[1.1]
[1.1]
2019-07-25 16:38:49.239043: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] 数据为:[1]
2019-07-25 16:38:49.239889: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] 数据为:[1]
2019-07-25 16:38:49.240536: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] 数据为:[1]
2019-07-25 16:38:49.241170: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] 数据为:[1]
2019-07-25 16:38:49.241837: I C:\tf_jenkins\home\workspace\rel-win\M\windows\PY\36\tensorflow\core\kernels\logging_ops.cc:79] 数据为:[1]
7、TensorFlow设备( with tf.device("/cpu:0"): )
• 设备是指一块可以用来运算并且拥有自己的地址空间的硬件,如CPU和GPU。Tensorflow 为了在执行操作的时候,充分利用计算资源,
可以明确指定操作在哪个设备上执行。
• 一般情况下,不需要显示指定使用CPU还是GPU,TensorFlow会自动检测。如果检测到 GPU,TensorFlow会尽可能地利用第一个GPU来
执行操作。注意:如果机器上有超过一个 可用的GPU,那么除了第一个外其它GPU默认是不参与计算的。所以,在实际TensorFlow
编程中,经常需要明确给定使用的CPU和GPU:
• “/cpu:0”:表示使用机器CPU运算
• “/gpu:0”:表示使用第一个GPU运算,如果有的话
• “/gpu:1”:表示使用第二个GPU运算,以此类推
将上述标题6中控制依赖的代码进行设备标注:
with tf.Graph().as_default():
# 一、图的构建
with tf.device("/cpu:0"): ----------- 固定用法,大小写无所谓
# a. 定义一个占位符,表示一个数字
input_x = tf.placeholder(dtype=tf.float32, shape=None)
# b. 创建一个变量,用于存储累加值
sum = tf.Variable(dtype=tf.float32, initial_value=1.0, name='sum')
with tf.device("/GPU:0"):
# c. 做一个累加操作
tmp = input_x * sum
assign_op = tf.assign(sum, tmp)
with tf.device("/gpu:1"):
# d. 加一个控制依赖
with tf.control_dependencies([assign_op]):
# sum = tf.Print(sum, data=[sum], message="数据为:")
y = sum * 3
# 二、图的执行
with tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True))
as sess:
'''
tf.Session 中动态cpu、gpu参数,防止 图构建中某些 Gpu不能使用将操作移至CPU中运行
'''
# 初始化变量
sess.run(tf.global_variables_initializer())
# 迭代计算累加值
n = 5
for data in range(1, n + 1):
r = sess.run([y], feed_dict={input_x: data})
print(r)
8、TensorFlow变量两种作用域
• 通过tf.Variable我们可以创建变量,但是当模型复杂的时候,需要构建大量的变量 集,这样会导致我们对于变量管理的复杂性,而且
没法共享变量(存在多个相似的 变量)。针对这个问题,可以通过TensorFlow提供的变量作用域机制来解决,在构 建一个图的时
候,就可以非常容易的使用共享命名过的变量。
• Tensorflow中有两个作用域,一个是name_scope,另一个是variable_scope。
(1)变量的作用域 tf.variable_scope( 域名 , reuse=tf.AUTO_REUSE)
• tf.variable_score方法的作用就是定义一个作用域,定义在variable_score作用域 中的变量和操作,会将variable score的
名称作为前缀添加到变量/操作名称前,支 持嵌套的作用域,添加前缀规则和文件目录路径的规则类似。
• tf.variable_score参数如果给定的是一个已经存在的作用域对象的时候,那么构建 变量的时候表示直接跳过当前作用域前缀,
直接成为一个完全不同与现在的作用域 (直接创建给定作用域下的变量)。但是构建操作的时候,还是和嵌套的方式一样, 直
接添加子作用域。
• tf.variable_score参数中,可以给定当前作用域中默认的初始化器initializer,并 且子作用域会直接继承父作用域的相关参
数(是否重用、默认初始化器等)
• 变量作用域机制在TensorFlow中主要通过两部分组成:
• tf.get_variable:通过所给定的名字创建或者返回一个对应的变量
• tf.variable_scope:为通过创建的变量或者操作Operation指定命名空间
• tf.get_variable方法在调用的时候,主要需要给定参数名称name,形状shape, 数据类型dtype以及初始化方式initializer
四个参数。该API底层执行的时候,根据 variable score的属性reuse的值决定采用何种方式来获取变量。当reuse值为Fals
e 的时候(不允许设置),作用域就是创建新变量设置的,此时要求对应的变量不存在, 否则报错;当reuse值为True的时候,
作用域就是为重用变量所设置的,此时要求 对应的变量必须存在,否则报错。当reuse的值为tf.AUTO_REUSE的
时候,表示 如果变量存在就重用变量,如果变量不存在,就创建新变量返回。(备注:reuse一 般设置在variable score
对象上)
• TF底层使用'变量作用域/变量名称:0'的方式标志变量(eg: func/op1/weight:0)。
特点:
1、tensorflow一张图内,如果创建多个相同的变量会产生不同的tensor对象,它们不会共用重复一个
例:
w11 = tf.Variable(initial_value=tf.random_normal(shape=[2],dtype = tf.float64),
dtype=tf.float64,name='w1')
w12 = tf.Variable(initial_value=tf.random_normal(shape=[2],dtype = tf.float64),
dtype=tf.float64,name='w1')
w13 = tf.Variable(initial_value=tf.random_normal(shape=[2],dtype = tf.float64),
dtype=tf.float64,name='w1')
print(w11.name) # w1:0
print(w12.name) # w1_1:0
print(w13.name) # w1_2:0
'''
由于他们不是一个对象,因此w11、w12、w13 随机数的值也不相同。
解决方式:变量的作用域
with tf.variable_scope('t1', reuse=tf.AUTO_REUSE):
参数:
reuse=tf.AUTO_REUSE ---- 变量重复时自动覆盖使用前一个
'''
2、变量的作用域是可以嵌套的,但是与python变量作用域不同的是:子父作用域之间可以相互访问计算
例:
def f2():
w1 = tf.get_variable(name='w1', shape=[2], dtype=tf.float32,
initializer=tf.random_normal_initializer(mean=0.0, stddev=1.0))
'''
参数name ---------- 给定tensor对象操作op名(注意不是 .name属性),存在获
取,不存在创建
'''
return w1
with tf.variable_scope('t1', reuse=tf.AUTO_REUSE):
with tf.variable_scope('t2'):
w12 = f2()
w22 = f2()
w33 = tf.add(w12,w22) -------- 子父作用域之间可以相互访问计算
tf.variable_scope()
def __init__(self,
name_or_scope,
default_name=None,
values=None,
initializer=None,
regularizer=None,
caching_device=None,
partitioner=None,
custom_getter=None,
reuse=None,
dtype=None,
use_resource=None,
constraint=None):
参数:
name_or_scope 域名
reuse=None 是否重用,一般用 tf.AUTO_REUSE
initializer 定义这个域名下默认的初始化器
dtype=None 定义这个域名下默认的数据类型
例1:
import tensorflow as tf
import numpy as np
import pandas as pd
------------------------------- 定义变量作用域
def f1():
w1 = tf.Variable(initial_value=tf.random_normal(shape=[2],dtype = tf.float64),dtype=tf.float64,
name='w111111')
print(w1)
return w1
def f2():
w1 = tf.get_variable(name = 'w1',initializer=tf.random_normal_initializer(dtype=tf.float64),shape=[2],dtype=tf.float64)
'''
参数 name : ---------- 给定tensor对象操作op名(注意不是 .name属性),存在获
取,不存在创建
'''
return w1
if __name__ == '__main__':
w11 = f1()
w21 = f1()
with tf.variable_scope('t1',reuse=tf.AUTO_REUSE): # reuse=tf.AUTO_REUSE,变量
# 重复时自动覆盖使用前一个变量
w12 = f2()
w22 = f2()
print(w11.name)
print(w21.name)
print(w12.name)
print(w22.name)
'''
结果:
w111111:0
w111111_1:0
t1/w111111:0 -------- t1 为变量作用域
t1/w111111:0
'''
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# 获取值
print('获取值为:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ')
print(sess.run([w11,w11,w21])) # w11与w21值不同,再次验证它们是不同的tensor对象
print(sess.run([w11, w21,w12,w22])) # w11,w21值不同(两个tensor对象),w12、w22是同一个tensor对象。
例2:
• tf.variable_score参数中,可以给定当前作用域中默认的初始化器initializer,并 且子作用域会直接继承父作用域的相关参
数(是否重用、默认初始化器等)
(2)with tf.name_score(): 可视化变量划分范围
• TensorFlow中的name_score和variable_score是两个不同的东西,name_score的主要作用 是为op_name前加前缀,variabl
e_score是为get_variable创建的变量的名字加前缀。简单来 讲:使用tf.Variable创建的变量受name_score和va
riable_score的的效果,会给变量添加前缀, 但是使用tf.get_variable创建变量只受variable_score的效果。
• name_score的主要作用就是:Tensorflow中常常会有数以千计的节点,在可视化的过程中很 难一下子展示出来,因此用name_s
cope为变量划分范围,在可视化中,这表示在计算图中的 一个层级。name_scope会影响op_name,不会影响用get_variab
le()创建的变量,而会影响 通过Variable()创建的变量。
• 注意:variable_score内部会创建一个同名的name_score
9、TensorFlow 训练和预测代码结构
# 实际写代码的时候一般结构为:
with tf.Graph().as_default():
# 1. 基于业务知识构建执行图对象
# 2. 运行
with tf.Session() as sess:
# 0. 加载数据
# 1. 图执行
# 2. 图效果查看
# 3. 持久化
pass
pass
# 持久化模型的应用代码结构
with tf.Graph().as_default():
# 1. 和训练过程完全一样构建执行图
# 2. 运行
with tf.Session() as sess:
# 0. 加载模型
# 1. 使用模型预测获取预测结果
pass
pass
# 持久化模型的应用代码结构
with tf.Graph().as_default():
with tf.Session() as sess:
# 0. 加载模型、同时加载执行图的信息
# 1. 使用模型预测获取预测结果
pass
pass
10、TensorFlow损失函数优化器构建
# 计算预测结果
predict = tf.add(tf.matmul(input_x, w), b, name='predict')
# 构建损失函数(回归用MSE、分类用加叉熵损失函数)
loss = tf.reduce_mean(tf.square(input_y - predict))
# 构建优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
# 对损失函数进行优化操作
train_op = optimizer.minimize(loss = loss) # 返回值为None
11、TensorFlow可视化
• TensorBoard通过读取TensorFlow的事件文件来运行, TensorFlow的事件文件包括了在TensorFlow运行中涉及到的主 要数据,比
如:scalar、image、audio、histogram和graph等。
• 通过tf.summary相关API,将数据添加summary中,然后在 Session中执行这些操作得到一个序列化Summary protobuf对 象,然
后使用FileWriter对象将汇总的序列数据写入到磁盘,然 后使用tensorboard命令进行图标展示,默认访问端口是:6006
• TensorBoard中支持结构视图和设备视图。
• TensorBoard显示的时候,必须给定对应的数据聚合文件路径信息:cmd命令:tensorboard --logdir 文件路径
注意:
1.执行tensorboard命令的当前磁盘必须和日志文件所在的磁盘一致;
2.日志 文件中不允许出现中文和空格)。
如果 打不开的情况下: 后面加上 --host=127.0.0.1
eg : tensorboard --logdir=C:\Users\Hasee\Desktop\mine_project\spam_filter_system\graph\text_rnn\dev --host=127.0.0.1
============================= API =====================================================
1、构建一个标量的可视化 tensorflow操作对象(构建在graph中)
tf.summary.scalar()
def scalar(name, tensor, collections=None, family=None):
参数:
name ------ 操作对象的名字,随意定义
tensor ------ 给定需要可视化的tensor对象
2、合并所有的可视化输出操作(一般定义在graph中)
summary_all = tf.summary.merge_all()
3、构建一个日志输出对象(构建在Session中)
write = tf.summary.FileWriter()
参数:
def __init__(self,
logdir, ----- 给定输出文件夹路径
graph=None, ----- 给定需要输出的图,一般用 sess对象.graph
max_queue=10, ---- 给定输出队列长度,一般默认
flush_secs=120, ------- 跟定刷新的时间,可默认
graph_def=None,
filename_suffix=None):
4、在迭代过程中运行上述 summary_all 可视化操作对象
eg:
summary_data = sess.run(summary_all)
5、将sess运行所获得的可视化数据添加到上述 日志输出对象write
eg:
writer.add_summary(summary=summary_data, global_step=当前迭代步骤)
参数:
summary ------- 给定可视化合并操作对象
global_step ------- 给定当前迭代步骤顺序
6、迭代循环训练结束后关闭 日志输出文件对象 write
eg:
write.close()
graph:
# 构建损失函数
loss = tf.reduce_mean(tf.square(input_y - predict))
# 构建loss数值可视化操作对象
tf.summary.scalar('loss_value',loss) -------- 第一步
# 合并所有的可视化操作
summary_all = tf.summary.merge_all() -------- 第二步
# 构建优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
sess:
with tf.Session() as sess:
# 初始化变量值
sess.run(tf.global_variables_initializer())
# 构建日志输出对象
write = tf.summary.FileWriter('./model/log',graph=sess.graph) --- 第三步
# 2 执行图的执行
# a 数据加载
np.random.seed(28)
N = 50
X = np.array(np.linspace(0, 10, N) + np.random.normal(0, 0.1, N)).reshape(-1, 1)
Y = 20 * X + 7 + np.random.normal(0, 1, N).reshape(-1, 1)
print(Y.shape)
# b 数据清洗
# c 特征提取与数据分割
# 特征工程
# f 模型构建与模型训练
for step in range(800):
train_op1, loss1,summary_all_ = sess.run(fetches=[train_op, loss,summary_all],
feed_dict={input_x: X, input_y: Y}) ----- 第四步
'''
解释:每获取一次 train_op 相当于执行一次优化器优化操作,返回值为None,因此我没一般不接受该值。
注意: 运行的结果的变量尽量不要与构建执行图的变量相同,以防止会话再循环执行时出现错误。'''
print('原损失函数值为{},第{}步迭代后优化器的返回值为{}'.format(loss1, step + 1, train_op1))
# 将可视化输出数据添加至日志输出对象中
write.add_summary(summary=summary_all_,global_step=step) ----- 第五步
# 日志输出对象关闭
write.close() ------ 第六步
12、TensorFlow线程和队列 (最小批次的数据(mini batches) )
• QueueRunner类可以创建一组线程,这些线程可以重复的执行Qnquene 操作,同时使用Coordinator来处理线程同步终止,此
外QueueRunner内 部维护了一个closer thread,当Coordinator收到异常报告时,这个线程会 自动关闭队列。
13、TensorFlow数据的读取
• TensorFlow提供了三种方式来读取数据:
• 供给数据(Feeding):在TensorFlow程序运行的每一步,让Python代码 来供给数据
• 从文件读取数据(深度学习中主要应用):在TensorFlow图的起始,让一 个输入管线从文件中读取数据
• 预加载数据:在TensorFlow图中定义常量或变量来保存所有数据(仅适 合小规模数据集的情况)
14、TensorFlow模型持久化
• TensorFlow使用tf.train.Saver类实现模型的保存和提取。
1、Saver 对象的saver方法将TensorFlow模型保存到指定路径中。
2、Saver对象的restore方法可以加载模型,并通过保存好的模 型变量相关值重新加载完全加载进来。
• 如果不希望重复定义计算图上的运算,可以直接加载已经持久化 的图,通过tf.train.import_meta_graph方法直接加载
• 备注:在加载的时候,可以在Saver对象构建的时候,明确给定 变量名之间的映射关系
注意点:
1. 注意操作名 与 tensor对象 name属性 的区别。
predict_ = sess.run([predict],feed_dict={input_x:X}) ----- predict、input_x 都是操作名
input_x = tf.get_default_graph().get_tensor_by_name('X:0') ---- 'X:0' 是tensor 的name属性
(1)TensorFlow模型对象保存
===================================== TensorFlow模型对象保存 ================================
1.第一步:构建一个持久化对象(在session中)
saver = tf.train.Saver(max_to_keep=2)
'''
def __init__(self,
var_list=None,
reshape=False,
sharded=False,
max_to_keep=5, # 最多保存5个版本的模型参数(保留最近的5个版本的模型参数)
keep_checkpoint_every_n_hours=10000.0,
name=None,
restore_sequentially=False,
saver_def=None,
builder=None,
defer_build=False,
allow_empty=False,
write_version=saver_pb2.SaverDef.V2,
pad_step_number=False,
save_relative_paths=False,
filename=None):
'''
2.第二步:根据持久化对象save 做一个模型持久化的操作(在session迭代训练过程中)
saver.save(sess=sess, save_path='./models/11/model.ckpt', global_step=step)
参数:
sess ------ 给定会话对象
save_path ------- 给定模型保存的文件路径,用 .ckpt 结尾
global_step -------- 给定迭代步骤
例:
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
if __name__ == '__main__':
with tf.Graph().as_default():
# 1. 创建执行图
with tf.name_scope("network"):
# a. 定义占位符, shape中的None表示不做限制的意思
input_x = tf.placeholder(dtype=tf.float32, shape=[None, 1], name='x')
input_y = tf.placeholder(dtype=tf.float32, shape=[None, 1], name='y')
# b. 定义模型参数变量
w = tf.Variable(initial_value=[[-5]], dtype=tf.float32, name='w')
b = tf.Variable(initial_value=[3], dtype=tf.float32, name='b')
# c. 计算预测值y
y_ = tf.add(tf.matmul(input_x, w), b, name='Add')
print(y_.name)
with tf.name_scope("loss"):
# d. 基于预测值和实际值构建损失函数
loss = tf.reduce_mean(tf.square(input_y - y_), name='loss')
# 添加一个损失函数的可视化输出的操作对象(Op)
tf.summary.scalar('loss mean', loss)
with tf.name_scope("train"):
# e. 让损失函数最小的时候模型就是最优模型
# 定义一个优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
# 对损失函数进行优化操作
train_op = optimizer.minimize(loss=loss)
# f. 合并所有可视化输出操作
summary = tf.summary.merge_all()
# 2. 执行图运行
with tf.Session() as sess:
# 变量初始化 给定变量值
sess.run(tf.global_variables_initializer())
# 构建一个日志输出对象
writer = tf.summary.FileWriter(logdir='./models/11', graph=sess.graph)
# 构建一个持久化对象
"""
def __init__(self,
var_list=None, # 给定对那些模型参数(变量)做持久化保存操作。默认情况下是所有的变量;
该参数是一个字典的结构: eg: {'需要加载tensor变量name属性':变量},下文详解
reshape=False,
sharded=False,
max_to_keep=5, # 最多保存5个版本的模型参数(保留最近的5个版本的模型参数)
keep_checkpoint_every_n_hours=10000.0,
name=None,
restore_sequentially=False,
saver_def=None,
builder=None,
defer_build=False,
allow_empty=False,
write_version=saver_pb2.SaverDef.V2,
pad_step_number=False,
save_relative_paths=False,
filename=None):
"""
saver = tf.train.Saver(max_to_keep=2) ----------- 第一步:构建持久化对象
# 1. 随机数据产生、加载
np.random.seed(28)
N = 100
x = np.linspace(0, 6, N) + np.random.normal(0, 2.0, N)
y = 14 * x + 7 - np.random.normal(0, 5.0, N)
x.shape = -1, 1
y.shape = -1, 1
print((np.shape(x), np.shape(y)))
# 2. 获取数据进行模型训练
for step in range(100):
summary_, _, loss_ = sess.run(fetches=[summary, train_op, loss], feed_dict={
input_x: x, # 给定占位符的值
input_y: y # 给定占位符的值
})
print("第{}次训练后模型的损失函数值为:{}".format(step, loss_))
writer.add_summary(summary=summary_, global_step=step)
# 做一个模型持久化的操作
saver.save(sess=sess, save_path='./models/11/model.ckpt', global_step=step)
-------- 第二步:根据save对象将参数保存至文件路径中,文件后缀为 .ckpt
# 3. 使用训练好的模型对数据做一个预测
predict = sess.run(y_, feed_dict={input_x: x})
# 可视化画图
plt.plot(x, y, 'ro')
plt.plot(x, predict, 'g-')
plt.show()
writer.close()
(2)TensorFlow模型对象加载
===================================== TensorFlow模型对象加载 ================================
1、第一步:构建持久化对象
2、第二步:根据持久化对象加载模型
3、第三步:模型预测
注意:加载模型参数 需要构建原数据模型的graph,只是不需要训练模型graph了。如果不希望重复定义计算图上的运算,可以
直接加载已经持久化 的图,通过tf.train.import_meta_graph方法直接加载
- 例1: 构键原graph
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
if __name__ == '__main__':
with tf.Graph().as_default():
# 1. 创建执行图
with tf.name_scope("network"):
# a. 定义占位符, shape中的None表示不做限制的意思
input_x = tf.placeholder(dtype=tf.float32, shape=[None, 1], name='x')
input_y = tf.placeholder(dtype=tf.float32, shape=[None, 1], name='y')
# b. 定义模型参数变量
w = tf.Variable(initial_value=[[-5]], dtype=tf.float32, name='w1')
b = tf.Variable(initial_value=[3], dtype=tf.float32, name='b')
# c. 计算预测值y
y_ = tf.add(tf.matmul(input_x, w), b)
with tf.name_scope("loss"):
# d. 基于预测值和实际值构建损失函数
loss = tf.reduce_mean(tf.square(input_y - y_), name='loss')
# 添加一个损失函数的可视化输出的操作对象(Op)
tf.summary.scalar('loss mean', loss)
with tf.name_scope("train"):
# e. 让损失函数最小的时候模型就是最优模型
# 定义一个优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
# 对损失函数进行优化操作
train_op = optimizer.minimize(loss=loss)
with tf.Session() as sess:
# 构建一个持久化对象
"""
def __init__(self,
var_list=None, # 给定对那些模型参数(变量)做持久化保存操作。默认情况下是所有的变量
reshape=False,
sharded=False,
max_to_keep=5, # 最多保存5个版本的模型参数(保留最近的5个版本的模型参数)
keep_checkpoint_every_n_hours=10000.0,
name=None,
restore_sequentially=False,
saver_def=None,
builder=None,
defer_build=False,
allow_empty=False,
write_version=saver_pb2.SaverDef.V2,
pad_step_number=False,
save_relative_paths=False,
filename=None):
"""
saver = tf.train.Saver({"network/w": w, "network/b": b},
max_to_keep=2) ----------第一步:创建模型持久化对象
---------- 第二步:加载模型
# 做一个变量的加载恢复的操作
# 方式一:直接给定模型的路径
saver.restore(sess=sess, save_path="./models/11/model.ckpt-99")
# 方式二:获取最后一个模型的保存路径然后进行加载
model_checkpoint_path = tf.train.latest_checkpoint("./models/11")
print(model_checkpoint_path)
saver.restore(sess=sess, save_path=model_checkpoint_path)
# 1. 随机数据产生、加载
np.random.seed(28)
N = 100
x = np.linspace(0, 6, N) + np.random.normal(0, 2.0, N)
y = 14 * x + 7 - np.random.normal(0, 5.0, N)
x.shape = -1, 1
y.shape = -1, 1
print((np.shape(x), np.shape(y)))
# 3. 使用训练好的模型对数据做一个预测
predict = sess.run(y_, feed_dict={input_x: x}) ------- 第三步:加载模型预测
# 可视化画图
plt.plot(x, y, 'ro')
plt.plot(x, predict, 'g-')
plt.show()
- 例2: 通过tf.train.import_meta_graph方法直接加载 graph
import tensorflow as tf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
with tf.Graph().as_default():
with tf.Session() as sess:
# 构建持久化对象
model_checkpoint_path = tf.train.latest_checkpoint('./model/linears') --- 第一步:获取
最后一个参数 w b 的文件路径
print(model_checkpoint_path)
save = tf.train.import_meta_graph(meta_graph_or_file='{}.meta'.format(model_checkpoint_path))
--------- 第二步:自动插入模型graph并构建持久化对象
# 加载模型
save.restore(sess=sess,save_path=model_checkpoint_path) ----- 第三步:加载模型至会话 sess
# 模型预测
# 数据加载
np.random.seed(28)
N = 50
X = np.array(np.linspace(0, 10, N) + np.random.normal(0, 0.1, N)).reshape(-1, 1)
Y = 20 * X + 7 + np.random.normal(0, 1, N).reshape(-1, 1)
print(Y.shape)
# 必须先获取tensor对象
input_x = tf.get_default_graph().get_tensor_by_name('X:0') ------ 第四步:获取预测所用
到的tensor对象(注意:后面参数是 tensor的name属性,而不是操作op名,因此需要加 :0 )
predict = tf.get_default_graph().get_tensor_by_name('predict:0')
# 模型预测
predict_ = sess.run([predict],feed_dict={input_x:X}) ----- 第五步:模型预测
print(Y)
print(predict_)
(3)TensorFlow训练断点续传持久化 (主要分五步)
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
if __name__ == '__main__':
with tf.Graph().as_default():
# 0. 创建全局共享变量
global_step = tf.train.get_or_create_global_step() ----- 第一步:创建全局共享变量
# 1. 创建执行图
with tf.name_scope("network"):
# a. 定义占位符, shape中的None表示不做限制的意思
input_x = tf.placeholder(dtype=tf.float32, shape=[None, 1], name='x')
input_y = tf.placeholder(dtype=tf.float32, shape=[None, 1], name='y')
# b. 定义模型参数变量
w = tf.Variable(initial_value=[[-5]], dtype=tf.float32, name='w')
b = tf.Variable(initial_value=[3], dtype=tf.float32, name='b')
# c. 计算预测值y
y_ = tf.add(tf.matmul(input_x, w), b, name='Add')
print(y_.name)
with tf.name_scope("loss"):
# d. 基于预测值和实际值构建损失函数
loss = tf.reduce_mean(tf.square(input_y - y_), name='loss')
# 添加一个损失函数的可视化输出的操作对象(Op)
tf.summary.scalar('loss mean', loss)
with tf.name_scope("train"):
# e. 让损失函数最小的时候模型就是最优模型
# 定义一个优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
# 对损失函数进行优化操作
train_op = optimizer.minimize(loss=loss, global_step=global_step) ----- 第二步:将共享
全局变量赋给参数 global_step =
# f. 合并所有可视化输出操作
summary = tf.summary.merge_all()
# 2. 执行图运行
with tf.Session() as sess:
# 获取持久化的对象、构建一个持久化对象
----------------------------- 第三步:以下可以当做固定用法,断点持久化模型参数 ----------------------
ckpt = tf.train.get_checkpoint_state("./models/14/model") ------ 如果模型没有持久化保存参数
,返回值为None
saver = tf.train.Saver()
if ckpt and ckpt.model_checkpoint_path:
print("进行变量的加载恢复操作,非第一次模型训练...")
# 加载模型参数
saver.restore(sess=sess, save_path=ckpt.model_checkpoint_path)
# 加载管理历史记录信息
saver.recover_last_checkpoints(checkpoint_paths=ckpt.all_model_checkpoint_paths)
else:
print("进行变量初始化操作,第一次模型训练....")
# 变量初始化 给定变量值
sess.run(tf.global_variables_initializer())
------------------------------------------------------------------------------------------------
# 构建一个日志输出对象
writer = tf.summary.FileWriter(logdir='./models/14/graph', graph=sess.graph)
# 1. 随机数据产生、加载
np.random.seed(28)
N = 100
x = np.linspace(0, 6, N) + np.random.normal(0, 2.0, N)
y = 14 * x + 7 - np.random.normal(0, 5.0, N)
x.shape = -1, 1
y.shape = -1, 1
print((np.shape(x), np.shape(y)))
# 2. 获取数据进行模型训练
_global_step = sess.run(global_step) ------- 第四步:获取全局共享变量
for step in range(_global_step, 100 + _global_step): ------ 第五步:将全局共享变量
代入 for 迭代模型训练
summary_, _, loss_ = sess.run(fetches=[summary, train_op, loss], feed_dict={
input_x: x, # 给定占位符的值
input_y: y # 给定占位符的值
})
print("第{}次训练后模型的损失函数值为:{}".format(step, loss_))
writer.add_summary(summary=summary_, global_step=step)
# 做一个模型持久化的操作
saver.save(sess=sess,
save_path='./models/14/model/model.ckpt',
global_step=step)
# if step >= 2:
# break
# 3. 使用训练好的模型对数据做一个预测
predict = sess.run(y_, feed_dict={input_x: x})
# 可视化画图
plt.plot(x, y, 'ro')
plt.plot(x, predict, 'g-')
plt.show()
writer.close()
15、TensorFlow分布式训练
(1)TensorFlow分布式训练基本概念
背景:
• 使用单台机器或者单个GPU/CPU来进行模型训练,训练速度会受资源的影响,因 为毕竟单个的设备的计算能力和存储能力具有一
定的上限的,针对这个问题, TensorFlow支持分布式模型运算,支持多机器、多GPU、多CPU各种模型的组合 运行方案的设
计。(默认情况下,TensorFlow程序会将程序运行在第一个GPU上< 如果有GPU,并且安装的TensorFlow支持GPU运行>)
• TensorFlow的分布式支持单机多GPU、单机GPU+CPU、多机GPU等结构,不过 所有结构的构建方式基本类似。
• 除了TensorFlow外,Caffe、DeepLearning4j等也支持分布式训练,并且其中 DeepLearning4j的分布式效果相对比较成熟
概念:
• TensorFlow中的集群(Cluster)指的是一 系列能够对TensorFlow中的图(graph)进 行分布式计算的任务(task)。每个任务
是 同服务(server)相关联的。TensorFlow中 的服务会包含一个用于创建session的主 节点和至少一个用于图运算的工
作节点。 另外在TensorFlow中,一个集群可以被拆 分为一个或者多个作业(job),每个作业可 以包含至少一个任务
(2)TensorFlow分布式训练代码过程
• TensorFlow分布式集群的构建主要通过代码实现,主要步骤如 下:
• 创建集群(Cluster) :
• 创建一个tf.train.ClusterSpec用于对集群中的所有任务进行描述,该描述内容对 于所有内容应该是相同的。
• 创建tf.train.Server并将tf.train.ClusterSpec中参数传入构造函数,
• 使用tf.device API指定运算的设备,构建计算图,最后提交运算
• 备注:TensorFlow负责内部作业之间的数据传输
(3)TensorFlow分布式训练的内部操作
• TensorFlow中主要包含两个方面:
第一:对不同数据大小进行 计算的任务(work作业)
第二:用于不停更新共享参数的任务 (ps作业)。
这样任务都可以运行不同在机器上,在TensorFlow中, 主要实现方式如下:
• 图内的拷贝(In-Graph Replication)
• 图间的拷贝(Between-Graph Replication)
• 异步训练(Asynchronous Training)
• 同步训练(Synchronous Training)
• 在In-Graph Replication模式中,指定整个集群由一个客户端来构建图,并且这个客户端 来提交图到集群中,worker只负责处理
执行任务。In-Graph模式的好处在于解耦了 TensorFlow集群和训练应用之间的关系,这样可以提前构建好参数服务器和计算服务
器, 而这些角色本身不需要额外的逻辑代码,只需要使用join等待即可,真正的训练逻辑全部 位于客户端,具有足够高的灵活
性。
• 在Between-Graph Replication模式中,每个客户端会构建一个相似的图结构,该结构 中的参数均通过ps作业进行声明并使用tf.t
rain.replica_device_setter方法将参数映射到不 同的任务作业中。
• 备注:在小规模数据
集的情况下,In-Graph Replication经常使用。在海量数据的训练过 程中,不建议使用该方式,建议使用Between-Graph Repl
ication模式。
• Synchronous Training:在同步训练中,每个graph的副本读取相同的 parameter值,并行的计算,然后将计算完的结果放到
一起处理。在TensorFlow 中,如果是Between-graph replication的情况下,可以通过 tf.train.SyncRe
plicasOptimizer来处理,如果是In-graph replication情况下,直 接对结果进行处理即可(比如平均).
• Asynchronous Training:在异步训练中,每个任务计算完后,就会直接使用计 算出的结果更新parameter值。不同的任务之
间不存在协调进度。
• 同步训练需要等待最慢的一个任务执行完后,才可用更新参数;异步训练中,可 以每执行完一个任务,就更新一次参数。一般情
况下,建议使用异步训练。
================================ server ==================================================
import tensorflow as tf
# 0. 定义外部传参数
tf.app.flags.DEFINE_string('job_name', default_value='work',
docstring='必须给定一个任务名称,可选值: ps or work')
tf.app.flags.DEFINE_integer('task_index', default_value=0,
docstring='必须给定一个启动的id')
FLAGS = tf.app.flags.FLAGS
# 1. 定义服务器(节点)都在哪些机器上,并且使用什么端口号提供服务
# ps:表示用于变量的存储节点
# work:表示用于工作计算的节点
ps_hosts = ['127.0.0.1:33331', '127.0.0.1:33332']
work_hosts = ['127.0.0.1:33333', '127.0.0.1:33334', '127.0.0.1:33335']
cluster = tf.train.ClusterSpec({'ps': ps_hosts, 'work': work_hosts})
def main(_):
# 构建server服务器
server = tf.train.Server(cluster, job_name=FLAGS.job_name, task_index=FLAGS.task_index)
# 启动线程等待client的链接
server.join()
if __name__ == '__main__':
# 默认会调用当前py文件中的main函数
tf.app.run()
=================================== cluster =============================================
import numpy as np
import tensorflow as tf
# v1 = tf.constant(np.random.rand(10).astype(np.float32), name='abc')
# y = v1 * 0.1 + 0.3
with tf.device("/job:ps/task:1"):
v1 = tf.constant(np.random.rand(10).astype(np.float32))
with tf.device("/job:work/task:0"):
y = v1 * 0.1 + 0.3
with tf.Session(target='grpc://localhost:33335',
config=tf.ConfigProto(log_device_placement=True)) as sess:
# with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
print(sess.run(y))
二、TensorFlow基本模型构建实例
1、TensorFlow实现机器学习模型
-
TensorFlow实现线性回归
import tensorflow as tf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
if __name__ == '__main__':
with tf.Graph().as_default():
# 1 执行图的的构建
# 1.1 定义输入的数据节点
feature = 1
input_x = tf.placeholder(dtype=tf.float32, shape=[None,feature], name='X')
input_y = tf.placeholder(dtype=tf.float32, shape=[None,feature], name='Y')
# 1.2 定义模型参数变量
print(tf.shape(input_x),'xxxxx')
# 结果 Tensor("Shape:0", shape=(2,), dtype=int32) xxxxx
print(type(np.shape(input_x)[1]))
# 结果 <class 'tensorflow.python.framework.tensor_shape.Dimension'> (?, 1)
feature = int(np.shape(input_x)[1])
# 这里需要将上述类型转化为 int类型
w_initial_value = tf.random_normal(shape=[feature,1], mean=0.0, stddev=0.1, dtype=tf.float32)
w = tf.Variable(initial_value=w_initial_value, dtype=tf.float32, name='w')
b_initial_value = tf.random_normal(shape=[feature,1], mean=0.0, stddev=0.1, dtype=tf.float32)
b = tf.Variable(initial_value=b_initial_value, dtype=tf.float32, name='b')
# 计算预测结果
predict = tf.add(tf.matmul(input_x, w), b, name='predict')
# 构建损失函数
loss = tf.reduce_mean(tf.square(input_y - predict))
# 构建优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
# 对损失函数进行优化操作
train_op = optimizer.minimize(loss = loss) # 返回值为None
with tf.Session() as sess:
# 初始化变量值
sess.run(tf.global_variables_initializer())
#2 执行图的执行
#a 数据加载
np.random.seed(28)
N = 50
X = np.array(np.linspace(0,10,N) + np.random.normal(0,0.1,N)).reshape(-1,1)
Y = 20 * X + 7 + np.random.normal(0,1,N).reshape(-1,1)
print(Y.shape)
#b 数据清洗
#c 特征提取与数据分割
# 特征工程
#f 模型构建与模型训练
for step in range(800):
train_op1,loss1 = sess.run(fetches=[train_op,loss],feed_dict={input_x:X,input_y:Y})
'''
解释:每获取一次 train_op 相当于执行一次优化器优化操作,返回值为None,因此我没一般不接受该值。
注意: 运行的结果的变量尽量不要与构建执行图的变量相同,以防止会话再循环执行时出现错误。'''
print('原损失函数值为{},第{}步迭代后优化器的返回值为{}'.format(loss1, step + 1, train_op1))
# g 模型评估
# 用训练后的模型参数 w b 进行预测
print('真实的数据值:\n{}'.format(Y))
Y_predict, w, b = sess.run(fetches=[predict, w, b], feed_dict={input_x: X})
print('预测值为{}'.format(Y_predict))
# 可视化
plt.figure()
plt.plot(X, Y, 'ro', label='True')
plt.plot(X, Y_predict, label='Predict')
plt.legend()
plt.show()
# 模型持久化
================================== 加入可视化 与 断点模型续传持久化 ==============================
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
if __name__ == '__main__':
with tf.Graph().as_default():
# 0. 创建全局共享变量
global_step = tf.train.get_or_create_global_step() ----- 第一步:创建全局共享变量
# 1. 创建执行图
with tf.name_scope("network"):
# a. 定义占位符, shape中的None表示不做限制的意思
input_x = tf.placeholder(dtype=tf.float32, shape=[None, 1], name='x')
input_y = tf.placeholder(dtype=tf.float32, shape=[None, 1], name='y')
# b. 定义模型参数变量
w = tf.Variable(initial_value=[[-5]], dtype=tf.float32, name='w')
b = tf.Variable(initial_value=[3], dtype=tf.float32, name='b')
# c. 计算预测值y
y_ = tf.add(tf.matmul(input_x, w), b, name='Add')
print(y_.name)
with tf.name_scope("loss"):
# d. 基于预测值和实际值构建损失函数
loss = tf.reduce_mean(tf.square(input_y - y_), name='loss')
# 添加一个损失函数的可视化输出的操作对象(Op)
tf.summary.scalar('loss mean', loss)
with tf.name_scope("train"):
# e. 让损失函数最小的时候模型就是最优模型
# 定义一个优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)
# 对损失函数进行优化操作
train_op = optimizer.minimize(loss=loss, global_step=global_step) ----- 第二步:将共享
全局变量赋给参数 global_step =
# f. 合并所有可视化输出操作
summary = tf.summary.merge_all()
# 2. 执行图运行
with tf.Session() as sess:
# 获取持久化的对象、构建一个持久化对象
----------------------------- 第三步:以下可以当做固定用法,断点持久化模型参数 ----------------------
ckpt = tf.train.get_checkpoint_state("./models/14/model") ------ 如果模型没有持久化保存参数
,返回值为None
saver = tf.train.Saver()
if ckpt and ckpt.model_checkpoint_path:
print("进行变量的加载恢复操作,非第一次模型训练...")
# 加载模型参数
saver.restore(sess=sess, save_path=ckpt.model_checkpoint_path)
# 加载管理历史记录信息
saver.recover_last_checkpoints(checkpoint_paths=ckpt.all_model_checkpoint_paths)
else:
print("进行变量初始化操作,第一次模型训练....")
# 变量初始化 给定变量值
sess.run(tf.global_variables_initializer())
------------------------------------------------------------------------------------------------
# 构建一个日志输出对象
writer = tf.summary.FileWriter(logdir='./models/14/graph', graph=sess.graph)
# 1. 随机数据产生、加载
np.random.seed(28)
N = 100
x = np.linspace(0, 6, N) + np.random.normal(0, 2.0, N)
y = 14 * x + 7 - np.random.normal(0, 5.0, N)
x.shape = -1, 1
y.shape = -1, 1
print((np.shape(x), np.shape(y)))
# 2. 获取数据进行模型训练
_global_step = sess.run(global_step) ------- 第四步:获取全局共享变量
for step in range(_global_step, 100 + _global_step): ------ 第五步:将全局共享变量
代入 for 迭代模型训练
summary_, _, loss_ = sess.run(fetches=[summary, train_op, loss], feed_dict={
input_x: x, # 给定占位符的值
input_y: y # 给定占位符的值
})
print("第{}次训练后模型的损失函数值为:{}".format(step, loss_))
writer.add_summary(summary=summary_, global_step=step)
# 做一个模型持久化的操作
saver.save(sess=sess,
save_path='./models/14/model/model.ckpt',
global_step=step)
# if step >= 2:
# break
# 3. 使用训练好的模型对数据做一个预测
predict = sess.run(y_, feed_dict={input_x: x})
# 可视化画图
plt.plot(x, y, 'ro')
plt.plot(x, predict, 'g-')
plt.show()
writer.close()
-
TensorFlow实现逻辑回归(分类问题) ----- 用内置交叉熵损失函数
import tensorflow as tf
with tf.Graph().as_default():
# 1. 创建执行图
# a. 定义占位符, shape中的None表示不做限制的意思
input_x = tf.placeholder(dtype=tf.float32, shape=[None, 2], name='x')
input_y = tf.placeholder(dtype=tf.float32, shape=[None, 2], name='y')
# b. 定义模型参数变量
w = tf.Variable(initial_value=tf.random_normal(shape=[2, 2], mean=0.0, stddev=0.1),
dtype=tf.float32)
b = tf.Variable(initial_value=tf.zeros(shape=[2]), dtype=tf.float32)
# c. 计算预测值y
z = tf.add(tf.matmul(input_x, w), b)
p = tf.nn.softmax(z)
y_ = tf.argmax(p, axis=1)
# d. 基于预测值和实际值构建损失函数
# loss = -tf.reduce_mean(tf.log(tf.reduce_sum(input_y * p, axis=1)), name='loss')
# labels: 是实际的标签对象,是一个二维的数组/Tensor,哑编码之后的
# logits: 是预测的相当于决策函数值形成的二维的数组/Tensor
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=input_y,
logits=z, name='loss'))
# e. 让损失函数最小的时候模型就是最优模型
# 定义一个优化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
# 对损失函数进行优化操作
train_op = optimizer.minimize(loss=loss)
# 2. 执行图运行
with tf.Session() as sess:
# 变量初始化 给定变量值
sess.run(tf.global_variables_initializer())
# 1. 加载数据
X = np.random.rand(7, 2)
Y = np.dot(X, [[5], [-3]])
Y[Y > 0] = 1
Y[Y <= 0] = 0
Y2 = []
for idx in range(len(Y)):
if Y[idx] == 0:
Y2.append([1, 0])
else:
Y2.append([0, 1])
# 2. 获取数据进行模型训练
for step in range(1000):
_, loss_ = sess.run(fetches=[train_op, loss], feed_dict={
input_x: X, # 给定占位符的值
input_y: Y2 # 给定占位符的值
})
print("第{}次训练后模型的损失函数值为:{}".format(step, loss_))
# 3. 使用训练好的模型对数据做一个预测
train_predict = sess.run(y_, feed_dict={input_x: X}).reshape((-1, 1))
# 可视化画图
y_train = Y
print("训练数据上的准确率:{}".format(accuracy_score(y_train, train_predict)))
print("训练数据上的混淆矩阵:\n{}".format(confusion_matrix(y_train, train_predict)))
2、其他tensorflow小案例
https://blog.csdn.net/qq_16555103/article/details/97519779 -------------- TensorFlow的小案例
三、TensorFlow常见API
(0)github地址:• 参考文档:
https://tensorflow.google.cn/versions/
https://github.com/tensorflow/docs/tree/r1.6/site/en/api_docs ----- r1.6版本
(1) 数据类型转换相关API
(2) Tensor Shape获取以及设置相关API
(3)tensor合并、分割相关API
(4)错误相关API
(5)常量类型的Tensor对象相关API
(6) 序列和随机Tensor对象相关API
(7)Session相关API
(8) 逻辑运算符相关API
(9)比较运算符相关API
(10)调试相关API
(11) 图像处理-编码解码相关API
(12)图像处理-调整大小相关API
(13)图像处理-图像裁剪相关API
(14) 图像处理-翻转换位相关API
(15)图像处理-图像调整相关API
(16)。。
(17)基础数学运算相关
(18)矩阵乘法相关API
(19)神经网络相关API
(20)Variables相关API
(21)模型持久化训练 train
(22)优化相关API