码迷,mamicode.com
首页 > 其他好文 > 详细

test

时间:2019-08-22 23:43:28      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:控制   注入   err   脚本   智能   ESS   原理   填充   出错   

1. TensorFlow简介

TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。TensorFlow 最初由Google大脑小组(隶属于Google机器智能研究机构)的研究员和工程师们开发出来,用于机器学习和深度神经网络方面的研究, 但这个系统的通用性使其也可广泛用于其他计算领域。它是谷歌基于DistBelief进行研发的第二代人工智能学习系统。2015年11月9日,Google发布人工智能系统TensorFlow并宣布开源。

其命名来源于本身的原理,Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算。Tensorflow运行过程就是张量从图的一端流动到另一端的计算过程。张量从图中流过的直观图像是其取名为“TensorFlow”的原因。TensorFlow的开发过程重点在于构建执行流图。

TensorFlow 是一个编程系统, 使用图来表示计算任务。图中的节点被称之为 op (operation 的缩写)。一个 op 获得 0 个或多个 Tensor, 执行计算, 产生 0 个或多个 Tensor。 每个 Tensor 是一个类型化的多维数组。
例如, 可以将一小组图像集表示为一个四维浮点数数组, 这四个维度分别是 [batch, height, width, channels]。

一个 TensorFlow 图描述了计算的过程。为了进行计算, 图必须在会话里被启动。 会话将图的 op 分发到诸如 CPU 或 GPU 之类的 设备 上, 同时提供执行 op 的方法. 这些方法执行后, 将产生的 tensor 返回。 在 Python 语言中, 返回的 tensor 是 numpy ndarray 对象; 在 C 和 C++ 语言中, 返回的 tensor 是 tensorflow::Tensor 实例。

TensorFlow 支持 C, C++, Python 编程语言。目前, TensorFlow 的 Python库更加易用, 它提供了大量的辅助函数来简化构建图的工作, 这些函数尚未被 C 和 C++ 库支持。三种语言的会话库 (session libraries) 是一致的。

基本概念

  • 图(Graph):图描述了计算的过程,TensorFlow使用图来表示计算任务。
  • 张量(Tensor):TensorFlow使用tensor表示数据。每个Tensor是一个类型化的多维数组。一个 tensor 包含一个静态类型 rank, 和 一个 shape。0维的张量,也叫做标量scalar或者数字,1维的张量,叫做向量vector,2维的张量,叫做矩阵matrix。

  • 操作(op):图中的节点被称为op(opearation的缩写),一个op获得/输入 0个或多个Tensor,执行计算,产生0个或多个Tensor。
  • 会话(Session):图必须在称之为“会话”的上下文中执行。会话将图的op分 发到诸如CPU或GPU之类的设备上执行。
  • 变量(Variable):运行过程中可以被改变,用于维护状态。
  • 边:TensorFlow的边即有两种连接关系:数据依赖和控制依赖
  • 供给(Feeds)和取回(Fetches):将数据传入或传出任何操作
  • 节点:又称为算子,表示一个操作或tensor。一般用来表示施加的数字运算,也可以表示数据输入的起点以及输出的终点,或者是读取/写入持久化变量的终点。

技术图片

2. TensorFLow编程模型、计算机制

TensorFlow的命名来源于本身的运行原理。Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算。TensorFlow是张量从图像的一端流动到另一端的计算过程,这也是TensorFlow的编程模型。TensorFlow的运行机制属于“定义”与“运行”相分离,即惰性求值。分成以下两个阶段:
构建阶段:op的执行步骤被描述成为一个图,然后使用TensorFlow提供的API构建这个图,用于组织计算图。
执行阶段:将构建好的执行图在给定的会话中执行,并得到执行结果。

构造阶段完成后, 才能启动图. 启动图的第一步是创建一个 Session 对象, 如果无任何创建参数, 会话构造器将启动默认图

import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!') #定义一个常量
sess = tf.Session() #建立一个session
print (sess.run(hello)) #通过session里面run函数来运行结果
sess.close() #关闭session

tf.constant定义的是一个常量,hello的内容只有在session的run内才可以返回。
可以试着在2和3行之间加入print(hello)看一下效果,这时并不能输出hello的内容。

接下来换种写法,使用with语法来开启session。with session的用法是最常见的,它沿用了Python中with的语法,即当程序结束后会自动关闭session,而不需要再去写close

import tensorflow as tf
a = tf.constant(3)  #定义常量3
b = tf.constant(4)  #定义常量4
#建立session
with tf.Session() as sess:
print ("相加: %i" % sess.run(a+b))
print( "相乘: %i" % sess.run(a*b))

2.1 注入机制feed和取回机制fetch

此外,在Session与图的交互中还加入了两种机制:
注入机制(feed):通过占位符向模式中传入数据;
取回机制(fetch):从模式中得到结果。

扩展上面代码:
使用注入机制,将具体的实参注入到相应的placeholder中。feed只在调用它的方法内有效,方法结束后feed就会消失。
实例描述:定义占位符,使用feed机制将具体数值(3和4)通过占位符传入,并进行相加和相乘运算。

a = tf.placeholder(tf.int16)
b = tf.placeholder(tf.int16)
add = tf.add(a, b)
mul = tf.multiply(a, b) #a与b相乘
with tf.Session() as sess:
   #计算具体数值
   print ("相加: %i" % sess.run(add, feed_dict={a: 3, b: 4}))
   print ("相乘: %i" % sess.run(mul, feed_dict={a: 3, b: 4}))
   print (sess.run([mul, add], feed_dict={a: 3, b: 4}))
输出:
相加: 7
相乘: 12
[12, 7]

