avatar

目录
tensflow

TensorFlow变量作用域 TensorFlow™ 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。 其命名来源于本身的原理,Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算.Tensorflow运行过程就是张量从图的一端流动到另一端的计算过程。张量从图中流过的直观图像是其取名为“TensorFlow”的原因。

TensorFlow的关键点是:“Data Flow Graphs”,表示TensorFlow是一种基于图的计算框架,其中节点(Nodes)在图中表示数学操作,线(Edges)则表示在节点间相互联系的多维数据数组,即张量(Tensor),这种基于流的架构让TensorFlow具有非常高的灵活性,该灵活性也让TensorFlow框架可以在多个平台上进行计算,例如:台式计算机、服务器、移动设备等。
备注:TensorFlow的开发过程中,重点在于构建执行流图。

What is Data Flow Graphs?

数据流图使用节点(Node)和线(Edges)的有向图描述数学计算;节点一般用来表示施加的数学操作,也可以表示数据输入(feed in)的起点和输出(push out)的终点,或者是读取/写入持久变量(persistent variable)的终点。线表示的是节点之间的输入/输出关系,这些线可以输运“size可动态调整”的多维数组,即张量(Tensor)。

一旦输入端的所有张量准备好,节点将被分配到各种计算设备完成异步并行地执行运算。1_ys

TensorFlow基本概念:

图(Graph):图描述了计算的过程,TensorFlow使用图来表示计算任务。

张量(Tensor):TensorFlow使用tensor表示数据。每个Tensor是一个类型化的多维数组。

操作(op):图中的节点被称为op(opearation的缩写),一个op获得/输入0个或多个Tensor,执行计算,产生0个或多个Tensor。

变量(Variable):运行过程中可以被改变,用于维护状态。

会话(Session):图必须在称之为“会话”的上下文中执行。会话将图的op分发到诸如CPU或GPU之类的设备上执行。

TensorFlow的边即有两种连接关系:
数据依赖
控制依赖
实线边表示数据依赖,代表数据,即张量。任意维度的数据统称为张量。在机器学习算法中,张量在数据流图中从前往后流动一遍就完成一次前向传播,而残差从后向前流动一遍就完成一次反向传播。
虚线边表示控制依赖,可以用于控制操作的运行,这被用来确保happens-before关系,这类边上没有数据流过,但源节点必须在目的节点开始执行前完成。

数据属性:

数据类型 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位浮点数组成的复数:实数和虚数

节点:

节点又称为算子,它代表一个操作,一般用来表示施加的数字运算,也可以表示数据输入的起点以及输出的重点,或者是读取/写出持久化变量的终点。

类别 示例
数学运算操作 Add、Subtract、Multiply、Div、Exp、Log、Greater、Less、Equal……
数组运算操作 Concat, Slice, Split, Constant, Rank, Shape, Shuffle……
矩阵运算操作 MatMul, MatrixInverse, MatrixDeterminant……
有状态的操作 Variable、Assign、AssignAdd……
神经网络构建操作 SoftMax, Sigmoid, ReLU, Convolution2D, MaxPool……
检查点操作 Save, Restore……
队列和同步操作 Enqueue, Dequeue, MutexAcquire, MutexRelease……
控制张量流动的操作 Merge, Switch, Enter, Leave, NextIteration……

使用TensorFlow必须理解下列概念:
使用图(graph)来表示计算任务;
在会话(session)的上下文中执行图;
使用tensor表示数据;
通过变量(Variable)来维护状态 ;
使用feed和fetch可以为任意的操作(Operation/op)赋值或者从其中获取数据。

TensorFlow程序结构:

TensorFlow的程序一般分为两个阶段:构建阶段和执行阶段;
构建阶段:op的执行步骤被描述称为一个图,然后使用TensorFlow提供的API构建这个图。
执行阶段:将构建好的执行图(Operation Graph)在给定的会话中执行,并得到执行结果。

TensorFlow图:

不使用默认图(Graph),使用多个图来进行编程;但是注意:操作必须属于同一个图,不同图中的节点不能相连。

TensorFlow会话:

当执行图构建完成后,才能给启动图,进入到执行阶段;启动图的第一步就是创建一个Session对象,如果无任何参数的情况下,会话构造器将启动默认图。

tf.Session在构建会话的时候,如果不给定任何参数,那么构建出来Session对应的内部的Graph其实就是默认Graph,不过我们可以通过参数给定具体对应的是那一个Graph以及当前Session对应的配合参数。Session的构造主 要有三个参数,作用如下:
target:给定连接的url,只有当分布式运行的时候需要给定(后面分布式运行讲);
graph:给定当前Session对应的图,默认为TensorFlow中的默认图;
config:给定当前Session的相关参数,参数详见:https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/protobuf/config.proto中的[ConfigProto]

