• TensorFlow机器学习实战指南之第二章


    一、计算图中的操作

    在这个例子中,我们将结合前面所学的知识,传入一个列表到计算图中的操作,并打印返回值:

    声明张量和占位符。这里,创建一个numpy数组,传入计算图操作:

    import tensorflow as tf
    import numpy as np
    
    # Create graph
    sess = tf.Session()
    # Create data to feed in
    x_vals = np.array([1., 3., 5., 7., 9.])
    x_data = tf.placeholder(tf.float32)
    m = tf.constant(3.)
    # Multiplication
    prod = tf.multiply(x_data, m)
    for x_val in x_vals:
        print(sess.run(prod, feed_dict={x_data: x_val}))

    输出:

    3.0
    9.0
    15.0
    21.0
    27.0

    在下面这个例子中,我们将学习如何在同一个计算图中进行多个乘法操作。

    下面我们将用两个矩阵乘以占位符,然后做加法。传入两个矩阵(三维numpy数组):

    我们将传入两个形状为3×5的numpy数组,然后
    每个矩阵乘以常量矩阵(形状为:5×1),将返回一个形状为3×1的矩阵。紧接着再乘以1×1的矩阵,返回的
    结果矩阵仍然为3×1。最后,加上一个3×1的矩阵,示例如下:

    1.首先,创建数据和占位符:

    # Create graph
    sess = tf.Session()
    # Create data to feed in
    my_array = np.array([[1., 3., 5., 7., 9.],
                         [-2., 0., 2., 4., 6.],
                         [-6., -3., 0., 3., 6.]])
    x_vals = np.array([my_array, my_array + 1])
    x_data = tf.placeholder(tf.float32, shape=(3, 5))

    2.接着,创建矩阵乘法和加法中要用到的常量矩阵:

    m1 = tf.constant([[1.],[0.],[-1.],[2.],[4.]])
    m2 = tf.constant([[2.]])
    a1 = tf.constant([[10.]])

    3.现在声明操作,表示成计算图:

    # 1st Operation Layer = Multiplication
    prod1 = tf.matmul(x_data, m1)
    
    # 2nd Operation Layer = Multiplication
    prod2 = tf.matmul(prod1, m2)
    
    # 3rd Operation Layer = Addition
    add1 = tf.add(prod2, a1)

    4.最后,通过计算图赋值:

    for x_val in x_vals:
        print(sess.run(add1, feed_dict={x_data: x_val}))

    输出:

    [[102.]
     [ 66.]
     [ 58.]]
    [[114.]
     [ 78.]
     [ 70.]]

    在我们通过计算图运行数据之前心里要有个数:声明数据形状,预估操作返回值形状。由于预先不知道
    或者维度在变化,情况也可能发生变化。为了实现目标,我们指明变化的维度,或者事先不知道的维度设为
    none。例如,占位符有未知列维度,使用方式如下:

    x_data = tf.placeholder(tf.float32,shape=(3,None))

    二、TensorFlow的多层Layer

    1.首先,通过numpy创建2D图像,4×4像素图片。我们将创建成四维:第一维和最后一维大小为1。注
    意,TensorFlow的图像函数是处理四维图片的,这四维是:图片数量、高度、宽度和颜色通道。这里是一张
    图片,单颜色通道,所以设两个维度值为1:

    # Create graph
    sess = tf.Session()
    
    # Create a small random 'image' of size 4x4
    x_shape = [1, 4, 4, 1]
    x_val = np.random.uniform(size=x_shape)

    2.下面在计算图中创建占位符。此例中占位符是用来传入图片的,代码如下:

    x_data = tf.placeholder(tf.float32, shape=x_shape)

    3.为了创建过滤4×4像素图片的滑动窗口,我们将用TensorFlow内建函数conv2d()(常用来做图像处
    理)卷积2×2形状的常量窗口。conv2d()函数传入滑动窗口、过滤器和步长。本例将在滑动窗口四个方向
    上计算,所以在四个方向上都要指定步长。创建一个2×2的窗口,每个方向长度为2的步长。为了计算*均
    值,我们将用常量为0.25的向量与2×2的窗口卷积,代码如下:

    my_filter = tf.constant(0.25, shape=[2, 2, 1, 1])
    my_strides = [1, 2, 2, 1]
    mov_avg_layer = tf.nn.conv2d(x_data, my_filter, my_strides,
                                 padding='SAME', name='Moving_Avg_Window')

    4.注意,我们通过conv2d()函数的name参数,把这层Layer命名为“Moving_Avg_Window”。

    5.现在定义一个自定义Layer,操作滑动窗口*均的2×2的返回值。自定义函数将输入张量乘以一个2×2
    的矩阵张量,然后每个元素加1。因为矩阵乘法只计算二维矩阵,所以剪裁图像的多余维度(大小为1)。
    TensorFlow通过内建函数squeeze()剪裁。下面是新定义的Layer:

    def custom_layer(input_matrix):
        input_matrix_sqeezed = tf.squeeze(input_matrix)
        A = tf.constant([[1., 2.], [-1., 3.]])
        b = tf.constant(1., shape=[2, 2])
        temp1 = tf.matmul(A, input_matrix_sqeezed)
        temp = tf.add(temp1, b) # Ax + b
        return(tf.sigmoid(temp))

    6.现在把刚刚新定义的Layer加入到计算图中,并且用tf.name_scope()命名唯一的Layer名字,后续在
    计算图中可折叠/扩展Custom_Layer层,代码如下:

    # Add custom layer to graph
    with tf.name_scope('Custom_Layer') as scope:
        custom_layer1 = custom_layer(mov_avg_layer)

    7.为占位符传入4×4像素图片,然后执行计算图,代码如下:

    print(sess.run(custom_layer1, feed_dict={x_data: x_val}))

    输出:

    [[0.9027293  0.9333066 ]
     [0.84296674 0.8839635 ]]

    三、TensorFlow实现损失函数

    损失函数(loss function)对机器学习来讲是非常重要的。它们度量模型输出值与目标值(target)间的
    差值。本节会介绍TensorFlow中实现的各种损失函数。

    为了优化机器学习算法,我们需要评估机器学习模型训练输出结果。在TensorFlow中评估输出结果依赖
    损失函数。损失函数告诉TensorFlow,预测结果相比期望的结果是好是坏。在大部分场景下,我们会有算法
    模型训练的样本数据集和目标值。损失函数比较预测值与目标值,并给出两者之间的数值化的差值。

    为了比较不同损失函数的区别,我们将会在图表中绘制出来。先创建计算图,然后加载
    matplotlib(Python的绘图库),代码如下:

    import matplotlib.pyplot as plt
    import tensorflow as tf

    首先,将讲解回归算法的损失函数。回归算法是预测连续因变量的。创建预测序列和目标序列作为张
    量,预测序列是-1到1之间的等差数列,代码如下:

    # Numerical Predictions 
    x_vals = tf.linspace(-1., 1., 500)
    target = tf.constant(0.)

    1.回归模型的损失函数

    (1)L2正则损失函数(即欧拉损失函数)。L2正则损失函数是预测值与目标值差值的*方和。注意,上述
    例子中目标值为0。L2正则损失函数是非常有用的损失函数,因为它在目标值附*有更好的曲度,机器学习
    算法利用这点收敛,并且离目标越*收敛越慢,代码如下:

    # L2 loss
    # L = (pred - actual)^2
    l2_y_vals = tf.square(target - x_vals)
    l2_y_out = sess.run(l2_y_vals)

    注意:

    TensorFlow有内建的L2正则形式,称为nn.l2_loss()。这个函数其实是实际L2正则
    的一半,换句话说,它是上面l2_y_vals的1/2。

    (2)L1正则损失函数(即绝对值损失函数)。与L2正则损失函数对差值求*方不同的是,L1正则损失函数
    对差值求绝对值。L1正则在目标值附*不*滑,这会导致算法不能很好地收敛。代码如下:

    # L1 loss
    # L = abs(pred - actual)
    l1_y_vals = tf.abs(target - x_vals)
    l1_y_out = sess.run(l1_y_vals)

    (3)Pseudo-Huber 损失函数

    Pseudo-Huber损失函数是Huber损失函数的连续、*滑估计,试图利用L1和L2正则削减极值处的陡峭,
    使得目标值附*连续。它的表达式依赖参数delta。我们将绘图来显示delta1=0.25和delta2=5的区别

    Huber损失函数经常用于回归问题,它是分段函数,公式如下:

    从这个公式可以看出当残差(预测值与目标值的差值,即y-f(x) )很小的时候,损失函数为L2范数,残差大的时候,为L1范数的线性函数。

    Peseudo-Huber损失函数是Huber损失函数的连续、*滑估计,在目标附*连续,公式如下:

    该公式依赖于参数delta,delta越大,则两边的线性部分越陡峭。

    # Pseudo-Huber loss
    # L = delta^2 * (sqrt(1 + ((pred - actual)/delta)^2) - 1)
    delta1 = tf.constant(0.25)
    phuber1_y_vals = tf.multiply(tf.square(delta1), tf.sqrt(1. + tf.square((target - x_vals) / delta1)) - 1.)
    phuber1_y_out = sess.run(phuber1_y_vals)
    
    delta2 = tf.constant(5.)
    phuber2_y_vals = tf.mul(tf.square(delta2), tf.sqrt(1. + tf.square((target - x_vals) / delta2)) - 1.)
    phuber2_y_out = sess.run(phuber2_y_vals)

    以下为L1、L2、Huber损失函数的对比图如下,其中Huber的delta取0.25、5两个值:

    x_array = sess.run(x_vals)
    plt.plot(x_array, l2_y_out, 'b-', label='L2 Loss')
    plt.plot(x_array, l1_y_out, 'r--', label='L1 Loss')
    plt.plot(x_array, phuber1_y_out, 'k-.', label='P-Huber Loss(0.25)')
    plt.plot(x_array, phuber2_y_out, 'g:', label='P-Huber Loss(5.)')
    plt.ylim(-0.2, 0.4)
    plt.legend(loc='lower right', prop={'size': 11})
    plt.show()

    2.分类模型的损失函数

    分类损失函数主要用于评估预测分类结果,重新定义预测值(-3至5的等差序列)和目标值(目标值为1),如下:

    y_pred=tf.linspace(-3., 5., 100)
    
    y_target=tf.constant(1.)
    
    y_targets=tf.fill([100, ], 1.)

    (1)Hinge损失函数

    Hinge损失常用于二分类问题,主要用来评估向量机算法,但有时也用来评估神经网络算法,公式如下:

    loss_hinge_vals = tf.maximum(0., 1. – tf.mul(y_target, y_pred))
    
    loss_hinge_out = sess.run(loss_hinge_vals)

     (2)两类交叉熵(Cross-entropy)损失函数

    交叉熵来自于信息论,是分类问题中使用广泛的损失函数。交叉熵刻画了两个概率分布之间的距离,当两个概率分布越接*时,它们的交叉熵也就越小,给定两个概率分布p和q,则距离如下:

    对于两类问题,当一个概率p=y,则另一个概率q=1-y,因此代入化简后的公式如下:

    # Cross entropy loss
    # L = -actual * (log(pred)) - (1-actual)(log(1-pred))
    xentropy_y_vals = - tf.multiply(target, tf.log(x_vals)) - tf.multiply((1. - target), tf.log(1. - x_vals))
    xentropy_y_out = sess.run(xentropy_y_vals)

    (3)Sigmoid交叉熵损失函数

    与上面的两类交叉熵类似,只是将预测值y_pred值通过sigmoid函数进行转换,再计算交叉熵损失。

    # Sigmoid entropy loss
    # L = -actual * (log(sigmoid(pred))) - (1-actual)(log(1-sigmoid(pred)))
    # or
    # L = max(actual, 0) - actual * pred + log(1 + exp(-abs(actual)))
    xentropy_sigmoid_y_vals = tf.nn.sigmoid_cross_entropy_with_logits(labels=x_vals, logits=targets)
    xentropy_sigmoid_y_out = sess.run(xentropy_sigmoid_y_vals)

    (4)加权交叉熵损失函数

    加权交叉熵损失函数是Sigmoid交叉熵损失函数的加权,是对正目标的加权。假定权重为0.5,在TensorFlow中的调用方式如下:

    # Weighted (softmax) cross entropy loss
    # L = -actual * (log(pred)) * weights - (1-actual)(log(1-pred))
    # or
    # L = (1 - pred) * actual + (1 + (weights - 1) * pred) * log(1 + exp(-actual))
    weight = tf.constant(0.5)
    xentropy_weighted_y_vals = tf.nn.weighted_cross_entropy_with_logits(x_vals, targets, weight)
    xentropy_weighted_y_out = sess.run(xentropy_weighted_y_vals)

    (5)Softmax交叉熵损失函数

    Softmax交叉熵损失函数是作用于非归一化的输出结果,只针对单个目标分类计算损失。

    通过softmax函数将输出结果转化成概率分布,从而便于输入到交叉熵里面进行计算(交叉熵要求输入为概率),softmax定义如下:

    结合前面的交叉熵定义公式,则Softmax交叉熵损失函数公式如下:

    # Softmax entropy loss
    # L = -actual * (log(softmax(pred))) - (1-actual)(log(1-softmax(pred)))
    unscaled_logits = tf.constant([[1., -3., 10.]])
    target_dist = tf.constant([[0.1, 0.02, 0.88]])
    softmax_xentropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels=unscaled_logits, logits=target_dist)

    用于回归相关的损失函数,对比图如下:

    3.总结

    下面对各种损失函数进行一个总结,如下表所示:

    在实际使用中,对于回归问题经常会使用MSE均方误差(L2取*均)计算损失,对于分类问题经常会使用Sigmoid交叉熵损失函数。

  • 相关阅读:
    iOS中block的探究
    输出IOS 版本号
    Luke's Homepage
    ObjectiveC: delegate的那点事儿
    浅谈XCode编译器的Blocks功能
    一个横版的tableViewFantasyView
    iOS中block的探究
    NSRunLoop 概述和原理
    Block使用中的一些疑问解答
    Flex 中的注释
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/10782374.html
Copyright © 2020-2023  润新知