使用取回机制,在执行图操作时,用于抓取多个tensor。intermed是input2和input3的和,最终在run中将mul和intermed一起都抓取出来了:

import tensorflow as tf
input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
intermed = tf.add(input2, input3)
mul = tf.multiply(input1, intermed)

with tf.Session() as sess:
    result = sess.run([mul, intermed])
    print(result) # [21.0, 7.0]

2.2 显示指定CPU或GPU执行

在实现上, TensorFlow 将图形定义转换成分布式执行的操作, 以充分利用可用的计算资源(如 CPU 或 GPU)。 一般不需要显式指定使用 CPU 还是 GPU, TensorFlow 能自动检测。如果检测到 GPU, TensorFlow 会尽可能地利用找到的第一个 GPU 来执行操作。
如果机器上有超过一个可用的 GPU, 除第一个外的其它 GPU 默认是不参与计算的。 为了让 TensorFlow 使用这些 GPU, 你必须将 op 明确指派给它们执行。 with...Device 语句用来指派特定的 CPU 或 GPU 执行操作:

with tf.Session() as sess:
  with tf.device("/gpu:1"):
    matrix1 = tf.constant([[3., 3.]])
    matrix2 = tf.constant([[2.],[2.]])
    product = tf.matmul(matrix1, matrix2)
    ...
设备用字符串进行标识。目前支持的设备包括:
"/cpu:0": 机器的 CPU。
"/gpu:0": 机器的第一个 GPU, 如果有的话。
"/gpu:1": 机器的第二个 GPU, 以此类推。

2.3 常用编程步骤

  • 定义Tensorflow输入节点;
  • 定义“学习参数”的变量;
  • 定义“运算”;
  • 优化函数,优化目标;
  • 初始化所有变量;
  • 迭代更新参数到最优解;jizhi
  • 测试模型;
  • 使用模型。

定义输入节点的方法
(1)通过占位符定义:一般使用这种方式。

x=tf.placeholder("float")  
y=tf.placeholder("float")

(2)通过字典类型定义:一般用于输入比较多的情况。

inputdict={  
x:tf.placeholder("float"),y:tf.placeholder("float")
}

(3)直接定义:

#构造训练数据
x_data=np.random.rand(1000).astype(np.float)           #随机生成100个类型为float32的值
y_data=x_data*2+np.random.randn(*x_data.shape)*0.5+3   #定义方程式y=x_data*W+b

定义“学习参数”的变量
分为直接定义和字典定义,在参数很多时使用字典定义。

定义“运算”
如定义模型,定义损失函数。

优化函数,优化目标
涉及L1、L2正则化,梯度下降等

初始化所有变量

#初始化全局变量
init = tf.initialize_all_variables()

通过session执行上述操作

sess = tf.Session()
sess.run(init)

迭代更新参数到最优解

i=0
#设置loss大于0.05时继续训练
while (sess.run(loss) > 0.5*1e-1):
    #每次迭代都要最小化Loss函数
    sess.run(train)
    # 输出训练好的w1 w2 w3 b
    print('第',i,'次迭代时参数和loss的值为:','w1=', sess.run(w1), ' w2=', sess.run(w2), ' w3=', sess.run(w3), ' b3=', sess.run(b), ' loss=',sess.run(loss))
    i=i+1

3. 模型保存与恢复(两种方法:ckpt和PB)

当训练好一个神经网络后,会想保存好模型便于以后使用并且用于生产。那么,什么是Tensorflow模型?Tensorflow模型主要包含网络设计(或者网络图)和训练好的网络参数的值。所以Tensorflow模型有两个主要的文件:

a) Meta图:
Meta图是一个协议缓冲区(protocol buffer),它保存了完整的Tensorflow图;比如所有的变量、运算、集合等。这个文件的扩展名是.meta。

b) Checkpoint 文件
这是一个二进制文件,它保存了权重、偏置项、梯度以及其他所有的变量的取值,扩展名为.ckpt。但是, 从0.11版本开始,Tensorflow对改文件做了点修改,checkpoint文件不再是单个.ckpt文件,而是如下两个文件:
model.data-00000-of-00001
model.index
其中, .data文件包含了我们的训练变量。除此之外,还有一个叫checkpoint的文件,它保留了最新的checkpoint文件的记录。

总结一下,对于0.10之后的版本,tensorflow模型包含以下文件:

  • checkpoint 文本文件,记录了模型文件的路径信息列表
  • model.ckpt.data-00000-of-00001 网络权重信息
  • model.ckpt.index .data和.index这两个文件是二进制文件,保存了模型中的变量参数(权重)信息
  • model.ckpt.meta 二进制文件,保存了模型的计算图结构信息(模型的网络结构)

存什么:Graph 结构、变量值
怎么存:主要两种模式:

  1. ckpt 模式:
    计算图和变量分开保存
    读取模型时需要重新定义计算图,无需指明变量名

  2. pb 模式: 封装存储方案,隐藏模型结构
    计算图和变量封装在一个文件中
    无需重新定义计算图,但是需要指出变量名

ckpt 模式

保存模型:

import tensorflow as tf

v1 = tf.Variable(tf.constant(1.0,shape=[1]),name="v1")
v2 = tf.Variable(tf.constant(2.0,shape=[1]),name="v2")
result = v1 + v2

# 保存训练好的数据
saver = tf.train.Saver()

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    saver.save(sess, "Saved_model/model.ckpt")
    print("已保存完毕!")

恢复模型:

import tensorflow as tf

v1 = tf.Variable(tf.constant(1.0,shape=[1]),name="v1")
v2 = tf.Variable(tf.constant(2.0,shape=[1]),name="v2")
result = v1 + v2

