TensorFlow 简介

一、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

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值