美文网首页
【Tensorflow】编程基础

【Tensorflow】编程基础

作者: 紫晶葫芦 | 来源:发表于2019-05-23 23:08 被阅读0次

    前面说了那么多都是理论的东西,太空洞了。从今天开始就着手编程了,并在编程的过程中,会对前面提到的理论一一的实现一遍,以加深对理论的理解,闲话少说,这就开始。

    1.Tensorflow编程模型

    关键要素:
    1.图:它包含训练模型的参数、语句、操作,它是Tensorflow 的核心,例如:上面提到的WX + B 就是放到图中的,图是运行到内存中的,所以在运行的过程中是特别的吃内存的。
    2.张量:在线性代数中叫向量,在程序中一般叫多维数组,也就是上个文档中提到的样本(X)和标签(Y),在tensorflow 中使用placeholder表示方式。
    3.OP:全称,operate。做的就是把输入的张量组合按W
    X + B起来。
    4.Variable:W、B就是Variable的表现形式之一。

    图1
    图的执行流程就是:张量 (输入) -> op (组合成 W*X + B) -> 运算资源(CPU/GPU)-> 输出结果,而整个图则是要放到session中运行的,也就是只有运行了session,图才能运行。

    2.Tensorflow编程示例

    示例1:

    import tensorflow as tf  
    hello = tf.constant("Hello Tensorflow!")   #定义一个常量
    sess = tf.Session()                        #建立一个Session()
    print(sess.run(hello))                     #通过Session中的run来运行结果
    sess.close()                               #关闭Session()
    

    运行结果:


    图2

    注意:1.constant() 是定义一个常量。2.Session创建了以后需要关闭,不然会造成内存泄漏。
    示例2

    a = tf.constant(3)                         #定义一个常量3
    b = tf.constant(4)                         #定义一个常量4
    with tf.Session() as sess:                 #建立Session
        print("相加:%i" % sess.run(a+b))      #运行a+b 也就是上面提到的OP
        print("相乘:%i" % sess.run(a*b))
    

    运行结果:


    图3

    注意:1.使用with创建的Session() ,是不需要调用sess.close()的,它会在使用完了自动的调用close(),释放掉内存。
    示例3

    c = tf.placeholder(tf.int16)
    d = tf.placeholder(tf.int16)
    add = tf.add(c, d)
    mul = tf.multiply(c, d)
    with tf.Session() as sess2:
        print("相加:%i" % sess2.run(add, feed_dict={c: 3, d: 4}))  
        print("相乘:%i" % sess2.run(mul, feed_dict={c: 3, d: 4}))
        print(sess2.run([add, mul], feed_dict={c: 3, d: 4}))
    

    运行结果:


    图4

    注意:1.这是使用placeholder注入的方式声明变量。

    3.Tensorflow 变量的操作

    1.variable 和 get_variable 的区别
    使用tf.Variable时,如果检测到命名冲突,系统会自己处理。使用tf.get_variable()时,系统不会处理冲突,而会报错。但是,Variable 与get_variable 首次重名可以自动生成。本质就是:tf.Variable() 每次都在创建新对象,而tf.get_variable则不是。

    with tf.Session() as sess2:
    var1 = tf.Variable(1, name="var1")
    var2 = tf.Variable(2, name="var1")
    sess2.run(tf.global_variables_initializer())
    print(var1.name)
    print(var1.eval())
    print(var2.name)
    print(var2.eval())
    print(var1 is var2)
    #输出
    var1:0
    1
    var1_1:0
    2
    False
    
    get_var1 = tf.get_variable(name="var1", initializer=1)
    print(get_var1.name)
    get_var2 = tf.get_variable(name="var1", initializer=2)
    print(get_var2.name)
    #输出
    var1_2:0
    #错误信息
    #ValueError: Variable w_1 already exists, disallowed. Did
    #you mean to set reuse=True in VarScope?
    

    2.variable_scope 与共享变量
    加上作用域以后get_variable可以定义同样的变量名称,系统会自动的生成加作用域的变量。如果在作用域声明的过程中,加入reuse=True,表示可以重复使用,定义了共享部分,如果已经创建的变量对象,就把那个对象返回。

    with tf.variable_scope("test1", ""):
        var1 = tf.get_variable(name="var1", shape=[2],dtype=float)  #定义1行2列的var1变量
        with tf.variable_scope("test2"):
            var2 = tf.get_variable(name="var1",shape=[2],dtype=float)
    print(var1.name)
    print(var2.name)
    #输出
    test1/var1:0
    test1/test2/var1:0
    
    with tf.variable_scope("test1", reuse=True):
        var3 = tf.get_variable(name="var1", shape=[2], dtype=float)
        with tf.variable_scope("test2"):
            var4 = tf.get_variable(name="var1", shape=[2], dtype=float)
    print(var3.name)
    print(var4.name)
    #输出
    test1/var1:0
    test1/test2/var1:0
    

    3.variable_scope 与name_scope的区别
    variable_scope :是作用域,
    name_scope:是操作符,针对上面提到的OP。如:下面的x = var2 + 0.1,就是一个操作。
    示例:

    with tf.variable_scope("scope3"):
        var1 = tf.get_variable("var1", [1])
        with tf.name_scope("scope_name"):  # 针对操作而言的
            var2 = tf.get_variable("var2", [1])
            x = var2 + 0.1
            with tf.variable_scope(""):
                with tf.name_scope(""):
                    var3 = tf.get_variable("var3", [1])
                    y = var2 + 0.2
    print(var1.name)
    print(var2.name)
    print(x.op.name)
    print(var3.name)
    print(y.op.name)
    # 输出
    scope3/var1:0
    scope3/var2:0
    scope3/scope_name/add
    scope3//var3:0
    add_2
    

    注意:
    1.如果tf.name_scope(""),则提到顶层。
    2.tf.variable_scope(""),则相当于增加了“”的域。
    3.name_scope对变量的作用域variable_scope是没有任何影响的,但是variable_scope对name_scope是有影响的。

    3.Tensorflow 图的操作

    1.建立图

    import tensorflow as tf
    # 定义在全局默认图上的常量
    c = tf.constant(0.0)  
    # 重新的定义一个图
    g = tf.Graph()
    with g.as_default():
        c1 = tf.constant(0.0)
        # 获取c1所在的图的地址
        print(c1.graph)
        # 获取创建图的地址
        print(g)
        # 获取c所在图的地址,也就是全局图的地址
        print(c.graph)
    # 获取全局图的地址
    g2 = tf.get_default_graph()
    print(g2)
    # 重新生成全局图,并把旧的图销毁
    tf.reset_default_graph()
    # 获取全局图的地址
    g3 = tf.get_default_graph()
    print("g3:", g3)
    #输出
    <tensorflow.python.framework.ops.Graph object at 0x000001CD50C4AB70>
    <tensorflow.python.framework.ops.Graph object at 0x000001CD50C4AB70>
    <tensorflow.python.framework.ops.Graph object at 0x000001CD4BDA9EF0>
    <tensorflow.python.framework.ops.Graph object at 0x000001CD4BDA9EF0>
    g3: <tensorflow.python.framework.ops.Graph object at 0x000001CD50C4AE10>
    

    注意:
    1.如果在局部图的作用域中获取全局的默认图是不成功的,它只能得到局部的图。
    2.重新设置全局图的方法tf.reset_default_graph()

    with g.as_default():
        c1 = tf.constant(0.0)
        print(c1.graph)
        print(g)
        print(c.graph)
        g3 = tf.get_default_graph()
        print(g3)
    # 输出
    <tensorflow.python.framework.ops.Graph object at 0x000002138838BCF8>
    <tensorflow.python.framework.ops.Graph object at 0x000002138838BCF8>
    <tensorflow.python.framework.ops.Graph object at 0x00000213FF0CB0B8>
    <tensorflow.python.framework.ops.Graph object at 0x000002138838BCF8>
    

    2.获取张量

    print(c1.name)
    # 通过名字,使用所在的图获取张量
    t = g.get_tensor_by_name(name="Const:0")
    # 打印张量的属性
    print(t)
    #输出
    Const:0
    Tensor("Const:0", shape=(), dtype=float32)
    

    3.获取节点操作OP

    # 定义一行两列的数组
    a = tf.constant([[1.0, 2.0]])
    print(a.shape)
    # 定义两行一列的数组
    b = tf.constant([[1.0], [2.0]])
    print(b.shape)
    # 定义矩阵的乘法,操作的名字为:exampleop
    tensor1 = tf.matmul(a, b, name="exampleop")
    # 打印张量的名字、属性
    print(tensor1.name, tensor1)
    # 打印张量的名字、属性
    test = g3.get_tensor_by_name("exampleop:0")
    # 打印张量的属性
    print(test)
    # 输出
    (1, 2)
    (2, 1)
    exampleop:0 Tensor("exampleop:0", shape=(1, 1), dtype=float32)
    Tensor("exampleop:0", shape=(1, 1), dtype=float32)
    
    print("获取操作的属性")
    print('tensor1.op.name', tensor1.op.name)
    # 通过名称使用所在的图得到操作OP的属性
    testop = g3.get_operation_by_name("exampleop")
    # 打印操作OP的属性
    print(testop)
    # 输出
    tensor1.op.name exampleop
    name: "exampleop"
    op: "MatMul"
    input: "Const"
    input: "Const_1"
    attr {
      key: "T"
      value {
        type: DT_FLOAT
      }
    }
    attr {
      key: "transpose_a"
      value {
        b: false
      }
    }
    attr {
      key: "transpose_b"
      value {
        b: false
      }
    }
    
    

    4.获取元素列表

    # 返回图中的操作节点列表
    tt2 = g.get_operations()
    print(tt2)
    # 输出 由上面可以看出在g图中只有c1 定义
    [<tf.Operation 'Const' type=Const>]
    
    

    5.获取对象

    print("获取对象")
    tt3 = g.as_graph_element(c1)
    print(tt3)
    # 输出
    Tensor("Const:0", shape=(), dtype=float32)
    

    4.深度学习训练模型简介

    深度学习的基本开发流程为:
    1.准备数据
    2.搭建模型
    3.训练模型
    4.保存模型
    5.测试模型
    6.查看模型
    下面以线性回归拟合为例(Y=2X)说明:
    说明:1.numpy .random.randn(d0,d1,…,dn):randn函数返回一个或一组样本,具有标准正态分布 ,dn表格每个维度。2.tf.random.normal([1]):从正太分布中随机输出一个值。3.tf.zeros([1]):创建一个所有元素都设置为零的张量,例如:tf.zeros([2]) ,其中的值就是[0. 0.]。

    import tensorflow as tf
    # 生成数据时使用
    import numpy as np
    # 图形化生成数据
    import matplotlib.pyplot as plt
    # 生成字典记录训练批次和loss值
    plotdata = {"batchsize": [], "loss": []}
    # 1.准备数据
    t_X = np.linspace(-1, 1, 100)
    t_Y = 2 * t_X + np.random.randn(100) * 0.3
    # 显示模拟数据
    plt.plot(t_X, t_Y, "ro", label="original data")
    plt.legend()
    plt.show()
    
    # 重新初始化图
    tf.reset_default_graph();
    # 2.搭建模型
    # 占位符
    X = tf.placeholder("float")
    Y = tf.placeholder("float")
    # 2.1模型参数
    W = tf.Variable(tf.random.normal([1]), name="weight")
    b = tf.Variable(tf.zeros([1]), name="bias")
    # 2.2向前结构
    z = tf.multiply(X, W) + b
    # 2.3反向优化(均方差)
    cost = tf.reduce_mean(tf.square(Y-z))
    learning_rate = 0.01
    # 2.4使用tf的梯度下降优化器设定的学利率不断优化W和b使的loss最小化,最终使z于Y的误差最小
    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)
    
    # 3.训练模型
    # 3.1初始化变量
    init = tf.global_variables_initializer()
    # 3.2训练参数
    training_epochs = 20
    display_step = 2
    
    # 4.保存模型
    saver = tf.train.Saver()
    savedir = "Model/"
    # 3.4启动Session
    with tf.Session() as sess:
        sess.run(init)
        for epoch in range(training_epochs):
            for (x, y) in zip(t_X, t_Y):
                sess.run(optimizer, feed_dict={X: x, Y: y})
    
            # 显示训练中详细信息
            if epoch % display_step == 0:
                loss = sess.run(cost, feed_dict={X: t_X, Y: t_Y})
                print("测试cost:", cost)
                print("测试loss:", loss)
                print("Epoch:", epoch+1, "loss=", loss, "W=", sess.run(W), "b=", sess.run(b))
                if not (loss == "NA"):
                    plotdata["batchsize"].append(epoch)
                    plotdata["loss"].append(loss)
    
        print(" Finsohed!")
        print("loss=", sess.run(cost, feed_dict={X: t_X, Y: t_Y}), "")
        #  4-1保存模型
        saver.save(sess, savedir+"linermodel.cpkt")
    
        # 图形显示
        plt.plot(t_X, t_Y, "go", label="original data")
        plt.plot(t_X, sess.run(W)*t_X+sess.run(b), label="Fitted")
        plt.legend()
        plt.show()
    
        def moving_average(a, w=10):
            if len(a) < w:
                return a[:]
            return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)]
        plotdata["avgloss"] = moving_average(plotdata["loss"])
        # plt.figure(1)
        # plt.subplot(211)
        plt.plot(plotdata["batchsize"], plotdata["avgloss"], "b--")
        plt.xlabel('Minibatch number')
        plt.ylabel('loss')
        plt.title('Minibatch run vs.Training loss')
        plt.show()
    
    # 5.测试模型-1
        print("方式1:", "x= 0.2,z=", sess.run(z, feed_dict={X: 0.2}))
    
    #   测试模型-2
    with tf.Session() as sess2:
        # 从新初始一下变量
        sess2.run(tf.global_variables_initializer())
        saver.restore(sess2, savedir+"linermodel.cpkt")
        print("方式2:", "x= 0.2,z=", sess2.run(z, feed_dict={X: 0.2}))
    # 输出
    
    
    方式1: x= 0.2,z= [0.41271693]
    方式2: x= 0.2,z= [0.41271693]
    
    
    图5
    图6
    图7
    查看模型:
    import tensorflow as tf
    # 从tensorflow.python.tools.inspect_checkpoint 引入 方法 print_tensors_in_checkpoint_file
    from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
    savedir = "Model/"
    # 打印参数
    print_tensors_in_checkpoint_file(savedir +  "linermodel.cpkt",, tensor_name=None, all_tensors=True)
    

    从新的修改参数:

    import tensorflow as tf
    # 从tensorflow.python.tools.inspect_checkpoint 引入 方法 print_tensors_in_checkpoint_file
    from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
    savedir = "Model/"
    # 修改参数
    W = tf.Variable(1.0, name="weight")
    b = tf.Variable(2.0, name="bias")
    saver = tf.train.Saver({'weight': b, 'bias': W})
    
    with tf.Session() as see:
        # 调用方式和以前的不一样
        tf.global_variables_initializer().run()
        # 保存参数
        saver.save(see, savedir + "linermodel.cpkt")
    # 打印参数
    print_tensors_in_checkpoint_file(savedir + "linermodel.cpkt", , tensor_name=None, all_tensors=True)
    

    保存模型注意:
    1.保存模型。由于训练的时间较长,且对内存要求过高,所以在训练的过程中,难免会出现异常,那么怎么样才能,不用多次重复的训练了呢。解决的最简单的办法就是训练几轮后对训练的结果进行保存,所以上面的演示代码是有问题的。修改的结果如下:

    # 每次保存一次的检测点
    saver = tf.train.Saver(max_to_keep=1)
    savedir = "Model/"
    
    if not (loss == "NA"):
        plotdata["batchsize"].append(epoch)
        plotdata["loss"].append(loss)
        # 加上保存的第几次循环
        saver.save(sess, savedir + "linermodel.cpkt", global_step=epoch)
    
    

    2.使用模型的其他方式

    with tf.Session() as sess2:
        # 从新初始一下变量
        sess2.run(tf.global_variables_initializer())
        saver.restore(sess2, savedir+"linermodel.cpkt")
        print("方式2:", "x= 0.2,z=", sess2.run(z, feed_dict={X: 0.2}))
    
    with tf.Session() as sess3:
        sess3.run(tf.global_variables_initializer())
        ckpt = tf.train.get_checkpoint_state(savedir)
        # 判断ckpt 存在
        if ckpt and ckpt.model_checkpoint_path:
            saver.restore(sess3, ckpt.model_checkpoint_path)
            print("方式3:", "x= 0.2,z=", sess3.run(z, feed_dict={X: 0.2}))
    
    with tf.Session() as sess4:
        sess4.run(tf.global_variables_initializer())
        # 检测最后一个文件
        ckpt = tf.train.latest_checkpoint(savedir)
        if ckpt != None:
            saver.restore(sess4, ckpt)
            print("方式4:", "x= 0.2,z=", sess4.run(z, feed_dict={X: 0.2}))
    

    相关文章

      网友评论

          本文标题:【Tensorflow】编程基础

          本文链接:https://www.haomeiwen.com/subject/woldzqtx.html