# 保存训练好的数据
saver = tf.train.Saver()

with tf.Session() as sess:
    print("正在加载...")
    saver.restore(sess, "./Saved_model/model.ckpt")
    print(sess.run(result)) 
    
#输出:
正在加载...
[3.]

如果你读取2次模型变量,可能(也可能不会出错)会出现以下错误:

NotFoundError (see above for traceback): Key weights_2 not found in checkpoint
     [[Node: save_3/RestoreV2_11 = RestoreV2[dtypes=[DT_FLOAT], _device="/job:localhost/replica:0/task:0/cpu:0"](_recv_save_3/Const_0, save_3/RestoreV2_11/tensor_names, save_3/RestoreV2_11/shape_and_slices)]]

原因:可以看到再次读取模型时,权重名称已经变成了weights_2。所以就会报错误。
解决办法:在存储模型的末尾加上tf.reset_default_graph()语句或在恢复程序定义变量前加上。

保存模型

import tensorflow as tf
v1 = tf.Variable(tf.constant(1.0,shape=[1]),name="v1")
v2 = tf.Variable(tf.constant(2.0,shape=[1]),name="v2")
result = v1 + v2

# 保存训练好的数据
saver = tf.train.Saver()

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    saver.save(sess, "Saved_model/model.ckpt")
    print("已保存完毕!")
    
#清除默认图的堆栈,并设置全局图为默认图
#解决多次运行之后的错误:NotFoundError (see above for traceback): Key Variable_1 not found in checkpoint
tf.reset_default_graph()

或在恢复模型中

import tensorflow as tf
# 清除默认图的堆栈,并设置全局图为默认图
tf.reset_default_graph()

v1 = tf.Variable(tf.constant(1.0,shape=[1]),name="v1")
v2 = tf.Variable(tf.constant(2.0,shape=[1]),name="v2")
result = v1 + v2

# 保存训练好的数据
saver = tf.train.Saver()
with tf.Session() as sess:
    print("正在加载...")
    saver.restore(sess, "./Saved_model/model.ckpt")
    print(sess.run(result))

直接加载已经持久化的图

import tensorflow as tf
# 清除默认图的堆栈,并设置全局图为默认图 
tf.reset_default_graph()
saver = tf.train.import_meta_graph("./Saved_model/model.ckpt.meta")
with tf.Session() as sess:
    saver.restore(sess, "./Saved_model/model.ckpt")
    print(sess.run(tf.get_default_graph().get_tensor_by_name("add:0")))

如果在tf.train.Saver()中不指定任何东西,它将默认保存所有的变量。要是不想保存所有的变量而只是一部分变量。可以指定想要保存的变量/集合。当创建tf.train.Saver()对象的时候,给它传递一个想要保存的变量的字典列表。来看一个例子:

import tensorflow as tf
w1 = tf.Variable(tf.random_normal(shape=[2]), name='w1')
w2 = tf.Variable(tf.random_normal(shape=[5]), name='w2')
saver = tf.train.Saver([w1,w2])
sess = tf.Session()
sess.run(tf.global_variables_initializer())
saver.save(sess, 'my_test_model',global_step=1000)

当需要的时候,这个代码可以用来保存Tensorflow图中的指定部分。

pb 模式

保存模型

w1= tf.Variable(tf.random_uniform([1]),name='w1')
w2= tf.Variable(tf.random_uniform([1]),name='w2')
w3= tf.Variable(tf.random_uniform([1]),name='w3')
b= tf.Variable(tf.random_uniform([1]),name='b')

#PB模式保存
constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph_def,["w1","w2","w3","b"])
with tf.gfile.FastGFile('save_pb.pb', mode='wb') as f:
    f.write(constant_graph.SerializeToString())

恢复模型

import tensorflow as tf

with tf.Session() as sess:
  with tf.gfile.FastGFile("save_pb.pb", "rb") as f:
    graph_def = tf.GraphDef()
    graph_def.ParseFromString(f.read())
    sess.graph.as_default()
    tf.import_graph_def(graph_def,name='')
    sess.run(tf.global_variables_initializer())
    print(sess.run(sess.graph.get_tensor_by_name("w1:0")))
    print(sess.run(sess.graph.get_tensor_by_name("w2:0")))
    print(sess.run(sess.graph.get_tensor_by_name("w3:0")))
    print(sess.run(sess.graph.get_tensor_by_name("b:0")))

ckpt转pb

4. tensorflow中的计算图(Graph)

只创建一个Graph图(默认图)

在Tensorflow中,始终存在一个默认的Graph,当创建Operation、Tensor时,tensorflow会将这些节点和边自动添加到这个默认Graph中。
那么,当我们只想创建一个图时,并不需要使用tf.Graph()函数创建一个新图,而是直接定义需要的Tensor和Operation,这样,tensorflow会将这些节点和边自动添加到默认Graph中。

import tensorflow as tf

###-----图的构建阶段---------###
w = tf.Variable([[3.0,2.5],[1.0,2.7]]) #图中边Variabel的定义
x = tf.constant(1.0,shape=[1,2])       #图中边x_tensor的生成

y = tf.matmul(w,tf.transpose(x))       #节点:变量的乘法和转置操作(operation)
init_op = tf.global_variables_initializer()   #节点:Variable的initialize_operation
#----------tensorflow会将上面定义的节点和边自动添加到默认Graph中------#

###------图的执行阶段-------###
with tf.Session() as sess:    
    sess.run(init_op)      # 执行init_op操作,此时tf.matmul并没有run  
    print(sess.run(y))     # 在会话中执行tf.matmul操作, 打印y_tensor,

