zoukankan      html  css  js  c++  java
  • tensorflow-基础知识

    tensorflow中,Graph是一个就像一个大容器,OP、Tensor、Variable是这个大容器的组成部件。

    Graph管理Tensor对象,Session管理Variable对象。Variable对象必须在Session对象内初始化。初始化所有Variable对象,把.global_variables_initializer() Op传给Session.run()。初始化部分Variable对象,把.variables_initializer() Op传给Session.run()。Variable.assign()Op,修改Variable对象,必须在Session对象中运行。.assign_add()创建自增Op,.assign_sub()创建自减Op。不同Session对象独立维护在Graph对象定义的Variable对象值。Optimizer类自动训练机器学习模型,自动修改Variable对象值。创建Variable对象时trainable参数设False,只允许手工修改值。

    1、基本元素

     

    1.1 图(Graph)

    class tf.Graph

    1. TensorFlow中的计算,表示为一个数据流图,简称“图”
    2. 一个Graph实例就是一个图,由一组Operation对象和Tensor对象构成:每个Operation对象(简记为op)表示最小的计算单元,每个Tensor对象表示在operations间传递的基本数据单元
    3. 如果你没有注册自己的图,系统会提供一个默认图。你可通过调用tf.get_default_graph()显式地访问这个图,也可以不理会这个图,因为调用任一个operation函数时,如调用constant op,c=tf.constant(4.0),一个表示operation的节点会自动添加到这个图上,此时c.graph就指这个默认图。
    4. 如果我们创建了一个Graph实例,并想用它取代上面的默认图,把它指定为一个新的默认图,至少是临时换一下,可以调用该Graph实例的as_default()方法,并得到一个Python中的上下文管理器(context manager),来管理临时默认图的生命周期,即with ...下的代码区域。

    为了向默认图添加一个操作,可以简单地调用定义了一个新的 Opertation 的函数:

    c = tf.constant(4.0)
    assert c.graph is tf.get_default_graph()

    另外一个典型的用法包括 Graph.as_default() 这个上下文管理器(context manager)在上下文环境中覆盖了当前的默认图。

    g = tf.Graph()
    with g.as_default():
    # Define operations and tensors in `g`.
      c = tf.constant(30.0)
      assert c.graph is g

    重要提示:这个类构建图是非线程安全的。所有的操作应该从单个线程中创建,否则必须提供外部同步。除非明确指明,所有方法都是非线程安全的。

    1.1.1 Graph的属性

    内部属性

      • 与operation相关: 
        • _nodes_by_id:dict( op的id => op ),按id记录所有添加到图上的op
        • _nodes_by_name:dict( op的name => op ),按名字记录所有添加到图上的op
        • _next_id_counter:int,自增器,创建下一个op时用的id
        • _version:int,记录所有op中最大的id
        • _default_original_op:有些op需要附带一个original_op,如replica op需要指出它要对哪个op进行复制
        • _attr_scope_map:dict( name scope => attr ),用于添加一组额外的属性到指定scope中的所有op
        • _op_to_kernel_label_map:dict( op type => kernel label ),kernel可能是指operation中更底层的实现
        • _gradient_override_map:dict( op type => 另一个op type ),把一个含自定义gradient函数的注册op,用在一个已存在的op上
      • 与命名域name scope相关: 
        • _name_stack:字符串,嵌套的各个scopes的名字拼成的栈,用带间隔符”/”的字符串表示
        • _names_in_use: dict( name scope => 使用次数 )
      • 与device相关: 
        • _device_function_stack: list,用来选择device的函数栈,每个元素是一个device_function(op),用来获取op所在device
      • 与控制流相关: 
        • _control_flow_context:一个context对象,表示当前控制流的上下文,如CondContext对象,WhileContext对象,定义在ops/control_flow_ops.py。实际上,控制流也是一个op,用来控制其他op的执行,添加一些条件依赖的关系到图中,使执行某个operation前先查看依赖
        • _control_dependencies_stack:list,一个控制器栈,每个控制器是一个上下文,存有控制依赖信息,表明当执行完依赖中的operations和tensors后,才能执行此上下文中的operations
      • 与feed和fetch相关: 
        • _unfeedable_tensors:set,定义不能feed的tensors
        • _unfetchable_ops:set,定义不能fetch的ops
        • _handle_feeders:dict( tensor handle placeholder => tensor dtype )
        • _handle_readers:dict( tensor handle => 它的read op )
        • _handle_movers:dict( tensor handle => 它的move op )
        • _handle_deleters:dict( tensor handle => 它delete op )
      • 图需要: 
        • _seed:当前图内使用的随机种子
        • _collections:dict( collection name => collection ),相当于图中的一块缓存,每个collection可看成一个list,可以存任何对象
        • _functions:定义图内使用中的一些函数
        • _container:资源容器resource container,用来存储跟踪stateful operations,如:variables,queues
        • _registered_ops:注册的所有操作
      • 程序运行需要: 
        • _finalized:布尔值,真表示Graph属性都已确定,不再做修改
        • _lock:保证读取Graph某些属性(如:_version)时尽可能线程安全
      • TensorFlow框架需要: 
        • _graph_def_version:图定义的版本
      • 其他: 
        • _building_function:该图是否表示一个函数
        • _colocation_stack:保存共位设置(其他op都与指定op共位)的栈

    对外属性

    • tf.Graph.version,也就是self._version,记录最新的节点version,即图中最大op id,但是与GraphDef的version无关
    • tf.Graph.graph_def_versions,也就是self._graph_def_versions,GraphDef版本,定义在tensorflow/tensorflow/core/framework/graph.proto
    • tf.Graph.seed,也就是self._seed,此图内使用的随机种子
    • tf.Graph.building_function,也就是self._building_function
    • tf.Graph.finalized,也就是self._finalized,表明组装图阶段是否完成

    1.1.2 Graph的主要方法

    tf.graph.__init__()

    创建一个新的空的图。

    tf.Graph.as_default()

    返回一个使得当前图成为默认图的上下文管理器
    这个方法应该在你想要在相同的过程中创建多图时被使用。为了方便,一个全局默认图已经被提供,如果你没有明确创建一个新的图,所有的操作将会被添加进这张图。当你使用这个方法时,请使用 with 关键字明确在接下来的代码块范围内创建的操作应该加进这张图。
    默认图是当前线程的一个属性,如果你创建了一个新的线程,并且希望在这个线程里使用默认图,你必须在这个线程的函数里明确添加 with g.as_default():
    下面的代码示例(相对于上述解释)是等价的:

    # 1. Using Graph.as_default():
    g = tf.Graph()
    with g.as_default():
      c = tf.constant(5.0)
      assert c.graph is g
    
    # 2. Constructing and making default:
    with tf.Graph().as_default() as g:
      c = tf.constant(5.0)
      assert c.graph is g

    返回: 一个用于将当前图作为默认图的上下文管理器

    tf.Graph.as_graph_def(from_version=None, add_shapes=False)

    返回一个表示这个图的序列化的 GraphDef。

    这个序列化的 GraphDef 可以被引入另一个图(使用 import_graph_def())或者使用 C++ Session API。
    这个方法是线程安全的。

    参数
    from_version: 可选的,如果被设定,将返回一个 GraphDef,它包含仅从这张图的版本属性有了给定值后加入这张图的节点(nodes),表明包括的节点version(即op id)的范围,from_version之前的节点都不要。
    add_shapes: 如果是真值,给每个带有输出推断图形的结点添加一个_output_shapes列表属性。(每个节点都要添加输出tensors的形状信息到_output_shapes)
    返回: 一个 GraphDef协议缓冲区(protocol buffer)
    引起的错误: ValueError: 如果 graph_def 太大

    tf.Graph.as_graph_element(obj, allow_tensor=True, allow_operation=True)

    该获取信息的方法实际上完成了一个验证加转换的工作,给定一个obj,看它能否对应到图中的元素,可以是一个operation,也可以是一个tensor,如果对应,则以operation或tensor的身份返回它自己。该方法可以被多个线程同时调用。 

    参数

    (1) obj:可以是一个Tensor对象,或一个Operation对象,或tensor名,或operation名,或其他对象;

    (2) allow_tensor:真表示obj可以是tensor;

    (3) allow_operation:真表示obj可以是operation

    get系列方法,可被多个线程同时调用:
    tf.Graph.get_operation_by_name(name):根据名字获取某个operation
    tf.Graph.get_tensor_by_name(name):根据名字获取某个tensor
    tf.Graph.get_operations():获取所有operations


    判断是否可feed或可fetch
    tf.Graph.is_feedable(tensor)
    tf.Graph.is_fetchable(tensor_or_op)


    设置不可feed或不可fetch
    tf.Graph.prevent_feeding(tensor)
    tf.Graph.prevent_fetching(op)

     

    tf.Graph.finalize()

    结束这个图,使它只读
    在调用g.finalize()后,不能向g添加任何新的操作。当这个图在多线程间共享时,为了保证没有操作添加到这个图,可以调用这个方法,例如当使用一个 QueueRunner时

    tf.Graph.finalized

    如果这个图已经结束,它为真

    tf.Graph.control_dependencies(control_inputs)

    返回一个明确控制依赖(control dependencies)的上下文管理器

    使用 with 关键字明确所有在上下文内创建的操作应该在control_inputs上有控制依赖。例如:

    with g.control_dependencies([a, b, c]):
    # `d` and `e` will only run after `a`, `b`, and `c` have executed.
    d = ...
    e = ...

    control_dependencies()的多重调用可以嵌套,在这种情况下,基于所有活动的上下文中的 control_inputs 的联合,一个新的 Operation 将拥有控制依赖。

    with g.control_dependencies([a, b]): # Ops constructed here run after `a` and `b`.
    	with g.control_dependencies([c, d]): # Ops constructed here run after `a`, `b`, `c`, and `d`.

    你可以通过None来清除控制依赖。

    with g.control_dependencies([a, b]): # Ops constructed here run after `a` and `b`.
    	with g.control_dependencies(None): # Ops constructed here run normally, not waiting for either `a` or `b`.
    with g.control_dependencies([c, d]): # Ops constructed here run after `c` and `d`, also not waiting for either `a` or `b`.

    :控制依赖应用于那些在上下文内建立的操作。很少在上下文中使用使用一个 op 或者 tensor 时不添加一个控制依赖。下面的例子解释了这一点:

    #tf.Graph.control_dependencies(control_inputs)
    # 错误代码
    def my_func(pred, tensor):
    	t = tf.matmul(tensor, tensor)
    	with tf.control_dependencies([pred]):
    		# 乘法操作(op)没有创建在该上下文,所以没有被加入依赖控制
    		return t
    
    # 正确代码
    def my_func(pred, tensor):
    	with tf.control_dependencies([pred]):
    		# 乘法操作(op)创建在该上下文,所以被加入依赖控制中
    		#执行完pred之后再执行matmul
    		return tf.matmul(tensor, tensor)

    参数:
    control_inputs:一个 Operation 或者 Tensor 对象列表,它上下文内定义的操作被运行前被执行或者计算。也可以为None来清除控制依赖。
    返回
    一个明确在上下文内所有操作的控制依赖的上下文管理器
    引起的错误
    TypeError: 如果 control_inputs 不是一个 Operation 或者Tensor 对象的列表。

    tf.Graph.devide(device_name_or_function)

    返回一个明确默认设备的使用的上下文管理器
    device_name_or_function 参数可以是一个设备名字符串,一个设备函数或者None:
    如果这个参数是一个设备名字符串,所有在此上下文构建的操作将被指派给是这个名称的设备,除非它被一个嵌套的 device() 上下文所覆盖
    如果这个参数是函数,它将被视为一个从 Operation 对象到设备名字符串的函数,并且每次一个新的Operation被创建时都会被调用。这个Operation将会被指派给这个带有返回名的设备
    如果是None,所有从封闭的上下文调用的device()将会被忽略
    想了解关于设备名字符串的合法语法,请在DeviceNameUtils中查阅相关文档

    示例:

    with g.device('/gpu:0'):
    	# All operations constructed in this context will be placed
    	# on GPU 0.
    	with g.device(None):
    		# All operations constructed in this context will have no
    		# assigned device.
    
    # Defines a function from `Operation` to device string.
    def matmul_on_gpu(n):
    	if n.type == "MatMul":
    		return "/gpu:0"
    	else:
    		return "/cpu:0"
    
    with g.device(matmul_on_gpu):
    	# All operations of type "MatMul" constructed in this context
    	# will be placed on GPU 0; all other operations will be placed
    	# on CPU 0.

    :设备范围可能会被op包装器或者其他库代码所覆盖。例如,一个变量指定操作 v.assign()必须被tf.Variable v所托管(colocated),并且不兼容的设备将被忽略。
    参数
    device_name_or_function:在上下文中使用的设备名或函数
    返回值
    一个为新创建的操作明确默认设备的上下文管理器

    tf.Graph.name_scope(name)

    返回为操作创建分层的上下文管理器
    一张图维持一个命名空间栈,在当前上下文生命期,一个 with name_scope(…):声明将一个新的名称压栈。
    name参数将解释如下
    一个字符串(没有以’/’结尾)将创建一个新的命名空间,在此空间name会附加到所有在上下文里创建的操作的前缀。如果name之前被用过,可以通过调用self.unique_name(name)使它变为独特的name
    一个从之前a with g.name_scope(…) as scope: 声明捕获的空间将被视为一个绝对命名空间,这使得它有可能代表现有的空间
    一个None值或者空字符串将会重置当前命名空间到最高层(空的)命名空间
    示例:

    # tf.Graph.name_scope(name)
    # 一个图中包含有一个名称范围的堆栈,在使用name_scope(...)之后,将压(push)新名称进栈中,
    #并在下文中使用该名称
    with tf.Graph().as_default() as g:
    	c = tf.constant(5.0, name="c")
    	assert c.op.name == "c"
    	c_1 = tf.constant(6.0, name="c")
    	assert c_1.op.name == "c_1"
    
    	# Creates a scope called "nested"
    	with g.name_scope("nested") as scope:
    		nested_c = tf.constant(10.0, name="c")
    		assert nested_c.op.name == "nested/c"
    
    		# Creates a nested scope called "inner".
    		with g.name_scope("inner"):
    			nested_inner_c = tf.constant(20.0, name="c")
    			assert nested_inner_c.op.name == "nested/inner/c"
    
    		# Create a nested scope called "inner_1".
    		with g.name_scope("inner"):
    			nested_inner_1_c = tf.constant(30.0, name="c")
    			assert nested_inner_1_c.op.name == "nested/inner_1/c"
    
    			# Treats `scope` as an absolute name scope, and
    			# switches to the "nested/" scope.
    			with g.name_scope(scope):
    				nested_d = tf.constant(40.0, name="d")
    				assert nested_d.op.name == "nested/d"
    
    				with g.name_scope(""):
    					e = tf.constant(50.0, name="e")
    					assert e.op.name == "e"

    空间本身的命名可以被with g.name_scope(…) as scope:所捕获,它在变量空间内存有空间的命名。这个结果可以在一个空间内命名代表执行操作的所有结果的操作(This value can be used to name an operation that represents the overall result of executing the ops in a scope)。

    参数:
    name: 一个空间的命名
    返回:
    一个设置(install)name为新的命名空间的上下文管理器
    一张图实例支持任意多个被命名标志的“集合”,为了方便,当建立一个很大的图时。集合能存储一组相关的对象。例如,tf.Variable为所有在图建立期间创建的变量使用一个集合(名为tf.GraphKeys.VARIABLES)。调用者可以通过指定一个新的命名来定义额外的集合。

    tf.Graph.add_to_collection(name,value)

    将value值存入给定name的collection
    注意collections不是sets,所以有可能将同一个值多次加入一个collection。
    参数:
    names: collection的关键字(key)。 GraphKeys类包含许多标准集合名称
    value:加入collection的值

    tf.Graph.add_to_collections(names,value)

    将value存入给定的names的collections中
    注意collections不是sets,所以有可能将同一个值多次加入一个collection。这个函数保证忽略names中的重复值,但不会检查names中任意一个collection的value里已存在的成员。(This function makes sure that duplicates in names are ignored, but it will not check for pre-existing membership of value in any of the collections in names.)
    names可以是可迭代的,但是如果它是个字符串,它将被视为一个单集合名
    参数:
    names: 要加入的collections的关键字(keys)。GraphKeys类包含许多标准集合名称
    value:加入collections的值

    tf.Graph.get_collection(name,scope=None)

    返回给定名称集合的值的列表
    这个方法不同于get_collection_ref(),后者总是返回真正的集合(如果存在),因此每次被调用时,它总是返回一个新的列表。(This is different from get_collection_ref() which always returns the actual collection list if it exists in that it returns a new list each time it is called.)
    参数
    name:集合的关键字。例如 GraphKeys类含有许多类的标准命名
    scope:(可选)如果提供了,结果过滤列表仅包含那些没有名称属性总不返回,名称(name)属性匹配使用re.match得到的条目。如果一个 空间(scope)被提供,那么choice或者re.match意味着一个没有特殊前缀标记过滤器的空间。
    返回:
    给定名称的集合中值的列表,或者空表(当没有值加入集合)。这个列表包含一些按顺序的值,在这个顺序下它们被收集。

    1.2 占位符(placeholder)

    tf.placeholder(dtype, shape=None, name=None)

    此函数可以理解为形参,用于定义过程,在执行的时候再赋具体的值。

    参数:

    • dtype:数据类型。常用的是tf.float32,tf.float64等数值类型
    • shape:数据形状。默认是None,就是一维值,也可以是多维,比如[2,3], [None, 3]表示列是3,行不定
    • name:名称。

     

    1.3 常量(constant)

     

    1.3.1 Constant Value Tensors

    tensorflow基本的数据类型有14种,在这几本数据类型上,给与了3种主要的包装类型,分别是Constants value tensors,Sequence和Random Tensors。

    数据类型 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位浮点数组成的复数:实数和虚数.
    DT_QINT32 tf.qint32 用于量化Ops的32位有符号整型.
    DT_QINT8 tf.qint8 用于量化Ops的8位有符号整型.
    DT_QUINT8 tf.quint8 用于量化Ops的8位无符号整型.

    tf.constant(value,dtype = None,shape = None,name = "Constant")
    这是最基础的一个,参数种dtype建议增加,若不增加,tensorflow会默认加一个,程序可能会有bug,shape对value进行一次形状变化,需要传入一个python列表;name为图中保存的名字。
    示例:
    a =tf.constant(np.arange(10),dtype = tf.float32,shape = [2,5],name = "constant")

    tf.zeros(shape,dtype = tf.float32,name = None)

    tf.ones(shape,dtype = tf.float32,name = None)
    这两个函数差不多,一个生成全为0的常量,一个生成全为1的常量,默认的格式tf.float32.

    tf.zeros_like(tensor,dtype=None,name = None)

    tf.ones_like(tensor,dtype=None,name = None)
    这俩函数基本一样,需要传入一个tensor,导出一个同结构全0/1的tensor,数据类型可能变化。

    tf.fill(dims,value,name = None)

    dims的参数其实和shape是一样的,这个函数生成了一个以dims(列表)为结构,value为值的一个tensor。

    1.3.2 Sequences

    生成一维tensor,主要由两个函数,分别是linspace 和 range,用法有稍微的区别。


    tf.linspace(start,stop,num,name = None )
    生成一个一维tensor,以start为开始,以stop为结束,这两个数都必须是float,num为总个数(int)。 print(tf.linspace(0.0,10.0,11).eval()) 结果为 [ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]


    tf.range(start,limit,delta = 1,name = "range")
    生成一个一维tensor,以start为开始,最大不超过limit,间隔为delta。建议使用整数,浮点数可能会出现精度问题。

    1.3.3 Random Tensors

    生成常用的多维随机数。包括几个生成器和一个种子设置方法。
    tf.random_normal(shape,mean = 0,stddev = 1,dtype = tf.float32,seed = None,name = None)
    tf.truncated_normal(shape,mean = 0,stddev = 1,dtype = tf.float32,seed = None,name = None)
    这两函数都是生成正态随机数,区别是truncated在生成随机数后,如果随机数在两倍标准差之外,就重新生成一个,直到生成最终结果。参数中shape为一个列表,表示形状,mean和stddev分别标书均值和标准差,seed为随机数种子。和其他python随机语法一样,固定seed以后,生成的随机数将不变。


    tf.random.uniform(shape,minval = 0.0,maxval = 1.0,dtype = tf.float32,seed = None)
    这个函数生成从0到1中平均分布的数值。


    tf.random_shuffle(value,seed = None,name = None)
    传入一个tensor,然后将这个rensor进行随机洗牌。

    1.4 变量(variable)

    当训练模型时,用变量来存储和更新参数。变量包含张量 (Tensor)存放于内存的缓存区。建模时它们需要被明确地初始化,模型训练后它们必须被存储到磁盘。这些变量的值可在之后模型训练和分析时被加载。

    当创建一个变量时,你将一个张量作为初始值传入构造函数Variable()。 TensorFlow提供了一系列操作符来初始化张量,初始值是常量或是随机值。在初始化时需要指定张量的shape,变量的shape通常是固定的,但TensorFlow提供了高级的机制来重新调整。

    Tensor、Op对象不可变(immutable)。.Variable()构造方法创建Variable对象,包含Session.run()调用中可持久化的可变张量值。

    我们通过tf.Variable构造一个variable添加进图中,Variable()构造函数需要变量的初始值(是一个任意类型、任意形状的tensor),这个初始值指定variable的类型和形状。通过Variable()构造函数后,此variable的类型和形状固定不能修改了,但值可以用assign方法修改。

    如果想修改variable的shape,可以使用一个assign op,令validate_shape=False.

    通过Variable()生成的variables就是一个tensor,可以作为graph中其他op的输入。另外,Tensor类重载的所有操作符都被转载到此variables中,所以可以通过对变量调用方法,将节点添加到图形中。

    1.4.1 新建与初始化

    tf.Variable

    tf.Variable.__init__(initial_value=None, trainable=True, collections=None, validate_shape=True, caching_device=None, name=None, variable_def=None, dtype=None)

    新变量添加到collections 列出的图集合中,默认添加到 [GraphKeys.VARIABLES]。

    如果 trainable 是True,变量也添加到图集合 GraphKeys.TRAINABLE_VARIABLES.

    这个构造器创建了两个操作节点,一个变量操作和一个赋值操作,用于将初始值赋给变量。

    • initial_value:  一个Tensor,或者可以转化为Tensor的Python对象,这是变量的初始值,可以传入数值,列表,numpy数组,tf的tensor等。初始值必须指定shape除非validate_shape 被设置为False。但是对一个变量来说,最好使用固定结构的变量。
    • trainable:  如果是True,变量也默认添加到GraphKeys.TRAINABLE_VARIABLES,collections默认添加到图的[GraphKeys.VARIABLES] 中。这是很多优化器类使用的默认变量列表。

    在tf.Variables的类中有add,sub,dtype、name,get_shape()等属性和方法

    Variable() 构造器需要一个初始值,可以是任意类型和shape 的Tensor。初始值定义了变量的type和shape。构造完成之后,变量的type和shape 是固定的。可以使用assign 方法来修改变量的值。

    如果你想修改变量的shape,你必须使用assign 操作,并且 validate_shpe=False。

    初始化器

    tf.variables_initilizer(var_list,name = "nint")

    tf.global_variables_initializer()

    前者对指定的一个变量列表进行初始化,后者则对所有的变量进行初始化。

    注意:这里的初始化只是在计算图中定义了这样的一个节点,这个节点的运算是将变量进行初始化,所以在实际计算中,还是要调用sess.run(initializer),才能真正的完成初始化过程。

    查询变量

    tf.gloable_variables()

    显示图中所有的变量。

    tf.trainable_variables()

    显示图中可训练的变量。

    初始值生成函数

     

    (1)生成tensor

    tf.ones | tf.zeros

    tf.ones(shape,type=tf.float32,name=None)

    用法类似,都是产生尺寸为shape的张量(tensor)

    示例:

    tf.zeros([2, 3], int32)

     

    tf.ones_like | tf.zeros_like

    tf.ones_like(tensor,dype=None,name=None)

    tf.zeros_like(tensor,dype=None,name=None)

    新建一个与给定的tensor类型大小一致的tensor,其所有元素为1和0

    示例:

    tensor=[[1, 2, 3], [4, 5, 6]]

    x = tf.ones_like(tensor)

     

    tf.fill

    tf.fill(shape,value,name=None)

    创建一个形状大小为shape的tensor,其初始值为value

    示例:

    tf.fill([2,3],2)

     

    tf.constant

    tf.constant(value,dtype=None,shape=None,name=’Const’)

    创建一个常量tensor,按照给出value来赋值,可以用shape来指定其形状。value可以是一个数,也可以是一个list。

    如果是一个数,那么这个常亮中所有值的按该数来赋值。

    如果是list,那么len(value)一定要小于等于shape展开后的长度。赋值时,先将value中的值逐个存入。不够的部分,则全部存入value的最后一个值。

    示例:

    v4_1 = tf.constant([1, 2, 3, 4, 5, 6, 7])

    v4_2 = tf.constant(-1.0, shape=[2, 3])

    (2)生成序列

    tf.linspace | tf.range

    tf.linspace(start,stop,num,name=None)

    tf.range(start,limit=None,delta=1,name=’range’)

    这两个放到一起说,是因为他们都用于产生等差数列,不过具体用法不太一样。

    tf.linspace在[start,stop]范围内产生num个数的等差数列。不过注意,start和stop要用浮点数表示,不然会报错

    tf.range在[start,limit)范围内以步进值delta产生等差数列。注意是不包括limit在内的。

     

    (3)生成随机数

    tf.random_normal | tf.truncated_normal | tf.random_uniform

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

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

    tf.random_uniform(shape,minval=0,maxval=None,dtype=tf.float32,seed=None,name=None)

    这几个都是用于生成随机数tensor的。尺寸是shape

    random_normal: 正太分布随机数,均值mean,标准差stddev

    truncated_normal:截断正态分布随机数,均值mean,标准差stddev,不过只保留[mean-2*stddev,mean+2*stddev]范围内的随机数

    random_uniform:均匀分布随机数,范围为[minval,maxval]

    tf.random_shuffle

    tf.random_shuffle(value,seed=None,name=None)

    沿着value的第一维进行随机重新排列

    示例:

    v8_5 = tf.random_shuffle([[1,2,3],[4,5,6],[6,6,6]], seed=134, name="v8_5")

    tf.random_crop(value, size, seed=None, name=None)

     

    tf.multinomial(logits, num_samples, seed=None, name=None)

     

    tf.random_gamma(shape, alpha, beta=None, dtype=tf.float32, seed=None, name=None)

     

    tf.set_random_seed(seed)

     

    tf.get_variable

     

    tf.get_variable(name, shape=None, dtype=dtypes.float32, initializer=None,

                     regularizer=None, trainable=True, collections=None,

                     caching_device=None, partitioner=None, validate_shape=True,

                     custom_getter=None)

    如果在该命名域中之前已经有名字=name的变量,则调用那个变量;如果没有,则根据输入的参数重新创建一个名字为name的变量。

    initializer: 初始化工具,有tf.zero_initializer, tf.ones_initializer, tf.constant_initializer, tf.random_uniform_initializer,tf.random_normal_initializer,tf.truncated_normal_initializer等。

    initializer(初始化)

     

    tf.constant_initializer(value=0, dtype=tf.float32)

     

    tf.random_normal_initializer(mean=0.0, stddev=1.0, seed=None, dtype=tf.float32)

     

    tf.truncated_normal_initializer(mean=0.0, stddev=1.0, seed=None, dtype=tf.float32)

     

    tf.random_uniform_initializer(minval=0, maxval=None, seed=None, dtype=tf.float32)

     

    tf.uniform_unit_scaling_initializer(factor=1.0, seed=None, dtype=tf.float32)

     

    tf.zeros_initializer(shape, dtype=tf.float32, partition_info=None)

     

    tf.ones_initializer(dtype=tf.float32, partition_info=None)

     

    tf.orthogonal_initializer(gain=1.0, dtype=tf.float32, seed=None)

     

    tf.get_variable与tf.variable的对比

     

    相同点

    通过两函数创建变量的过程基本一样,且tf.variable函数调用时提供的维度(shape)信息以及初始化方法(initializer)的参数和tf.Variable函数调用时提供的初始化过程中的参数基本类似。

    不同点

    两函数指定变量名称的参数不同,对于tf.Variable函数,变量名称是一个可选的参数,通过name="v"的形式给出。而tf.get_variable函数,变量名称是一个必填的参数,它会根据变量名称去创建或者获取变量。

    tf.get_variable在创建变量时会查名字,如果给的名字在之前已经被别的变量占用,则会报错,不会创建相应变量。而tf.variable并不进行检查,如果有重复,则自动的修改名字,加上数字来进行区别。所以从这来看要想共享变量并不能通过使用相同的名字来调用多次 tf.get_variable 和 tf.variable 做到。

     

    1使用tf.Variable时,如果检测到命名冲突,系统会自己处理。使用tf.get_variable()时,系统不会处理冲突,而会报错。

    import tensorflow as tf
    w_1 = tf.Variable(3, name="w_1")
    w_2 = tf.Variable(1, name="w_1")
    print w_1.name
    print w_2.name
    # 输出
    # w_1:0
    # w_1_1:0

    *********************************************************************

    import tensorflow as tf
    w_1 = tf.get_variable(name="w_1", initializer=1)
    w_2 = tf.get_variable(name="w_1", initializer=2)
    # 错误信息
    # ValueError: Variable w_1 already exists, disallowed. Did
    # you mean to set reuse=True in VarScope?

    当我们需要共享变量的时候,需要使用tf.get_variable()。在其他情况下,这两个的用法是一样的。

    2由于tf.Variable() 每次都在创建新对象,所有reuse=True 和它并没有什么关系。对于get_variable(),来说,如果已经创建的变量对象,就把那个对象返回,如果没有创建变量对象的话,就创建一个新的。

    import tensorflow as tf
    with tf.variable_scope("scope1"):
       w1 = tf.get_variable("w1", shape=[])
       w2 = tf.Variable(0.0, name="w2")
    with tf.variable_scope("scope1", reuse=True):
       w1_p = tf.get_variable("w1", shape=[])
       w2_p = tf.Variable(1.0, name="w2")
    print(w1 is w1_p, w2 is w2_p)
    # 输出
    # True  False

     

    tf.trainable_variables

    返回所有可训练的变量。

    在创造变量(tf.Variable, tf.get_variable 等操作)时,都会有一个trainable的选项,表示该变量是否可训练。这个函数会返回图中所有trainable=True的变量。

    tf.get_variable(…), tf.Variable(…)的默认选项是True, 而 tf.constant(…)只能是False。

    各种优化器类使用这个集合作为默认的变量列表去优化。

    tf.all_variables

    返回的是所有变量的列表

    1.4.2 变量的保存与读取

    tensorflow使用Saver类进行变量的保存和读取,系统的变量将被保存到checkpoints中,point我简单的理解成快照,其本质是tensorflow使用二进制保存的变量名到变量值的map映射文件。

    1.5 tf.Operation 

    Operation是teansorflow 中操作节点的抽象化,有0个或多个输入和0个或多个输出,在运行后使用tf.get_default_session().run(op)进行运行,或者op.run(),这是前面的简化调用方式。主要属性与方法如下:

    tf.Operation.name 获取名称
    tf.Operation.type 获取属性
    tf.Operation.inputs 获取输入值
    tf.Operation.control_inputs 获取输入依赖值
    tf.Operation.outputs 获取输出值
    tf.Operation.device 获取操作设备
    tf.Operation.graph 获取graph
    tf.Operation.run(feed_dict=None, session=None) 如果op传入的是placeholder 对象,则需要使用feed_dict参数进行传入。
    tf.Operation.get_attr(name) 获取op该属性的对应值。

    1.6 tf.Tensor

    tensor代表一个operation的结果。从tensorflow 的实际运行来说,tensor是operation一个输出的句柄,但是tensor所引用的并不持有具体的值,而是保持一个计算过程,在session调用的时候,可以使用这个计算过程来得到最终的结果。在python api中主要由两方面基本的内容:
    (1)一个tensor可以被传递到另外一个operation,从而形成最终的数据流。这样,session中只需要对最后一个计算进行编码即可。
    (2)在session调用最终的图之后,可以使用session.run()或者t.eval()对tensor的值进行计算。
    常用的属性和函数如下:
    tf.Tensor.dtype 数据类型
    tf.Tensor.name tensor名称
    tf.Tensor.value_index 在input中的index
    tf.Tensor.graph 返回图名
    tf.Tensor.op 返回操作名
    tf.Tensor.consumers() 返回使用了这个tensorflow 的op列表
    tf.Tensor.eval(feed_dict=None, session=None) 需要在session中使用,可以事先使用placeholder
    tf.Tensor.get_shape() 获取形状
    tf.Tensor.set_shape(shape) 设置形状
    tf.Tensor.device 获取计算的设备

    3、正则

    在损失函数上加上正则项是防止过拟合的一个重要方法。

    tensorflow中对参数使用正则项分为两步:

    1. 创建一个正则方法(函数/对象)

    2. 将这个正则方法(函数/对象),应用到参数上

    3.1 创建正则方法函数

    tf.contrib.layers.l1_regularizer(scale, scope=None)

    返回一个用来执行L1正则化的函数,函数的签名是func(weights)。

    参数:

    • scale: 正则项的系数.
    • scope: 可选的scope name

    tf.contrib.layers.l2_regularizer(scale, scope=None)

    返回一个执行L2正则化的函数.

    tf.contrib.layers.sum_regularizer(regularizer_list, scope=None)

    返回一个可以执行多种(个)正则化的函数.意思是,创建一个正则化方法,这个方法

    是多个正则化方法的混合体.

    参数:

    regularizer_list: regulizer的列表。

    3.2 应用正则化方法到参数上

    tf.contrib.layers.apply_regularization(regularizer, weights_list=None)

    参数:

    • regularizer:就是我们上一步创建的正则化方法
    • weights_list: 想要执行正则化方法的参数列表,如果为None的话,就取GraphKeys.WEIGHTS中的weights.

     

    5、控制

     

    tf.control_dependencies()

    control_dependencies(self, control_inputs)

    只有在 control_inputs被执行以后,上下文管理器中的操作才会被执行。例如:

    1. with tf.control_dependencies([a, b, c]):  
    2.      # `d` and `e` will only run after `a`, `b`, and `c` have executed.  
    3.      d = ...  
    4.      e = ...  
    5.      c= tf.no_op(name='train') # tf.no_op;什么也不做

     

    只有[a,b,c]都被执行了才会执行d和e操作,这样就实现了流的控制。

    也能通过参数None清除控制依赖,例如:

    1. with g.control_dependencies([a, b]):  
    2.       # Ops constructed here run after `a` and `b`.  
    3.       with g.control_dependencies(None):  
    4.         # Ops constructed here run normally, not waiting for either `a` or `b`.  
    5.         with g.control_dependencies([c, d]):  
    6.           # Ops constructed here run after `c` and `d`, also not waiting  
    7.           # for either `a` or `b`.  

    注意

    控制依赖只对那些在上下文环境中建立的操作有效,仅仅在context中使用一个操作或张量是没用的。

    6、Saver

    我们经常在训练完一个模型之后希望保存训练的结果,这些结果指的是模型的参数,以便下次迭代的训练或者用作测试。Tensorflow针对这一需求提供了Saver类。

    1. Saver类提供了向checkpoints文件保存和从checkpoints文件中恢复变量的相关方法。Checkpoints文件是一个二进制文件,它把变量名映射到对应的tensor值 。
    2. 只要提供一个计数器,当计数器触发时,Saver类可以自动的生成checkpoint文件。这让我们可以在训练过程中保存多个中间结果。例如,我们可以保存每一步训练的结果。
    3. 为了避免填满整个磁盘,Saver可以自动的管理Checkpoints文件。例如,我们可以指定保存最近的N个Checkpoints文件。

     

    Class tf.train.Saver

    保存和恢复变量

    最简单的保存和恢复模型的方法是使用tf.train.Saver 对象。构造器给graph的所有变量,或是定义在列表里的变量,添加save 和 restore ops。saver 对象提供了方法来运行这些ops,定义检查点文件的读写路径。

    检查点是专门格式的二进制文件,将变量name 映射到 tensor value。检查checkpoin 内容最好的方法是使用Saver 加载它。

    Savers 可以使用提供的计数器自动计数checkpoint 文件名。这可以是你在训练一个模型时,在不同的步骤维持多个checkpoint。例如你可以使用 training step number 计数checkpoint 文件名。为了避免填满硬盘,savers 自动管理checkpoint 文件。例如,你可以最多维持N个最近的文件,或者没训练N小时保存一个checkpoint.

    通过传递一个值给可选参数 global_step ,你可以编号checkpoint 名字。

    1. saver.save(sess, 'my-model', global_step=0) ==>filename: 'my-model-0'  
    2. saver.save(sess, 'my-model', global_step=1000) ==>filename: 'my-model-1000'  

    另外,Saver() 构造器可选的参数可以让你控制硬盘上 checkpoint 文件的数量。

    • max_to_keep:  表明保存的最大checkpoint 文件数。当一个新文件创建的时候,旧文件就会被删掉。如果值为None或0,表示保存所有的checkpoint 文件。默认值为5(也就是说,保存最近的5个checkpoint 文件)。
    • keep_checkpoint_every_n_hour:  除了保存最近的max_to_keep checkpoint 文件,你还可能想每训练N小时保存一个checkpoint 文件。这将是非常有用的,如果你想分析一个模型在很长的一段训练时间内是怎么改变的。例如,设置 keep_checkpoint_every_n_hour=2 确保没训练2个小时保存一个checkpoint 文件。默认值10000小时无法看到特征。

    注意,你仍然必须调用save() 方法去保存模型。传递这些参数给构造器并不会自动为你保存这些变量。

    一个定期保存的训练程序如下这样:

    1. #Create a saver  
    2. saver=tf.train.Saver(...variables...)  
    3. #Launch the graph and train, saving the model every 1,000 steps.  
    4. sess=tf.Session()  
    5. for step in xrange(1000000):  
    6.     sess.run(...training_op...)  
    7.     if step % 1000 ==0:  
    8.         #Append the step number to the checkpoint name:  
    9.         saver.save(sess,'my-model',global_step=step)  

    除了checkpoint 文件之外,savers 还在硬盘上保存了一个协议缓存,存储最近的checkpoint 列表。这用于管理 被编号的checkpoint 文件,并且通过latest_checkpoint() 可以很容易找到最近的checkpoint 的路径。协议缓存存储在紧挨checkpoint 文件的名为 'checkpoint' 的文件中。

    如果你创建了几个savers,你可以调用save() 指定协议缓存的文件名。

    tf.train.Saver.__init__(var_list=None, reshape=False, shared=False, max_to_keep=5, keep_checkpoint_every_n_hour=10000.0, name=None, restore_sequentially=False, saver_def=None, builder=None)

    创建一个Saver

    构造器添加操作去保存和恢复变量。

    var_list 指定了将要保存和恢复的变量。它可以传dict 或者list

    • 变量名字的dict: key 是将用来在checkpoint 文件中存储和恢复的变量的名称。
    • 变量的list:  变量的 op name

    可选参数 reshape ,如果为True,允许从保存文件中恢复一个不同shape 的变量,但元素的数量和type一致。如果你reshap 了一个变量而又想从一个旧的文件中恢复,这是非常有用的。

    可选参数 shared,如果为True,通知每个设备上共享的checkpoint.

    tf.train.Saver.save(sess, save_path, global_step=None, latest_filename=None, meta_graph_suffix='meta', write_meta_graph=True)

    保存变量

    这个方法运行通过构造器添加的操作。它需要启动图的session。被保存的变量必须经过了初始化。

    方法返回新建的checkpoint 文件的路径。路径可以直接传给restore() 进行调用。

    参数:

    • sess:  用于保存变量的Session
    • save_path:  checkpoint 文件的路径。如果saver 是共享的,这是共享checkpoint 文件名的前缀。
    • global_step:  如果提供了global step number,将会追加到 save_path 后面去创建checkpoint 的文件名。可选参数可以是一个Tensor,一个name Tensor或integer Tensor.

    返回值:

    一个字符串:保存变量的路径。如果saver 是被共享的,字符串以'-?????-of-nnnnn' 结尾。'nnnnn' 是共享的数目。

    保存变量

    用tf.train.Saver() 创建一个Saver 来管理模型中的所有变量。

    如果你不给tf.train.Saver() 传入任何参数,那么server 将处理graph 中的所有变量。其中每一个变量都以变量创建时传入的名称被保存

    tf.train.Saver.restore(sess, save_path)

    恢复之前保存的变量

    这个方法运行构造器为恢复变量所添加的操作。它需要启动图的Session。恢复的变量不需要经过初始化,恢复作为初始化的一种方法。

    save_path 参数是之前调用save() 的返回值,或调用 latest_checkpoint() 的返回值。

    参数:

    • sess:  用于恢复参数的Session
    • save_path:  参数之前保存的路径

     

  • 相关阅读:
    【转】WPF DataGridComboBoxColumn使用
    【转】CAD 二次开发--属性块 Block和BlockReference
    【转】【Revit】Revit二次开发——读取cad中的文字信息
    【转】【Centos】Linux(Centos7)下搭建SVN服务器
    现代php编程
    drone实践记录
    PHP拆分YAPI导出的swagjson文件
    pydantic验证器Validator
    利用notion打造读书追逐系统
    opencv马赛克python实现
  • 原文地址:https://www.cnblogs.com/qjoanven/p/7736025.html
Copyright © 2011-2022 走看看