Code
tf.Session(target='', graph=None, config=None)
target: 给定连接的url,只有当分布式运行的时候需要给定。
graph: 调用哪张图,如果不给定,则调用默认图。
config: 会话的配置文件。
"""

通过Session的config参数可以对TensorFlow的应用的执行进行一些优化调整,主要涉及到的参数如下:

属性 作用
gpu_options GPU相关参数,主要参数:per_process_gpu_memory_fraction和allow_growth
allow_soft_placement 是否允许动态使用CPU和GPU,默认为False;当我们的安装方式为GPU的时候,建议该参数设置为True,因为TensorFlow中的部分op只能在CPU上运行。
log_device_placement 是否打印日志,默认为False,不打印日志
graph_options Graph优化相关参数,一般不需要给定,默认即可,主要参数:optimizer_options(do_common_subexpression_elimination、do_constant_folding和opt_level)
Code
"""
gpu_options 参数
per_process_gpu_memory_fraction 浮点数[0, 1.0], 表示限制该gpu设备显存使用的百分比
allow_growth bool值,不预先分配使用整个gpu显存计算,而是从小到大按需增长。
"""

在TensorFlow中,除了可以使用Session表示这个会话外,还可以通过InteractiveSession来表示会话,InteractiveSession的意思是:交互式会话,使用交互式会话可以降低代码的复杂度,使用Tensor.eval()或者Operation.run()来代替Session.run()方法,这样可以避免一个变量来维持会话;备注:Session也可以使用Tensor.eval()和Operation.run()获取数据/执行操作(只要明确当前会话)。

Tensor张量:

TensorFlow使用Tensor数据结构来代表所有数据,计算图中,操作间传递的数据都是Tensor。Tensor可以看作是一个n维的数组或者列表,一个Tensor主要由一个静态数据类型和动态类型的维数(Rank、Shape)组成。Tensor可以在图中的节点之间流通。

2

TensorFlow变量:

变量(Variables)是维护图执行过程中的状态信息。在训练模型过程中,可以通过变量来存储和更新参数。变量包含张量(Tensor)存放于内存的缓存区。建模的时候变量必须被明确的初始化,模型训练后变量必须被存储到磁盘。这些变量的值可以在之后的模型训练和分析中被加载。

在构建变量的时候,必须将一个张量或者可以转化为张量的Python对象作为初始值传入构造函数Variable中。

占位符:

可以使用 shape=[None, 3], None使用类似于numpy。

input_x = tf.placeholder(dtype=tf.float32, shape=[None, 3], name=‘input_x’)

y_hat_, y_hat1_ = sess.run(
fetches=[y_hat, y_hat1], feed_dict={input_x: data2, input_c: 10.0})

以字典方式通过feed_dict传入

Code
import tensorflow as tf
import numpy as np

"""
使用tensorflow 实现简单的 线性回归 y = np.dot(x, W) + b
"""

def f1():
"""
先使用常量进行构建,展示大致的业务逻辑
:return:
"""
# 一、建图
with tf.Graph().as_default():
# 1、创建模型输入
input_x = tf.constant(
value=[[1,2,3],
[2,3,4],
[12,34,23],
[2,3,9]], dtype=tf.float32, shape=[4, 3], name='input_x'
)
# 2、创建变量
weights = tf.constant(
value=[[-5],
[3],
[2]], dtype=tf.float32, shape=[3, 1], name='weights'
)
bias = tf.constant(
value=[2], dtype=tf.float32, shape=[1], name='bias'
)

# 3、构建正向传播过程
y_hat = tf.matmul(input_x, weights) + bias
print(y_hat)

# 二、构建会话
with tf.Session() as sess:
# 执行模型图
y_hat_ = sess.run(y_hat)
print(y_hat_)


def f2():
"""
变量使用 tf.Variable()来构建
:return:
"""
# 一、建图
with tf.Graph().as_default():
# 1、创建模型输入
input_x = tf.constant(
value=[[1,2,3],
[2,3,4],
[12,34,23],
[2,3,9]], dtype=tf.float32, shape=[4, 3], name='input_x'
)
"""
tf.Variable(self,
initial_value=None, # 给定初始化的值,可以是python的基本数据类型,也可以是tf的tensor对象
trainable=True, # bool 该变量是否参与模型训练。也就是该变量是否会执行梯度下降
collections=None,
validate_shape=True,
caching_device=None,
name=None, # tensorflow底层的名字。
variable_def=None,
dtype=None, # 数据类型
expected_shape=None,
import_scope=None,
constraint=None):
"""
# 2、创建变量
weights = tf.Variable(
initial_value=[[-5],
[3],
[2]], dtype=tf.float32, name='weights'
)
print(weights)
bias_value = tf.constant(
value=[2], dtype=tf.float32, shape=[1], name='bias'
)
bias = tf.Variable(initial_value=bias_value, dtype=tf.float32, name='bias')

# 3、构建正向传播过程
y_hat = tf.matmul(input_x, weights) + bias
print(y_hat)

# 二、构建会话
with tf.Session() as sess:
# fixme 执行变量初始化赋值
sess.run(tf.global_variables_initializer())
# 执行模型图
y_hat_ = sess.run(y_hat)
print(y_hat_)


def f3():
"""
占位符的使用
:return:
"""
# 一、建图
with tf.Graph().as_default():
# 1、创建模型输入(占位符)
# todo 可以使用 shape=[None, 3], None使用类似于numpy。
input_x = tf.placeholder(dtype=tf.float32, shape=[None, 3], name='input_x')
input_c = tf.placeholder_with_default(
input=1.0, shape=[], name='input_c'
)
# 2、创建变量
weights = tf.Variable(
initial_value=[[-5],
[3],
[2]], dtype=tf.float32, name='weights'
)
print(weights)
bias_value = tf.constant(
value=[2], dtype=tf.float32, shape=[1], name='bias'
)
bias = tf.Variable(initial_value=bias_value, dtype=tf.float32, name='bias')

# 3、构建正向传播过程
y_hat = tf.matmul(input_x, weights) + bias
y_hat1 = y_hat + input_c
print(y_hat)

# 二、构建会话
with tf.Session() as sess:
# fixme 执行变量初始化赋值
sess.run(tf.global_variables_initializer())
# 加载训练数据
data1 = [[1,2,3],
[2,3,4],
[12,34,23],
[2,3,9]]
# 执行模型图
y_hat_, y_hat1_ = sess.run(
fetches=[y_hat, y_hat1], feed_dict={input_x: data1})
print(y_hat_, y_hat1_)

data2 = [[1, 2, 3],
[2, 3, 4],
[2, 3, 9]]
y_hat_, y_hat1_ = sess.run(
fetches=[y_hat, y_hat1], feed_dict={input_x: data2, input_c: 10.0})
print(y_hat_, y_hat1_)


def f4():
"""
tensorboard的调用
:return:
"""
# 一、建图
with tf.Graph().as_default():
# 1、创建模型输入(占位符)
# todo 可以使用 shape=[None, 3], None使用类似于numpy。
input_x = tf.placeholder(dtype=tf.float32, shape=[None, 3], name='input_x')
input_c = tf.placeholder_with_default(
input=1.0, shape=[], name='input_c'
)
# 2、创建变量
weights = tf.Variable(
initial_value=[[-5],
[3],
[2]], dtype=tf.float32, name='weights'
)
print(weights)
bias_value = tf.constant(
value=[2], dtype=tf.float32, shape=[1], name='bias'
)
bias = tf.Variable(initial_value=bias_value, dtype=tf.float32, name='bias')

# 3、构建正向传播过程
y_hat = tf.matmul(input_x, weights) + bias
y_hat1 = y_hat + input_c
print(y_hat)

# 二、构建会话
with tf.Session() as sess:
# fixme 执行变量初始化赋值
sess.run(tf.global_variables_initializer())
# fixme 加入一段可视化代码
"""
tf.summary.FileWriter(self,
logdir, # 记录日志或者事件的路径。
graph=None, # 可视化的图对象
max_queue=10,
flush_secs=120,
graph_def=None,
filename_suffix=None,
session=None):
"""
writer = tf.summary.FileWriter(
logdir='./model/ai13', graph=sess.graph
)
# 加载训练数据
data1 = [[1,2,3],
[2,3,4],
[12,34,23],
[2,3,9]]
# 执行模型图
y_hat_, y_hat1_ = sess.run(
fetches=[y_hat, y_hat1], feed_dict={input_x: data1})
print(y_hat_, y_hat1_)

data2 = [[1, 2, 3],
[2, 3, 4],
[2, 3, 9]]
y_hat_, y_hat1_ = sess.run(
fetches=[y_hat, y_hat1], feed_dict={input_x: data2, input_c: 10.0})
print(y_hat_, y_hat1_)

if __name__ == '__main__':
f4()

tensorboard 可视化:

打开日志文件 tensorboard —logdir 绝对路径(到文件夹 )

“”"
tf.summary.FileWriter(self,
logdir, # 记录日志或者事件的路径。
graph=None, # 可视化的图对象
max_queue=10,
flush_secs=120,
graph_def=None,
filename_suffix=None,
session=None):
“”"
writer = tf.summary.FileWriter(
logdir=’./model/ai13’, graph=sess.graph
)

TensorFlow控制依赖:

with g.control_dependencies[a,b,c]:

“d” and “e” will only run after ‘’’a‘’ ‘’b’’ ‘’c’‘ have executed

我们可以通过Variable和assign完成变量的定义和更新,但是如果在更新变量之前需要更新其它变量,那么会导致一个比较严重的问题:也就是需要多次调用sess.run方法来进行变量的更新。通过这种方式,代码复杂程度上升,同时也没有执行效率。
解决该问题的方案就是:控制依赖。通过TensorFlow中提供的一组函数来处理不完全依赖的情况下的操作排序问题(即给定哪个操作先执行的问题), 通过tf.control_dependencies API完成。

Code
def change_var_shape():
"""
实现动态的更新变量的维度数目。需要设置tf.assign中的validate_shape=False
:return:
"""
with tf.Graph().as_default():
# 1、定义一个变量
x = tf.Variable(
initial_value=[[0, 2, 3, 4, 0]],
dtype=tf.float32,
validate_shape=True # 设置为False时候,表示不进行初始值shape的验证
)

# 2、做一个矩阵合并的操作---沿着行进行合并。
temp = [0.0, 2.0, 3.0, 4.0, 0.0]
concat = tf.concat(values=[x, tf.expand_dims(temp, axis=0)], axis=0) # 必须沿着已经存在的轴进行拼接。tf.expand_dims扩展轴
# tf.squeeze() 缩减tensor中维度为1的轴(需要指定)。
# 3、做一个赋值更新的操作
assign_opt = tf.assign(ref=x, value=concat, validate_shape=False)

# 二、执行会话
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

for _ in range(5):
_, x_ = sess.run([assign_opt, x])
print(x_)

3

Code
def factorial():
"""
实现一个求解n阶乘的值,再乘以3的这样一个需求。
tf.control_dependencies()
:return:
"""
with tf.Graph().as_default():
# 1、定义一个占位符,表示一个数字
input_x = tf.placeholder(tf.float32, shape=None, name='inputx')

# 2、定一个变量,作为储存阶乘的值
sum_x = tf.Variable(initial_value=1.0, dtype=tf.float32, name='sum_x')

# 3、执行乘法的操作
temp = sum_x * input_x
# 将temp 赋值给 sum_x
assign_opt = tf.assign(ref=sum_x, value=temp)

# 4、将阶乘以后的sum_x 乘以3,得到最终的预测值y_hat
with tf.control_dependencies(control_inputs=[assign_opt]):
# fixme 在执行y_hat之前,一定先执行assign_opt赋值的操作
y_hat = sum_x * 3
"""
该段代码的含义是:确保执行顺序为 assign_opt --> assign_opt1 --> y_hat
with tf.control_dependencies(control_inputs=[assign_opt]):
with tf.control_dependencies(control_inputs=[assign_opt1]):
# fixme 在执行y_hat之前,一定先执行assign_opt赋值的操作
y_hat = sum_x * 3
"""

# 二、创建会话
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

# 构建迭代累加的值
data = [1, 3, 5, 7, 9]
for i in data:
y_hat_ = sess.run(y_hat, feed_dict={input_x: i})
print(y_hat_)

TensorFlow设备:

设备是指一块可以用来运算并且拥有自己的地址空间的硬件,如CPU和GPU。Tensorflow为了在执行操作的时候,充分利用计算资源,可以明确指定操作在哪个设备上执行。

一般情况下,不需要显示指定使用CPU还是GPU,TensorFlow会自动检测。如果检测到GPU,TensorFlow会尽可能地利用第一个GPU来执行操作。注意:如果机器上有超过一个可用的GPU,那么除了第一个外其它GPU默认是不参与计算的。所以,在实际TensorFlow编程中,经常需要明确给定使用的CPU和GPU。

“/cpu:0”:表示使用机器CPU运算
“/gpu:0”:表示使用第一个GPU运算,如果有的话
“/gpu:1”:表示使用第二个GPU运算,以此类推

Code
import os
import tensorflow as tf


def factorial():
with tf.Graph().as_default():
"""
注意事项:
如果不使用tf.device指定具体运行的设备的话,tensorflow会根据你安装的版本选择默认的设备运行。
1、如果安装的是cpu版本的tf,那么运行在cpu上面。
2、如果安装的是gpu版本的tf,那么运算操作一定运行在第一个gpu,但是会在所有gpu上分配内存。
如何通过tf.device指定了具体的运行设备,那么该运算一定会放到你指定的设备上运行,如果没有,就会报错。
建议将:allow_soft_placement=True
"""
with tf.device('/CPU:0'):
# 1、定义一个占位符,表示一个数字
input_x = tf.placeholder(tf.float32, shape=None, name='inputx')

with tf.device('/CPU:1'):
# 2、定一个变量,作为储存阶乘的值
sum_x = tf.Variable(initial_value=1.0, dtype=tf.float32, name='sum_x')

with tf.device('/GPU:0'):
# 3、执行乘法的操作
temp = sum_x * input_x
# 将temp 赋值给 sum_x
assign_opt = tf.assign(ref=sum_x, value=temp)

# 4、将阶乘以后的sum_x 乘以3,得到最终的预测值y_hat
with tf.control_dependencies(control_inputs=[assign_opt]):
# fixme 在执行y_hat之前,一定先执行assign_opt赋值的操作
y_hat = sum_x * 3

# 二、创建会话
config = tf.ConfigProto(
log_device_placement=True, allow_soft_placement=True
)
with tf.Session(config=config) as sess:
sess.run(tf.global_variables_initializer())

# 构建迭代累加的值
data = [1, 3, 5, 7, 9]
for i in data:
y_hat_ = sess.run(y_hat, feed_dict={input_x: i})
print(y_hat_)

"""
假设现在有两个GPU,我们代码运行的时候希望仅在第二个GPU上运行,并且仅在第二个GPU上分配内存
--> 通过给定环境变量解决
"""
# os.environ['CUDA_DEVICE_ORDER'] = 'PCI_BUS_ID'
# os.environ['CUDA_VISIBLE_DEVICES'] = "0,1" # 允许当前代码使用第一块、第二块GPU
# os.environ['CUDA_VISIBLE_DEVICES'] = "1" # 允许当前代码使用第二块GPU
# os.environ['CUDA_VISIBLE_DEVICES'] = "-1" # 允许当前代码不允许使用GPU

if __name__ == '__main__':
factorial()

TensorFlow变量作用域:

通过tf.Variable我们可以创建变量,但是当模型复杂的时候,需要构建大量的变量集,这样会导致我们对于变量管理的复杂性,而且没法共享变量(存在多个相似的变量)。针对这个问题,可以通过TensorFlow提供的变量作用域机制来解决,在构建一个图的时候,就可以非常容易的使用共享命名过的变量。

Tensorflow中有两个作用域,一个是name_scope,另一个是variable_scope。
变量作用域机制在TensorFlow中主要通过两部分组成:
tf.get_variable:通过所给定的名字创建或者返回一个对应的变量
tf.variable_scope:为通过创建的变量或者操作Operation指定命名空间

Code
import tensorflow as tf
import numpy as np

# sum_x = 0
# for i in range(1, 5):
# sum_x += i
# print(sum_x)
with g.c
def sum1():
"""
使用tf.assign实现一个累加器。
:return:
"""
with tf.Graph().as_default():
# 1、定义一个占位符,表示被累加的值
input_x = tf.placeholder(tf.float32, shape=None, name='inputx')

# 2、定一个变量,作为储存累加的值
sum_x = tf.Variable(initial_value=0.0, dtype=tf.float32, name='sum_x')

# 3、执行累加的操作
sum_x = sum_x + input_x

# 二、创建会话
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

# 构建迭代累加的值
data = [1, 3, 5, 7, 9]
for i in data:
sum_x_ = sess.run(sum_x, feed_dict={input_x: i})
print(sum_x_)


def sum2():
"""
使用tf.assign_add() 或者 tf.assign() 实现一个累加器。
:return:
"""
with tf.Graph().as_default():
# 1、定义一个占位符,表示被累加的值
input_x = tf.placeholder(tf.float32, shape=None, name='inputx')

# 2、定一个变量,作为储存累加的值
sum_x = tf.Variable(initial_value=0.0, dtype=tf.float32, name='sum_x')

# 3、执行累加的操作
# assign_add = tf.assign_add(ref=sum_x, value=input_x)
"""
tf.assign(ref, value)
ref: 你要更新的值。
value: 累加的值。
"""
temp = sum_x + input_x
assign_opt = tf.assign(ref=sum_x, value=temp)

# 二、创建会话
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

# 构建迭代累加的值
data = [1, 3, 5, 7, 9]
for i in data:
sum_x_, _ = sess.run([sum_x, assign_opt], feed_dict={input_x: i})
print(sum_x_)

def change_var_shape():
"""
实现动态的更新变量的维度数目。需要设置tf.assign中的validate_shape=False
:return:
"""
with tf.Graph().as_default():
# 1、定义一个变量
x = tf.Variable(
initial_value=[[0, 2, 3, 4, 0]],
dtype=tf.float32,
validate_shape=True # 设置为False时候,表示不进行初始值shape的验证
)

# 2、做一个矩阵合并的操作---沿着行进行合并。
temp = [0.0, 2.0, 3.0, 4.0, 0.0]
concat = tf.concat(values=[x, tf.expand_dims(temp, axis=0)], axis=0) # 必须沿着已经存在的轴进行拼接。
# tf.squeeze() 缩减tensor中维度为1的轴(需要指定)。
# 3、做一个赋值更新的操作
assign_opt = tf.assign(ref=x, value=concat, validate_shape=False)

# 二、执行会话
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

for _ in range(5):
_, x_ = sess.run([assign_opt, x])
print(x_)
with control

def factorial():
"""
实现一个求解n阶乘的值,再乘以3的这样一个需求。
tf.control_dependencies()
:return:
"""
with tf.Graph().as_default():
# 1、定义一个占位符,表示一个数字
input_x = tf.placeholder(tf.float32, shape=None, name='inputx')

# 2、定一个变量,作为储存阶乘的值
sum_x = tf.Variable(initial_value=1.0, dtype=tf.float32, name='sum_x')

# 3、执行乘法的操作
temp = sum_x * input_x
# 将temp 赋值给 sum_x
assign_opt = tf.assign(ref=sum_x, value=temp)

# 4、将阶乘以后的sum_x 乘以3,得到最终的预测值y_hat
with tf.control_dependencies(control_inputs=[assign_opt]):
# fixme 在执行y_hat之前,一定先执行assign_opt赋值的操作
y_hat = sum_x * 3
"""
该段代码的含义是:确保执行顺序为 assign_opt --> assign_opt1 --> y_hat
with tf.control_dependencies(control_inputs=[assign_opt]):
with tf.control_dependencies(control_inputs=[assign_opt1]):
# fixme 在执行y_hat之前,一定先执行assign_opt赋值的操作
y_hat = sum_x * 3
"""

# 二、创建会话
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())

# 构建迭代累加的值
data = [1, 3, 5, 7, 9]
for i in data:
y_hat_ = sess.run(y_hat, feed_dict={input_x: i})
print(y_hat_)

if __name__ == '__main__':
# sum2()
# change_var_shape()
factorial()

TensorFlow变量作用域:

通过tf.Variable我们可以创建变量,但是当模型复杂的时候,需要构建大量的变量集,这样会导致我们对于变量管理的复杂性,而且没法共享变量(存在多个相似的变量)。针对这个问题,可以通过TensorFlow提供的变量作用域机制来解决,在构建一个图的时候,就可以非常容易的使用共享命名过的变量。
Tensorflow中有两个作用域,一个是name_scope,另一个是variable_scope。
变量作用域机制在TensorFlow中主要通过两部分组成:
tf.get_variable:通过所给定的名字创建或者返回一个对应的变量
tf.variable_scope:为通过创建的变量或者操作Operation指定命名空间

tf.get_variable方法在调用的时候,主要需要给定参数名称name,形状shape,数据类型dtype以及初始化方式initializer四个参数。该API底层执行的时候,根据variable score的属性reuse的值决定采用何种方式来获取变量。当reuse值为False的时候(不允许设置),作用域就是创建新变量设置的,此时要求对应的变量不存在,否则报错;当reuse值为True的时候,作用域就是为重用变量所设置的,此时要求对应的变量必须存在,否则报错。当reuse的值为tf.AUTO_REUSE的时候,表示如果变量存在就重用变量,如果变量不存在,就创建新变量返回。(备注:reuse一般设置在variable score对象上)

tf.get_variable常用的initializer初始化器:

初始化器 描述
tf.constant_initializer(value) 初始化为给定的常数值value
tf.random_uniform_initializer(a, b) 初始化为从a到b的均匀分布的随机值
tf.random_normal_initializer(mean, stddev) 初始化为均值为mean、方差为stddev的服从高斯分布的随机值
tf.orthogonal_initializer(gini=1.0) 初始化一个正交矩阵,gini参数作用是最终返回的矩阵是随机矩阵乘以gini的结果
tf.identity_initializer(gini=1.0) 初始化一个单位矩阵,gini参数作用是最终返回的矩阵是随机矩阵乘以gini的结果

tf.variable_score方法的作用就是定义一个作用域,定义在variable_score作用域中的变量和操作,会将variable score的名称作为前缀添加到变量/操作名称前,支持嵌套的作用域,添加前缀规则和文件目录路径的规则类似。
tf.variable_score参数如果给定的是一个已经存在的作用域对象的时候,那么构建变量的时候表示直接跳过当前作用域前缀,直接成为一个完全不同与现在的作用域(直接创建给定作用域下的变量)。但是构建操作的时候,还是和嵌套的方式一样,直接添加子作用域。
tf.variable_score参数中,可以给定当前作用域中默认的初始化器initializer,并且子作用域会直接继承父作用域的相关参数(是否重用、默认初始化器等)

TensorFlow中的name_score和variable_score是两个不同的东西,name_score的主要作用是为op_name前加前缀,variable_score是为get_variable创建的变量的名字加前缀。简单来讲:使用tf.Variable创建的变量受name_score和variable_score的的效果,会给变量添加前缀,但是使用tf.get_variable创建变量只受variable_score的效果。
name_score的主要作用就是:Tensorflow中常常会有数以千计的节点,在可视化的过程中很难一下子展示出来,因此用name_scope为变量划分范围,在可视化中,这表示在计算图中的一个层级。name_scope会影响op_name,不会影响用get_variable()创建的变量,而会影响通过Variable()创建的变量。
注意:variable_score内部会创建一个同名的name_score

Code
import tensorflow as tf

def f1():
"""
基于tf.Variable()创建一个变量
:return:
"""
# 创建一个新的变量,哪怕名字相同。
w = tf.Variable(
initial_value=tf.random_normal(shape=[2], mean=0.0, stddev=1.0),
dtype=tf.float32, name='w'
)
return w


def f2(initializer=tf.random_normal_initializer(mean=0.0, stddev=1.0)):
"""
基于tf.get_variable()获取或者创建变量
:return:
"""
"""
tf.get_variable(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内部获取相应的变量,如果name对应的变量已经存在,那么直接获取该变量,
如果不存在,直接创建一个新的变量。
注意:根据name获取变量重用,只支持tf.get_variable创建的变量。
"""
w = tf.get_variable(
name='w', shape=[2], dtype=tf.float32, initializer=initializer
)
return w


def h1():
"""
学习tf.get_variable()变量重用用法。
:return:
"""
# 1、用tf.Variable()创建2个变量
w11 = f1()
w12 = f1()

# 2、用tf.get_variable()创建变量
w21 = f2()
# fixme 需要设置一下,告诉tf名字相同可以重用。
tf.get_variable_scope().reuse_variables()
w22 = f2()

print(w11.name, w12.name, w21.name, w22.name)
print('w21 和 w22是同一个变量吗?:{}'.format(w21 == w22))

# 二、执行会话
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run([w11, w12, w21, w22]))

"""
1、学习 变量命名域 tf.varible_scope()用法
2、学习 命名域 tf.name_scope() 用法
3、学习 tf.trainable_variables() 的使用
"""

"""
tf.variable_scope(self,
name_or_scope, # string类型 该变量命名域名字。
default_name=None, # 默认名字。如果参数name_or_scope 为空,那么使用该参数定义的名字。反之,则启用name_or_scope定义的名字
values=None, # 传入的值
initializer=None, # 变量命名域的初始化器
regularizer=None, # 变量命名域的正则化项
caching_device=None,
partitioner=None,
custom_getter=None,
reuse=None, # 决定该变量命名域的变量是否重用。
dtype=None,
use_resource=None,
constraint=None,
auxiliary_name_scope=True):

tf.name_scope(
name, # 命名域的名字
default_name=None, # 命名域默认的名字
values=None): # 传入的tensor值。
"""

def h2():
with tf.name_scope('ai13'):
with tf.variable_scope('t1'):
# 再次创建2个变量
w11 = f1()
w12 = f1()

# 父域定义的参数 同样也会影响子域。
with tf.variable_scope('t10', initializer=tf.constant_initializer(28.0)):
with tf.name_scope('ai14'): # fixme tf.name_scope对tf.get_variable生成的变量无效
with tf.variable_scope('t2', reuse=tf.AUTO_REUSE):
w21 = f2(initializer=None)
w22 = f2()
# 做一个加法操作
with tf.name_scope('ai15'):
with tf.variable_scope('t5'):
rezult = tf.add(w11+w12+w21, w22, name='add_rezult')

print(w11.name, w12.name)
print('**'*50)
print(w21.name, w22.name)
print('**'*50)
print(rezult.name)

with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run([w11, w12, w21, w22, rezult]))

# 基于tensor的名字直接从图中获取对应的tensor的值。
temp = tf.get_default_graph().get_tensor_by_name('t10/t2/w:0')
print(sess.run(temp))


def h3():
"""
学习tf.trainable_variables()使用
:return:
"""
with tf.name_scope('ai13'):
with tf.variable_scope('t1'):
# 再次创建2个变量
w11 = f1()
w12 = f1()

with tf.name_scope('ai14'): # fixme tf.name_scope对tf.get_variable生成的变量无效
with tf.variable_scope('t2', reuse=tf.AUTO_REUSE):
w21 = f2(initializer=None)
w22 = f2()
# 做一个加法操作
with tf.name_scope('ai15'):
with tf.variable_scope('t5'):
rezult = tf.add(w11+w12+w21, w22, name='add_rezult')

# print(w11.name, w12.name)
# print('**'*50)
# print(w21.name, w22.name)
# print('**'*50)
# print(rezult.name)
# fixme 增加一段代码,展示如何获取指定的变量。
t_vars = tf.trainable_variables()
print(t_vars)
ai13_vars = [var for var in t_vars if var.name.startswith('ai13')]
print(ai13_vars)

with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run([w11, w12, w21, w22, rezult]))


def h4():
"""
展示tf.variable_scope() 中values参数的用法
:return:
"""
default_graph = tf.Graph()
with default_graph.as_default():
w12 = f1()

graph1 = tf.Graph()
with graph1.as_default():
with tf.variable_scope('foo'):
w21 = f1()

graph2 = tf.Graph()
with graph2.as_default():
with tf.variable_scope('foo', values=[w12]):
w22 = f1()

print(w21.graph == default_graph)
print(w22.graph == default_graph)


if __name__ == '__main__':
h4()

模型持久化

Code
import tensorflow as tf
import os

"""
模型持久化:就是将训练好的模型(权重 和 网络结构)保存到磁盘中。
1、可以用于部署。(服务器上训练---拷贝到 移动端进行预测)
2、进行断点继续训练。(大型模型训练 3--4天)
3、迁移学习。
"""

# 变量的持久化
def train():
with tf.Graph().as_default():
# 构建2个变量
v1 = tf.get_variable(
name='v1', shape=[], dtype=tf.float32,
initializer=tf.constant_initializer(value=5.0)
)
v2 = tf.get_variable(
name='v2', shape=[], dtype=tf.float32,
initializer=tf.random_normal_initializer(mean=0.0, stddev=5.0)
)
rezult = v1 + v2
print(rezult)

# fixme 1、构建一个持久化的对象
saver = tf.train.Saver()

# 创建持久化文件路径
checkpoint_dir = './model/ai13'
# 创建该路径(不存在该路径的情况下,执行)
if not os.path.exists(checkpoint_dir):
# 创建路径
os.makedirs(checkpoint_dir)
print('成功创建路径:{}'.format(checkpoint_dir))

with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
print(sess.run([v1, v2, rezult]))
# [5.0, -4.2127123, 0.7872877]

# fixme 触发持久化的操作
files_name = 'model.ckpt'
save_files = os.path.join(checkpoint_dir, files_name)
saver.save(sess=sess, save_path=save_files) # 执行持久化的
print('成功将变量持久化到文件:{}'.format(save_files))


def restore_variables():
"""
从磁盘中恢复变量
:return:
"""
with tf.Graph().as_default():
# 构建2个变量
v1 = tf.get_variable(
name='v1', shape=[], dtype=tf.float32,
initializer=tf.constant_initializer(value=5.0)
)
v2 = tf.get_variable(
name='v2', shape=[], dtype=tf.float32,
initializer=tf.random_normal_initializer(mean=0.0, stddev=5.0)
)
rezult = v1 + v2
print(rezult)

# fixme 1、构建一个持久化的对象
saver = tf.train.Saver()

# 创建持久化文件路径
checkpoint_dir = './model/ai13'

with tf.Session() as sess:
# fixme 不需要变量初始化操作了

# 做一个恢复模型的操作。
files_name = 'model.ckpt'
save_files = os.path.join(checkpoint_dir, files_name)

# fixme 直接恢复变量。
saver.restore(sess=sess, save_path=save_files)
print(sess.run([v1, v2, rezult]))
# [5.0, -4.2127123, 0.7872877]


if __name__ == '__main__':
# train()
restore_variables()
文章作者: Eckle
文章链接: https://wowli-up.github.io/2020/01/17/tensflow/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Eckle的个人网站
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论