tf基础

作者: __method__ | 来源:发表于2020-07-05 20:49 被阅读0次

    Tensorflow的运行方式

    Tensorflow作为谷歌开源的深度学习框架,受到众多的人工智能开发人员欢迎。Tensorflow的数据控制单元,张量Tensor是一个可以定义为任意维度的数据,张量的阶Tensor’s rank就是张量的维度,例如:

    零阶张量: 1   一个标量
    一阶张量: [1,2,3]    一个向量 shape 3
    二阶张量: [[1,2,3],[4,5,6]]   一个矩阵 shape 2x3
    三阶张量: [[[1,2,3]],[[4,5,6]]]   shape:2x1x3
    

    Tensorflow的编程主要分为两步,第一步构造计算图(computational Graph),第二步运行计算图。那么计算图是什么呢?
    计算图是一系列由计算操作抽象出来的节点构成的结构,张量(Tensor)在这些节点之间流动运行,由此称该框架为Tensorflow。接下来我们就来介绍一下Tensorflow的基本概念

    Constant常量

    要使用Tensorflow我们首先需要导入该框架

        import tensorflow as tf 
    

    Tensorflow中一个基础的节点类型就是constant,常量节点

        node_A = tf.constant(10,tf.float32)
        node_B = tf.constant(11,tf.int32)
    

    所有的常量类型在定义时,就已经赋予了数值,而且其数值在后面的运行中是无法改变的。

    Session会话

    如果我们直接输出上面定义的两个节点时,例如

        print(node_A,node_B)
    

    我们会得到下面的结果

    Tensor("Const:0", shape=(), dtype=float32) 
    Tensor("Const_1:0", shape=(), dtype=float32)
    

    这里输出的并不是我们想要的10和11,想要输出运行一个节点的结果,必须在一个会话Session中运行计算图,Tensor flow中的session很好的封装了其运行时的状态和控制,接下来我们定义一个会话,输出两个节点的值

        sess = tf.Session()
        a,b = sess.run([node_A,node_B])
        print(a,b)
    

    输出如下:

    10.0 11.0
    

    Op计算节点

    上面我们定义了两个常量节点和会话,并输出了节点的值,我们可以通过定义一些计算操作(Operation、Op)节点,构建更加复杂的计算
    加法:

        node_C = tf.add(node_A,node_B)
        print(sess.run(node_C)) 
    

    输出为

    21.0
    

    乘法:

        node_D = tf.multiply(node_A,node_B)
        print(sess.run(node_D)) 
    

    输出为

    110.0
    

    Placehoder占位符

    上面我们已经熟悉了常量类型以及一些运算符号的操作,Tensorflow的计算图还可以使用占位符placeholder参数化的从外部输入数据,简单来说placehold的作用就是给之后输入的值提前占位,设置这个结构的存在。

        # 这里是构造计算图的部分
        a=tf.placeholder(tf.float32)  
        b=tf.placeholder(tf.float32)  
        adder_node=a+b  
        #运行计算图  
        print("adder_node:",adder_node)  
        print(sess.run(adder_node,{a:3,b:4.5}))  
        print(sess.run(adder_node,{a:[1,3],b:[2,4]}))  
    

    输出结果为:

    adder_node: Tensor("add:0", dtype=float32)
    7.5
    [ 3.  7.]
    

    在我们构建一个神经网络时,通常会为网络的输入输出构建一个placeholder占位符

    Variable变量

    在网络模型中,我们不光有常量类型,计算操作、输入输出占位符等,更多的是大量的变量类型,模型具有可训练能力,需要在一次次训练中修正计算图,使对于同样的输入得到新的输出。变量variable允许我们为计算图添加可变的训练参数
    例如,我们构造一个线性模型

        定义图结构
        W=tf.Variable([.3],tf.float32)  
        b=tf.Variable([-.3],tf.float32)  
        x=tf.placeholder(tf.float32)  
        linear_model=W*x+b  
    
        运行计算图
        init = tf.global_variables_initializer()  
        sess.run(init)  
        print(sess.run(linear_model,{x:[1,2,3,4]}))  
    

    这里的初始化是必要的,与常量类型的定义不同,所有的变量类型在定义时都不会赋予初始值,只有在执行初始化操作时,值才会被赋予变量
    上述代码的输出为:

    [ 0.          0.30000001  0.60000002  0.90000004]
    

    TensorFlow 程序基本框架

    1 准备数据

    import tensorflow as tf
    import matplotlib.pyplot as plt
    import numpy as np
    
    x = np.linspace(-1,1,100)
    y = 2*x+np.random.randn(100)*0.3
    
    plt.plot(x,y)
    
    [<matplotlib.lines.Line2D at 0x7f19750c6780>]
    
    
    image.png
    x_test = np.linspace(-1,1,10)
    y_test = 2*x_test
    
    plt.plot(x_test,y_test)
    
    [<matplotlib.lines.Line2D at 0x7f197503c208>]
    
    
    image.png

    认识一个函数 tf.random_normal

    import tensorflow as tf
    
    W = tf.Variable(tf.random_normal(shape=[1]),name='weight')
    W2 = tf.Variable(tf.random_normal(shape=[2]),name='weight')
    W3 = tf.Variable(tf.random_normal(shape=[2,2]),name='weight')
    init = tf.global_variables_initializer()
    session = tf.Session()
    session.run(init)
    print(session.run(W))
    print(session.run(W2))
    print(session.run(W3))
    
    [-1.0780782]
    [ 1.7330054 -1.1080178]
    [[ 0.5643331   1.7905867 ]
     [-0.03158719 -0.14434654]]
    

    2 搭建模型

    X = tf.placeholder(dtype=tf.float32,shape=None)
    Y = tf.placeholder(dtype=tf.float32,shape=None)
    W = tf.Variable(tf.random_normal(shape=[1]),name='weight')
    b = tf.Variable(tf.zeros(shape=[1]),name='bais')
    z = tf.multiply(W,X)+b
    
    cost = tf.reduce_mean(tf.square(Y-z))  # 求平均值和平方
    learning_rate = 0.01
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cost)
    

    cost = tf.reduce_mean(tf.square(Y-z)) 求计算值z和真实值Y的均方误差

    image.png
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cost)
    

    上面这行代码, 通过梯度下降法,在底层调整权重W和偏置b,使得均方误差cost(也即损失最小)。

    train_epochs = 20
    display_step = 2
    init = tf.global_variables_initializer()
    

    3 迭代模型

    with tf.Session() as sess:
        sess.run(init)
        for epoch in range(train_epochs):
            for (x_s,y_s) in zip(x,y):
                sess.run(optimizer,feed_dict={X:x_s,Y:y_s})
            if epoch%display_step==0:
                loss = sess.run(cost,feed_dict={X:x_test,Y:y_test})
                print('epoch: ',epoch,' loss:',loss)
        print("x=0.2, z=",sess.run(z,feed_dict={X:0.2}))
    
    epoch:  0  loss: 0.9508975
    epoch:  2  loss: 0.071659505
    epoch:  4  loss: 0.0039047264
    epoch:  6  loss: 0.00013607423
    epoch:  8  loss: 9.526675e-05
    epoch:  10  loss: 0.0001471997
    epoch:  12  loss: 0.0001647953
    epoch:  14  loss: 0.00016962932
    epoch:  16  loss: 0.00017089822
    epoch:  18  loss: 0.00017122082
    x=0.2, z= [0.38921914]
    
    计算sess.run的第一个参数所需要的参数由sess.run的第二个参数给出,一般是一个字典。
    
    

    从打印结果可以看出,随着训练批次的增加,网络训练出来了y=2x的线性关系(x=0.2, z= [0.38921914]),同时我们看到损失cost在不断减小。

    4 定义输入节点的方法

    (1) 占位符

    X = tf.placeholder(dtype = tf.float32)
    

    (2) 字典

    input_dict = {'x': tf.placeholder(dtype=tf.float32),'y':tf.placeholder(dtype=tf.float32)}
    

    5 定义学习参数

    (1) 直接定义

    W = tf.Variable(tf.random_normal([1]),name='weight')
    b = tf.Variable(tf.zeros([1]),name='bias')
    

    (2) 字典定义

    para_dict = {'W':tf.Variable(tf.random_normal([1])),'b':tf.Variable(tf.zeros([1]))}
    z = tf.multiply(x,para_dict['W'])+ para_dict['b']
    

    6 初始化所有变量

    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init)
    

    0. 认识一个numpy方法np.newaxis

    np.newaxis的作用就是在这一位置增加一个一维,这一位置指的是np.newaxis所在的位置,比较抽象,需要配合例子理解。
    x1 = np.array([1, 2, 3, 4, 5])
    # the shape of x1 is (5,)
    x1_new = x1[:, np.newaxis]
    # now, the shape of x1_new is (5, 1)
    # array([[1],
    #        [2],
    #        [3],
    #        [4],
    #        [5]])
    x1_new = x1[np.newaxis,:]
    # now, the shape of x1_new is (1, 5)
    # array([[1, 2, 3, 4, 5]])
    

    再来一个例子

    In [124]: arr = np.arange(5*5).reshape(5,5)
    
    In [125]: arr.shape
    Out[125]: (5, 5)
    
    # promoting 2D array to a 5D array
    In [126]: arr_5D = arr[np.newaxis, ..., np.newaxis, np.newaxis]
    
    In [127]: arr_5D.shape
    Out[127]: (1, 5, 5, 1, 1)
    
    

    1.数据准备

    从下图可以看出,变量a为1维的ndarray对象时,a[:, np.newaxis]a.reshape(-1, 1)相同。

    image
    import numpy as np
    
    X = np.linspace(-1, 1, 300)[:, np.newaxis].astype('float32')
    noise = np.random.normal(0, 0.05, X.shape).astype('float32')
    y = np.square(X) - 0.5 + noise
    
    

    第1行代码导入numpy库,起别名np;
    第3行代码调用np.linspace方法获得一个区间内的等间距点,例如np.linspace(0, 1, 11)是获取[0, 1]区间的11个等间距点。如下图所示:

    image

    第4行代码调用np.random.normal方法初始化符合正态分布的点,第1个参数是正态分布的均值,第2个参数是正态分布的方差,第3个参数是返回值的shape,返回值的数据类型为ndarray对象。
    第5行代码调用np.square方法对X中的每一个值求平方,- 0.5使用了ndarray对象的广播特性,最后加上噪声noise,将计算结果赋值给变量y。

    2.搭建神经网络

    import tensorflow as tf 
    
    Weights_1 = tf.Variable(tf.random_normal([1, 10]))
    biases_1 = tf.Variable(tf.zeros([1, 10]) + 0.1)
    Wx_plus_b_1 = tf.matmul(X, Weights_1) + biases_1
    outputs_1 = tf.nn.relu(Wx_plus_b_1)
    Weights_2 = tf.Variable(tf.random_normal([10, 1]))
    biases_2 = tf.Variable(tf.zeros([1, 1]) + 0.1)
    Wx_plus_b_2 = tf.matmul(outputs_1, Weights_2) + biases_2
    outputs_2 = Wx_plus_b_2
    loss = tf.reduce_mean(tf.square(y - outputs_2))
    optimizer = tf.train.AdamOptimizer(0.1)
    train = optimizer.minimize(loss)
    
    

    第1行代码导入tensorflow库,起别名tf;
    第3-6这4行代码定义神经网络中的输入层到第1隐层的连接;
    第7-10这4行代码定义神经网络中的第1隐层到输出层的连接;
    第3、7行代码定义Weights,它的形状是连接上一层神经元的个数*连接下一层神经元的个数
    第4、8行代码定义biases,它是二维矩阵,行数一直为1,列数为连接下一层神经元的个数,即它的形状为1*连接下一层神经元的个数
    第5、9行代码表示wx+b的计算结果;
    第6行代码表示在第1个连接的输出结果,经过激活函数relu得出;
    第10行代码表示在第2个连接的输出结果,因为此连接的下一层是输出层,所以不需要激活函数。
    第11行代码定义损失函数,等同于回归预测中的MSE,中文叫做均方误差,数据类型如下图所示:

    image

    第12行代码调用tf.train库中的AdamOptimizer方法实例化优化器对象,数据类型如下图所示:

    image

    第13行代码调用优化器的minimize方法定义训练方式,参数为损失函数。方法的返回结果赋值给变量train,数据类型如下图所示:

    image

    3.变量初始化

    init = tf.global_variables_initializer()
    session = tf.Session()
    session.run(init)
    
    

    对于神经网络模型,重要是其中的W、b这两个参数。
    开始神经网络模型训练之前,这两个变量需要初始化。
    第1行代码调用tf.global_variables_initializer实例化tensorflow中的Operation对象。

    image

    第2行代码调用tf.Session方法实例化会话对象;
    第3行代码调用tf.Session对象的run方法做变量初始化。

    4.模型训练

    模型训练200次,每运行1次代码session.run(train)则模型训练1次。
    在训练次数为20的整数倍时,打印训练步数、loss值。

    for step in range(201):
        session.run(train)
        if step % 20 == 0:
            print(step, 'loss:', session.run(loss))
    
    

    上面一段代码的运行结果如下:

    > 0 loss: 0.23739298
    > 20 loss: 0.0074774586
    > 40 loss: 0.0032493745
    > 60 loss: 0.0026177235
    > 80 loss: 0.0025075015
    > 100 loss: 0.002472407
    > 120 loss: 0.0024537172
    > 140 loss: 0.002427246
    > 160 loss: 0.002398049
    > 180 loss: 0.002373801
    > 200 loss: 0.002357695
    

    5.完整代码

    下面代码与前文相比,将搭建神经网络时重复定义Weights、biases的步骤封装成了函数。

    import numpy as np
    import tensorflow as tf 
    
    X = np.linspace(-1, 1, 300)[:, np.newaxis].astype('float32')
    noise = np.random.normal(0, 0.05, X.shape).astype('float32')
    y = np.square(X) - 0.5 + noise
    
    def addConnect(inputs, in_size, out_size, activation_function=None):
        Weights = tf.Variable(tf.random_normal([in_size, out_size]))
        biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
        Wx_plus_b = tf.matmul(inputs, Weights) + biases
        if not activation_function:
            return Wx_plus_b
        else:
            return activation_function(Wx_plus_b)
    
    connect_1 = addConnect(X, 1, 10, tf.nn.relu)
    predict_y = addConnect(connect_1, 10, 1)
    loss = tf.reduce_mean(tf.square(y - predict_y))
    optimizer = tf.train.AdamOptimizer(0.1)
    train = optimizer.minimize(loss)
    
    init = tf.global_variables_initializer()
    session = tf.Session()
    session.run(init)
    
    for step in range(201):
        session.run(train)
        if step % 20 == 0:
            print(step, 'loss:', session.run(loss))
    
    

    上面一段代码的运行结果如下:

    > 0 loss: 0.28191957
    > 20 loss: 0.011470509
    > 40 loss: 0.0044303066
    > 60 loss: 0.003392854
    > 80 loss: 0.0031887146
    > 100 loss: 0.0030761429
    > 120 loss: 0.0029888747
    > 140 loss: 0.0029117232
    > 160 loss: 0.0028402375
    > 180 loss: 0.0027794265
    > 200 loss: 0.0027436544
    

    6.可视化

    import numpy as np
    import tensorflow as tf
    import matplotlib.pyplot as plt
    
    X = np.linspace(-1, 1, 300)[:, np.newaxis].astype('float32')
    noise = np.random.normal(0, 0.05, X.shape).astype('float32')
    y = np.square(X) - 0.5 + noise
    
    
    def addConnect(inputs, in_size, out_size, activation_function=None):
        Weights = tf.Variable(tf.random_normal([in_size, out_size]))
        biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
        Wx_plus_b = tf.matmul(inputs, Weights) + biases
        if not activation_function:
            return Wx_plus_b
        else:
            return activation_function(Wx_plus_b)
    
    
    layer_1 = addConnect(X, 1, 10, tf.nn.relu)
    predict_y = addConnect(layer_1, 10, 1)
    loss = tf.reduce_mean(tf.square(y - predict_y))
    optimizer = tf.train.AdamOptimizer(0.1)
    train = optimizer.minimize(loss)
    
    init = tf.global_variables_initializer()
    session = tf.Session()
    session.run(init)
    
    
    
    for step in range(151):
        session.run(train)
        if step == 150:
            predict_value = session.run(predict_y)
            ax = plt.subplot(111)
            ax.scatter(X, y)
            plt.ylim(-0.65, 0.65)
    
            lines = ax.plot(X, predict_value, 'r-', lw=5)
            plt.title('step: %d loss: %.4f' % (step, session.run(loss)))
            plt.show()
    

    可视化部分截图:

    image

    相关文章

      网友评论

          本文标题:tf基础

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