tf.get_default_graph()获取默认计算图

在tensorflow程序中,系统会自动维护一个默认的计算图,可以通过tf.get_default_graph()函数获取。以下代码展示了如何获取默认计算图以及如何查看一个运算所属的计算图:

import tensorflow as tf
a=tf.constant([1.0,2.0], name='a') # 定义一个常量使用tf.constant方法
b=tf.constant([1.0,2.0], name='b')
result = a+b
# 通过a.graph可以查看张量所属的计算图,如果没有特别指定,则属于当前默认的计算图
print(a.graph is tf.get_default_graph()) # 输出为True

tf.Graph()定义多个Graph图

在tensorflow中,可以使用tf.Graph()函数创建图。如果我们需要定义多个Graph,则可以在with语句中调用tf.Graph.as_default()方法将某个graph设置成默认Graph,这样with语句块中调用的Operation或Tensor将会添加到该Graph中。

with语句是保证操作的资源可以正确的打开和释放,而且不同的计算图上的张量和运算彼此分离,互不干扰

import tensorflow as tf
graph1 = tf.Graph()
with graph1.as_default():#创建图1
    c1 = tf.constant([9.0])

with tf.Graph().as_default() as graph2:  #创建图2
    c2 = tf.constant([1.0])

with tf.Session(graph=graph1) as sess1:#使用sess1 运行graph1
    print (sess1.run(c1))
with tf.Session(graph=graph2) as sess2:#使用sess2 运行graph2
    print (sess2.run(c2))

注:定义多个图时,可以通过设置tf.Sesstion(graph=) 中的参数,选择当前的Session执行哪个计算图。

指定Graph计算图运行的设备

TensorFlow中计算图可以通过tf.Graph.device函数来指定运行计算图的设备。下面程序将加法计算放在CPU上执行,也可以使用tf.device达到同样的效果。

g = tf.Graph()
with g.device('/cpu:0'):
    result = 1 + 2

5. 会话Session

Session会话是tensorflow里面的重要机制,tensorflow构建的计算图必须通过Session会话才能执行.比如在tensorflow中定义了两个矩阵a和b,和一个计算a和b乘积的c节点,如果想要得到a和b的乘积(也就是c节点的运算结果)的话,必须要建立Session会话,并调用Session中的run方法运行c节点才行。

  • 应用sess.run或者eval运行图程序并获取张量值
  • 应用feed_dict机制实现运行时填充数据
  • 应用placeholder实现创建占位符

创建方式

(1)tf.Session()创建一个会话,当上下文管理器退出时会话关闭和资源释放自动完成。

import tensorflow as tf
a = tf.constant(3, tf.float32)
b = tf.constant(4, tf.float32)
c = a+b
with tf.Session() as sess1:
    print(sess1.run(c))
print(a.eval(session = sess1))

在执行语句print(a.eval(session = sess1))时, 由于上下文管理器已经退出,会话已经关闭,因此会报错。

(2)tf.Session().as_default()创建一个默认会话,当上下文管理器退出时会话没有关闭,还可以通过调用会话进行run()和eval()操作

import tensorflow as tf
a = tf.constant(3, tf.float32)
b = tf.constant(4, tf.float32)
c = a+b
with tf.Session().as_default()  as sess1:
    print(sess1.run(c))
print(a.eval(session = sess1))

tf.Session().as_default()虽然上下文管理器已经退出,但是会话没有关闭,后面的函数还是可以调用该会话中的函数。

下面的两个命令有相同的功能:
print(sess.run(result))
print(result.eval(session=sess))

(3) tf.InteractiveSession()是一种交替式((比如Python脚本 IPython 或者Jupyter的编辑器下)的会话方式,它让自己成为了默认的会话,也就是说用户在单一会话的情境下,不需要指明用哪个会话也不需要更改会话运行的情况下,就可以运行起来,这就是默认的好处。这样的话就是run和eval()函数可以不指明session了。

import tensorflow as tf
a = tf.constant(3, tf.float32)
b = tf.constant(4, tf.float32)
c = a+b
sess = tf.InteractiveSession()
print(a.eval())

简单来说InteractiveSession()等价于:
sess=tf.Session()
with sess.as_default():

两种管理模式

推荐使用通过Python的上下文管理器来使用会话,比较下面两种:
第一种:

# 创建一个会话。
sess = tf.Session()
# 使用会话得到之前计算的结果。
sess.run(...)
# 关闭会话使得本次运行中使用到的资源可以被释放。
sess.close()

这种方式在所有计算完成之后,需要明确调用Session.close函数来关闭会话释放资源。然而,当程序因为异常而退出时,关闭会话的函数可能就不会被执行从而导致资源泄露。

第二种:(推荐使用)

#创建一个会话,并通过Python中的上下文管理器来管理
with tf.Session() as sess:
 
    #使用这个会话来计算关心的结果
    sess.run(...)

这种不再需要调用“Session.close()”函数来关闭会话,当上下文退出时会话关闭和资源释放也会自动完成

6. Tensor

在TensorFlow中,所有数据都通过Tensor的形式来表示。从功能上看,Tensor可以被简单的理解为多维数组。零阶张量表示标量(scalar),一阶张量表示向量,二阶张量表示矩阵,n阶张量表示n维数组。张量并没有保存数字,保存的是运算结果的引用。

TensorFlow 支持以下三种类型的张量:

  • 常量:常量是其值不能改变的张量。
  • 变量:当一个量在会话中的值需要更新时,使用变量来表示。例如,在神经网络中,权重需要在训练期间更新,可以通过将权重声明为变量来实现。变量在使用前需要被显示初始化。另外需要注意的是,常量存储在计算图的定义中,每次加载图时都会加载相关变量。换句话说,它们是占用内存的。另一方面,变量又是分开存储的。它们可以存储在参数服务器上。
  • 占位符:用于将值输入 TensorFlow 图中。它们可以和 feed_dict 一起使用来输入数据。在训练神经网络时,它们通常用于提供新的训练样本。在会话中运行计算图时,可以为占位符赋值。这样在构建一个计算图时不需要真正地输入数据。需要注意的是,占位符不包含任何数据,因此不需要初始化它们。

例如:

#定义两个向量a,b
#tf.constant是一个计算,这个计算的结果为一个张量,保存在变量a,b中
a = tf.constant([1.0, 2.0], name='a')
b = tf.constant([2.0, 3.0], name='b')
result = a+b
# result = tf.add(a, b, name="add")  #两行都可以
print(result)
>>Tensor("add:0", shape=(2,), dtype=float32)

从结果可看出,一个张量主要保存了三个属性:名字name、维度shape和类型type。  

  • 张量的命名:可以用“node:src_output”来表示,node为节点的名称,src_output表示当前张量来自节点的第几个输出。add:0表示result张量是节点add输出的第一个结果(从0开始)。  
  • 张量的维度,shape=(2,)说明了result是一个一维数组,长度为2。
  • 张量的类型type:应用于数据计算中,计算的时候数据类型要匹配。
    TensorFlow支持14种不同的类型,实数(tf.float32、tf.float64)、整数(tf.int8、tf.int16、tf.int32、tf.int64、tf.uint8)、布尔型(tf.bool)和复数(tf.complex64、tf.complex128)。  

TensorFlow计算时会对类型检查,若类型不匹配则会报错。若不显示指出类型,tensorflow会给出下面程序会报错:

#报错版本
a = tf.constant([1, 2], name='a')
b = tf.constant([2.0, 3.0], name='b')
result = a+b
改成如下形式则正确:
a = tf.constant([1, 2], name='a',dtype=float)
b = tf.constant([2.0, 3.0], name='b')
result = a+b
或
from tensorflow import float32 
a = tf.constant([1, 2], name='a',dtype=float32)
b = tf.constant([2.0, 3.0], name='b')
result = a+b

Tensor形式

  • tf.Tensor
  • tf.Variable
  • numpy.ndarray
  • list (and lists of tensor-like objects)
  • Scalar Python types: bool, float, int, str

一些特殊的:

  • tf.constant():返回一个常量 tensor
  • tf.Variable():返回一个 tensor-like 对象,表示变量
  • tf.SparseTensor():返回一个tensor-like 对象
  • tf.placeholder():return a tensor that may be used as a handle for feeding a value, but not evaluated directly.

创建张量

固定值张量

tf.zeros(shape, dtype=tf.float32, name=None)
创建所有元素设置为零的张量。此操作返回一个dtype具有形状shape和所有元素设置为零的类型的张量。

tf.zeros_like(tensor, dtype=None, name=None)
给tensor定单张量(),此操作返回tensor与所有元素设置为零相同的类型和形状的张量。

tf.ones(shape, dtype=tf.float32, name=None)
创建一个所有元素设置为1的张量。此操作返回一个类型的张量,dtype形状shape和所有元素设置为1。

tf.ones_like(tensor, dtype=None, name=None)
给tensor定单张量(),此操作返回tensor与所有元素设置为1 相同的类型和形状的张量。

tf.fill(dims, value, name=None)
创建一个填充了标量值的张量。此操作创建一个张量的形状dims并填充它value。

tf.constant(value, dtype=None, shape=None, name=‘Const‘)
创建一个常数张量。

tf.linspace(start, stop, num,, name=None)
产生 num 个等距分布在 [start, stop] 间元素组成的数组,包括 start & stop (需为 float 类型), increase by (stop - start) / (num - 1)

tf.range([start], limit, delta=1, dtype=None, name=‘range‘)
[]为可选参数,步长 delta 默认为 1,start 默认为 0, limit 的值取不到,它产生一个数字序列

tf.range(start=3, limit=18, delta=3)  # [3, 6, 9, 12, 15]
tf.range(limit=5)  # [0, 1, 2, 3, 4]
随机张量

(1)正态分布
tf.random_normal:创建一个正态分布的随机数张量
tf.random_normal( shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None )

args:

  • shape:一维整数或 Python 数组表示输出张量的形状。
  • mean:dtype 类型的0-D张量或 Python 值表示正态分布的均值。
  • stddev:dtype 类型的0-D张量或 Python 值表示正态分布的标准差。
  • dtype:输出的类型。
  • seed:一个 Python 整数。用于为分发创建一个随机种子。
  • name:操作的名称(可选)。

返回:将返回一个指定形状的张量,通过符合要求的随机值填充。

tf.truncated_normal
生成的值遵循具有指定平均值和标准差的正态分布,和tf.random_normal不同之处在于其平均值大于 2 个标准差的值将被丢弃并重新选择。

tf.truncated_normal( shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None )

(2)均匀分布  
tf.random_uniform:从均匀分布中输出随机值。
random_uniform( shape, minval=0, maxval=None, dtype=tf.float32, seed=None, name=None )

生成的值在该 [minval, maxval) 范围内遵循均匀分布。下限 minval 包含在范围内,而上限 maxval 被排除在外。

args:

  • shape:一维整数或 Python 数组表示输出张量的形状。
  • minval:dtype 类型的 0-D 张量或 Python 值;生成的随机值范围的下限;默认为0。
  • maxval:dtype 类型的 0-D 张量或 Python 值。要生成的随机值范围的上限。如果 dtype 是浮点,则默认为1 。
  • dtype:输出的类型:float16、float32、float64、int32、orint64。
  • seed:一个 Python 整数。用于为分布创建一个随机种子。
  • name:操作的名称(可选)。

返回:
用于填充随机均匀值的指定形状的张量。

(3)随机分布  

7. 变量的创建

变量是计算图中的一种特殊的节点,张量是对数据样本的抽象表示。
变量常用来表达我们机器学习中不断调整的参数,调参数需要干两件事:1. 赋初值;2. 更新参数

常量初始化
constant_name = tf.constant(value)

tf.Variable、tf.get_variable()和tf.placeholder()创建变量

  • 三个方法都能创建变量,tf.get_variable()和tf.Variable()创建的变量默认都是trainable;tf.placeholder()是占位符,创建的变量是不可训练的。
  • 使用tf.Variable()变量,不进行初始化数值会出错
  • tf.Variable()和tf.get_variable()最大的区别在于指定变量名称的参数。对于tf.Variable(),变量名称name是一个可选的参数。但是对于tf.get_variable(),变量名称是一个必填的参数。
  • tf.get_variable()是官方推荐的最佳方式:这个函数要求指定变量的名称,这个名称将作为副本用于访问相同的变量,以及在检查点和导出模型时命名次变量的值。
  • tf.Variable、tf.tf.Variable()设计目的不同,创建方式不同:tf.Variable主要用于新创建,tf.get_variable()主要用于重用或共享变量。因此,tf.Variable用于创建新变量,可以重名,如果检测到命名冲突,系统会自己处理。使用tf.get_variable()时,系统不会处理冲突,而会报错。tf.get_variable()允许重复使用先前创建的同名变量,从而轻松定义复用层的模型。共享变量通过tf.variable_scope()和tf.get_variable配合来实现
  • get_variable 第一次创建,要至少给 shape
  • tf.get_variable:无视 name_scope, 只看 variable_scope

tf.Variable(initial_value, trainable=True, collections=None, validate_shape=True, name=None)
tf.get_variable()和tf.Variable参数差不多,只是初始值不是必须的
参数名称 | 参数类型 | 含义
---|--- |---
initial_value | 所有可以转换为Tensor的类型 |变量的初始值(必须的,其他参数可选)
trainable | bool |如果为True,会把它加入到GraphKeys.TRAINABLE_VARIABLES,才能对它使用Optimizer
collections | list | 指定该图变量的类型、默认为[GraphKeys.GLOBAL_VARIABLES]
validate_shape |bool | 如果为False,则不进行类型和维度检查
name | string |变量的名称,如果没有指定则系统会自动分配一个唯一的值

In [1]: import tensorflow as tf
In [2]: v = tf.Variable(3, name='v')
In [3]: v2 = v.assign(5)
In [4]: sess = tf.InteractiveSession()
In [5]: sess.run(v.initializer)
In [6]: sess.run(v)
Out[6]: 3
In [7]: sess.run(v2)
Out[7]: 5
import tensorflow as tf
# 设置GPU按需增长
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
# 1.placeholder
v1 = tf.placeholder(tf.float32, shape=[2,3,4])
print(v1.name)  #Placeholder:0
v1 = tf.placeholder(tf.float32, shape=[2,3,4], name='ph')
print(v1.name)   #ph:0
v1 = tf.placeholder(tf.float32, shape=[2,3,4], name='ph')
print(v1.name)   #ph_1:0
print(type(v1)) #<class 'tensorflow.python.framework.ops.Tensor'>
print(v1)  #Tensor("ph_1:0", shape=(2, 3, 4), dtype=float32)


# 2. tf.Variable()
v2 = tf.Variable([1,2], dtype=tf.float32)
print (v2.name)  #Variable:0
v2 = tf.Variable([1,2], dtype=tf.float32, name='V')
print (v2.name)  #V:0
v2 = tf.Variable([1,2], dtype=tf.float32, name='V')
print (v2.name)  #V_1:0
print (type(v2))  #<class 'tensorflow.python.ops.variables.Variable'>
print (v2)    #<tf.Variable 'V_1:0' shape=(2,) dtype=float32_ref>

# 3.tf.get_variable() 创建变量的时候必须要提供 name
v3 = tf.get_variable(name='gv', shape=[])
print (v3.name) #gv:0
print (type(v3))  #<class 'tensorflow.python.ops.variables.Variable'>
print (v3)   #<tf.Variable 'gv:0' shape=() dtype=float32_ref>
#下面报错:ValueError: Variable gv already exists, disallowed. Did you mean to set reuse=True in VarScope?
#v4 = tf.get_variable(name='gv', shape=[2])

tf.trainable_variables()
tf.get_variable()和tf.Variable()创建的变量默认都是trainable;tf.placeholder()是占位符,创建的变量是不可训练的。

#tf.get_variable()和tf.Variable()创建的变量默认都是trainable
vs = tf.trainable_variables()
print(len(vs)) #4
for v in vs:
    print(v)
# <tf.Variable 'Variable:0' shape=(2,) dtype=float32_ref>
# <tf.Variable 'V:0' shape=(2,) dtype=float32_ref>
# <tf.Variable 'V_1:0' shape=(2,) dtype=float32_ref>
# <tf.Variable 'gv:0' shape=() dtype=float32_ref>

tf.get_variable:无视 name_scope, 只看 variable_scope

import tensorflow as tf
with tf.name_scope('nsc1'):
    v1 = tf.Variable([1], name='v1')
    with tf.variable_scope('vsc1'):
        v2 = tf.Variable([1], name='v2')
        v3 = tf.get_variable(name='v3', shape=[])
print ('v1.name: ', v1.name)
print ('v2.name: ', v2.name)
print ('v3.name: ', v3.name)
# v1.name:  nsc1/v1:0
# v2.name:  nsc1/vsc1/v2:0
# v3.name:  vsc1/v3:0

变量初始化

个别变量初始化:
init_op = name_variable.initializer()
所有变量初始化:
init= tf.global_variables_initializer()
sess.run(init)

命名规则和作用域、scope机制(scope:tf.name_scope, tf.variable_scope)

(1)tensorflow采用scope机制, 一种层级的命名管理机制:例:vgg16/conv1/w:0。
(2)可以不显示起名,此时tensorflow自动取名。在定义saver的时候没有自己给tensor取名字,那么,tensorflow会按照自己的方式给你的tensor取名字。取名字的方式如下:

如果tensor是常量,那么就按规律取名:Const,Const_1,Const_2,Const_3,……
如果tensor是变量,那么就按规律取名:Variable,Variable_1,Variable_2,Variable_3,……

和普通模型相比,深度学习模型的节点(参数)非常多,我们很难确定哪个变量属于哪层。为了解决此问题,所以引入了两个作用域(scope)name_scope和variable_scope,两者分别承担着不同的责任:
tf.name_scope : 给变量名前面加个变量空间名,只限于tf.Variable()的变量
tf.variable_scope :给变量名前面加个变量空间名,包括tf.get_variable()的变量和tf.Variable()的变量;与或tf.variable_scope一起用还可以实现变量共享

  • tf.variable_scope和tf.get_variable搭配使用可以实现变量分类命名和变量共享。tf.get_variable:无视 name_scope, 只看 variable_scope。
  • tf.Variable可以搭配tf.name_scope或tf.variable_scope使用,给变量分类命名,模块化。
  • tf.Variable和tf.variable_scope搭配使用不伦不类,不是设计者的初衷
import tensorflow as tf
with tf.name_scope('nsc1'):
    v1 = tf.Variable([1], name='v1')
    with tf.variable_scope('vsc1'):
        v2 = tf.Variable([1], name='v2')
        v3 = tf.get_variable(name='v3', shape=[])
print ('v1.name: ', v1.name)
print ('v2.name: ', v2.name)
print ('v3.name: ', v3.name)
# v1.name:  nsc1/v1:0
# v2.name:  nsc1/vsc1/v2:0
# v3.name:  vsc1/v3:0

tf.name_scope, tf.variable_scope实现共享变量

当训练复杂模型时,可能经常需要共享大量的变量。例如,使用测试集来测试已训练好的模型性能表现时,需要共享已训练好模型的变量,如全连接层的权值。

import tensorflow as tf
with tf.name_scope('nsc1'):
    v1 = tf.Variable([1], name='v1')
    with tf.variable_scope('vsc1'):
        v2 = tf.Variable([1], name='v2')
        v3 = tf.get_variable(name='v3', shape=[])
print ('v1.name: ', v1.name)
print ('v2.name: ', v2.name)
print ('v3.name: ', v3.name)
# v1.name:  nsc1/v1:0
# v2.name:  nsc1/vsc1/v2:0
# v3.name:  vsc1/v3:0
----------------------------------------
with tf.variable_scope("one"):
     a = tf.get_variable("v", [1]) #a.name == "one/v:0"
with tf.variable_scope("one"):
     b = tf.get_variable("v", [1]) #创建两个名字一样的变量会报错 ValueError: Variable one/v already exists 
with tf.variable_scope("one", reuse = True): #注意reuse的作用。
     c = tf.get_variable("v", [1]) #c.name == "one/v:0" 成功共享,因为设置了reuse

在声明命名空间的时候,将reuse设置为True,这样tf.get_variable将直接获取已经声明的变量。

import tensorflow as tf
with tf.variable_scope("foo"):
    v=tf.get_variable("v",[1],initializer=tf.constant_initializer(1.0))

with tf.variable_scope("foo", reuse=True):
    v1=tf.get_variable("v",[1])
    print(v==v1);

执行这段代码,输出为True。
不过,reuse定义为True的时候,tf.get_variable只能获取已经拥有的变量。如果命名空间中没有定义这个变量就会报错。
比如讲上面代码的第二个命名空间名字改为bar再次执行就会报错。

import tensorflow as tf
with tf.variable_scope("foo"):
    v=tf.get_variable("v",[1],initializer=tf.constant_initializer(1.0))

#下面代码报错
with tf.variable_scope("bar", reuse=True):
    v1=tf.get_variable("v",[1])
    print(v==v1);

变量管理器还可以通过名称轻松访问变量。

import tensorflow as tf
with tf.variable_scope("foo"):
    v = tf.get_variable("v",[1],initializer=tf.constant_initializer(1.0))
    print(v.name)

with tf.variable_scope("foo"):
    with tf.variable_scope("bar"):
        v1 = tf.get_variable("v",[1])
        print(v1.name);

with tf.variable_scope("",reuse=True):
    v2 = tf.get_variable("foo/v");
    print(v2==v)
    print(v2==v1)
    v3 = tf.get_variable("foo/bar/v")
    print(v3==v)
    print(v3==v1)
    
输出结果:
foo/v:0
foo/bar/v:0
True
False
False
True
共享变量总结

(1)不考虑变量重用
最好不用 tf.get_variable, 只用 tf.Variable,name_scope,variable_scope 随意
(2)考虑变量重用
只用 tf.get_variable、用 variable_scope 划分名字空间、scope 的 reuse 属性用 tf.AUTOREUSE 方便复用定义
(3)搞不清将来要不要复用变量
用 tf.get_variable 创建变量、最好用 variable_scope 划分名字空间、scope 的 reuse 属性设置为每层传进来的参数(...,reuse=reuse_flag)

8. 变量赋值或更新assign()

TF通过assign operation 赋值机制,来修改、更新变量值包括 assign(ref, value, validate_shape= None, use_locking=None, name = None)及一些变种:assign_add()、assign_sub()

用法注意:不是我们习惯的 ref = assign(assign_value) 而是
assign_tensor = assign(ref, assign_value)
返回值 assign_tensor 是一个在赋值完成后,保留”ref” 的新值的张量,后续计算需要更新的值的时候,引用的是 assign_tensor;
不但可以改值,变量定义参数 validate_shape = False,还可以改变量形状。

例子:tf.assign(A, new_number)赋值
这个函数的功能主要是把A的值变为new_number

import tensorflow as tf

x = tf.Variable(1)
x = tf.assign(x, 2)
sess = tf.Session()
print(sess.run(x))

例子:tf.assign_add(b,value)
返回一个op张量,表示给变量b加value的操作

tf.assign和 = 的区别

tf.assign是创建一个操作符这个操作符具有这个值变量的值,而=是Python中的赋值,tensorflow函数的操作会新建一个节点,如果用Python的=那么就相当于将变量的引用给到这个新节点上,但是在计算图上并没有相应的赋值操作节点(因为只是python对于等式右边节点的一个引用而已),而如果使用tf.assign的话计算图中有赋值节点。

a = tf.Variable(3)
op = tf.assign_add(a,1)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    sess.run(op)
    sess.run(op)
    sess.run(op)
    sess.run(op)
    print(sess.run(a))
>>7

------------------------------------------不用assign不能更新a
a = tf.Variable(3)
a = a + 1

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    sess.run(a)
    sess.run(a)
    sess.run(a)
    sess.run(a)
    print(a)
    print(sess.run(a))
>>Tensor("add:0", shape=(), dtype=int32)
4
import tensorflow as tf

b=tf.Variable ([2], name='b')
b=tf.add(b,1)
out=b*2

with tf.Session () as sess:
   sess.run(tf. global_variables_initializer ())
   for i in range (3):
      print(sess.run([out ,b]))
# [array([6], dtype=int32), array([3], dtype=int32)]
# [array([6], dtype=int32), array([3], dtype=int32)]
# [array([6], dtype=int32), array([3], dtype=int32)]

assign与数据驱动的机制:数据驱动图,从一次 fetch 的最高节点倒推到涉及的最初节点,从下往上逐个计算

import tensorflow as tf

#创建变量b,并初始化为2
b=tf.Variable ([2], name='b')
#返回一个op张量,表示给变量b加1的操作
assign_op=tf.assign_add(b ,[1])
out=assign_op *2

with tf.Session () as sess:
   sess.run(tf. global_variables_initializer ())
   for i in range (3):
      print(sess.run([out ,b]))
# [array([6], dtype=int32), array([3], dtype=int32)]
# [array([8], dtype=int32), array([4], dtype=int32)]
# [array([10], dtype=int32), array([5], dtype=int32)]

   y = b * out
   print(sess.run([y]))
# [array([72], dtype=int32)]

x=b+out
with tf.Session () as sess:
   #必须初始化,否则出现x未初始化
   sess.run(tf. global_variables_initializer ())
   print(sess.run([x]))
#[array([9], dtype=int32)]
import tensorflow as tf
import numpy as np

var=tf.Variable(0.,name='var')
const=tf.constant(1.)
add_op=tf.add(var,const,name='myAdd')

assign_op=tf.assign(var,add_op,name='myAssign')

out1=assign_op*1
out2=assign_op*2

#sess.run(out1),sess.run(out2)分别对var加1,执行两次
with tf.Session() as sess:
   sess.run(tf.global_variables_initializer())
   for i in range(3):
      print('var:',sess.run(var),sess.run(out1),sess.run(out2))
# var: 0.0 1.0 4.0
# var: 2.0 3.0 8.0
# var: 4.0 5.0 12.0

#sess.run([out1,out2])一起对var加1一次
with tf.Session() as sess:
   sess.run(tf.global_variables_initializer())
   for i in range(3):
      print('var:',sess.run(var),sess.run([out1,out2]))
# var: 0.0 [1.0, 2.0]
# var: 1.0 [2.0, 4.0]
# var: 2.0 [3.0, 6.0]

9. TensorFlow之矩阵基本运算

这里所说的基本运算,是指常见的加、减、乘、除运算,需要区分矩阵乘法和矩阵点乘。

tf.add(x, y, name=None)
矩阵x和矩阵y对应位置的元素相加

tf.subtract(x, y, name=None)
矩阵x和矩阵y对应位置的元素相减

tf.divide(x, y, name=None)
矩阵x和矩阵y对应位置的元素相除

Hadamard积:tf.multiply(x, y, name=None)
矩阵x和矩阵y对应位置的元素相乘

矩阵乘法:tf.matmul(a, b, transpose_a=False, transpose_b=False, adjoint_a=False, adjoint_b=False, a_is_sparse=False, b_is_sparse=False, name=None)

注意:若a是一个tensor,b是一个scalar,则对a里面的每个元素,都执行相同操作(+,-,*,/)scalar

test

标签:控制   注入   err   脚本   智能   ESS   原理   填充   出错   

原文地址:https://www.cnblogs.com/yyl424525/p/11397430.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!