TensorFlow 高级函数

来自CloudWiki
跳转至: 导航搜索

软件环境

Ubuntu 16.04.1 LTS 64 位

隐含层、输入层和输出层

隐含层,指除输入、输出层外,的中间层。输入、输出层对外可见。隐含层对外不可见。理论上,只要隐含层节点足够多,只有一个隐含层,神经网络可以拟合任意函数。隐含层越多,越容易拟合复杂函数。

Tf2-7.png

参考文档:https://www.cnblogs.com/libinggen/p/7221264.html

激活函数

功能说明

神经网络结构的输出为所有输入的加权和,这导致整个神经网络是一个线性模型。如果将每一个神经元的输出通过一个非线性函数,那么整个神经网络的模型也就不再是线性的了,使得神经网络可以更好地解决较为复杂的问题。这个非线性函数也就是激活函数。

神经网络中激活函数的主要作用是提供网络的非线性建模能力,如不特别说明,激活函数一般而言是非线性函数。假设一个示例神经网络中仅包含线性卷积和全连接运算,那么该网络仅能够表达线性映射,即便增加网络的深度也依旧还是线性映射,难以有效建模实际环境中非线性分布的数据。加入(非线性)激活函数之后,深度神经网络才具备了分层的非线性映射学习能力。因此,激活函数是深度神经网络中不可或缺的部分。

从定义来看,几乎所有的连续可导函数都可以用作激活函数。但目前常见的多是分段线性和具有指数形状的非线性函数。下文将依次对它们进行总结。

TensorFlow提供的激活函数有:

详见官方文档

1、tf.nn.relu(features, name=None)
2、tf.nn.relu6(features, name=None)
3、tf.nn.softplus(features, name=None)
4、tf.nn.dropout(x, keep_prob, noise_shape=None, seed=None, name=None)
5、tf.nn.bias_add(value, bias, name=None)
6、tf.sigmoid(x, name=None)
7、tf.tanh(x, name=None)

除了上述的激活函数,TensorFlow当然还可以自定义激活函数

在神经网络中,激活函数的作用是能够给神经网络加入一些非线性因素,使得神经网络可以更好地解决较为复杂的问题。

常见的激活函数有Sigmoid,Relu,tanh等。


relu激活函数可以参考 CS231n: Convolutional Neural Networks for Visual Recognition

参考文档: https://blog.csdn.net/brucewong0516/article/details/78834332

https://blog.csdn.net/jiaoyangwm/article/details/79247434

https://blog.csdn.net/DaVinciL/article/details/75313391

relu激活函数

参数列表

tf.nn.relu

参数名 	必选 	类型 	说明
features 	是 	tensor 	是以下类型float32, float64, int32, int64, uint8, int16, int8, uint16, half
name 	否 	string 	运算名称


relu(
    features,
    name=None
)

示例代码

现在您可以在 /home/ubuntu 目录下创建源文件 relu.py,内容可参考:

示例代码:/home/ubuntu/relu.py


import tensorflow as tf

a = tf.constant([1,-2,0,4,-5,6])
b = tf.nn.relu(a)
with tf.Session() as sess:
    print (sess.run(b))

然后执行:

cd /home/ubuntu;

python relu.py

执行结果:

[1 0 0 4 0 6]

损失函数

什么是损失函数

损失函数:用来表示预测值(y)与已知答案(y_)的差距。在训练神经网络是,通过不断改变神经网络中所有参数,使损失函数不断减小,从而训练出更高的准确率的神经网络模型。常用的损失函数有均方误差、自定义和交叉熵等。

均方误差损失函数

均方误差mse:预测值y与已知答案y_之差的平方和,再求平均值。在TensorFlow中,用loss_mes = tf.reduce_mean(tf.square(y_-y))

例如:

预测酸奶日销量y,x1和x2是影响日销量的两个因素。
       应以前采取的数据有:一段时间内,每日的x1因素、x2因素和销量y_。采集的数据尽量多。
       在本例中,销量预测产量,最优的产量应该等于销量。由于目前没有数据集,所以拟造了一套数据集。利用TensorFlow中函数随机生成x1、x2,制造表中答案y_ = x1 + x2,为了更真实,求和后还加了正负0.05的随机噪声。

源码:

#coding:utf-8
    #预测多或预测少的影响一样
    #0 导入模块,生成数据集
    import tensorflow as tf
    import numpy as np
    BATCH_SIZE = 8
    SEED = 23455
     
    rdm = np.random.RandomState(SEED)
    X = rdm.rand(32,2)
    Y = [[x1+x2+(rdm.rand()/10.0-0.05)] for (x1, x2) in X]
     
    #1 定义神经网络的输入、参数和输出,定义前向传播过程
    x = tf.placeholder(tf.float32, shape=(None, 2))
    y_= tf.placeholder(tf.float32, shape=(None, 1))
     
    w1 = tf.Variable(tf.random_normal([2,1], stddev=1, seed=1))
     
    y = tf.matmul(x,w1)
     
    #2 定义损失函数及反响传播方法
    #定义损失函数为MES,反响传播方法为梯度下降
    loss_mes = tf.reduce_mean(tf.square(y_-y))
    train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss_mes)
     
    #3 生成会话,训练STEPS轮
    with tf.Session() as sess:
        init_op = tf.global_variables_initializer()
        sess.run(init_op)
        STEPS = 20000
        for i in range(STEPS):
            start = (i*BATCH_SIZE) % 32
            end = start + BATCH_SIZE
            sess.run(train_step, feed_dict={x:X[start:end], y_:Y[start:end]})
            if i % 500 == 0:
                print "After %d training steps, w1 is: " %i
                print sess.run(w1)
     
        print "Finam w1 is: \n", sess.run(w1)
     
    """
    Finam w1 is: 
    [[0.98019385]
     [1.0159807 ]]
    """
       可以看到,神经网络模型得到最终参数w1=0.98,w2=1.02,销售预测结果为y=0.98*x1+1.02*x2。由于在生成数据集时,标准答案为y=x1+x2,因此,销售量预测结果和标准答案已经非常接近,说明该神经网络预测酸奶销售量正确。

交叉熵计算函数

交叉熵(cross_entropy),它描述了两个概率分布之间的距离,当交叉熵越小说明二者之间越接近。它是分类问题中使用比较广的一种损失函数。

T1-12.png

y 是我们预测的概率分布, y' 是实际的分布(我们输入的one-hot vector)。比较粗糙的理解是,交叉熵是用来衡量我们的预测用于描述真相的低效性。更详细的关于交叉熵的解释超出本教程的范畴,但是你很有必要好好理解它。

tf.nn.sigmoid_cross_entropy_with_logits


sigmoid_cross_entropy_with_logits(
    _sentinel=None,
    labels=None,
    logits=None,
    name=None
)

常用交叉熵函数

以下交叉熵计算函数输入中的logits都不是softmax或sigmoid的输出,因为它在函数内部进行了sigmoid或softmax操作

tf.nn.sigmoid_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, name=None)

它对于输入的logits先通过sigmoid函数计算,再计算它们的交叉熵,但是它对交叉熵的计算方式进行了优化,使得结果不至于溢出
它适用于每个类别相互独立但互不排斥的情况:例如一幅图可以同时包含一条狗和一只大象

tf.nn.softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, dim=-1, name=None)

它对于输入的logits先通过softmax函数计算
它适用于每个类别相互独立且排斥的情况,一幅图只能属于一类,而不能同时包含一条狗和一只大象

tf.nn.sparse_softmax_cross_entropy_with_logits(_sentinel=None, labels=None, logits=None, name=None)

它适用于每个类别相互独立且排斥的情况,一幅图只能属于一类,而不能同时包含一条狗和一只大象

tf.nn.weighted_cross_entropy_with_logits(labels, logits, pos_weight, name=None)

计算具有权重的sigmoid交叉熵sigmoid_cross_entropy_with_logits()

参考文档:https://blog.csdn.net/qw_sunny/article/details/68960838

交叉熵函数sigmoid_cross_entropy_with_logits

功能说明

先对 logits 通过 sigmoid 计算,再计算交叉熵,交叉熵代价函数可以参考 CS231n: Convolutional Neural Networks for Visual Recognition


参数列表

参数名 	必选 	类型 	说明
_sentinel 	否 	None 	没有使用的参数
labels 	否 	Tensor 	type, shape 与 logits相同
logits 	否 	Tensor 	type 是 float32 或者 float64
name 	否 	string 	运算名称


示例代码

现在您可以在 /home/ubuntu 目录下创建源文件 sigmoid_cross_entropy_with_logits.py:

示例代码:/home/ubuntu/sigmoid_cross_entropy_with_logits.py

import tensorflow as tf
x = tf.constant([1,2,3,4,5,6,7],dtype=tf.float64)
y = tf.constant([1,1,1,0,0,1,0],dtype=tf.float64)
loss = tf.nn.sigmoid_cross_entropy_with_logits(labels = y,logits = x)
with tf.Session() as sess:
    print (sess.run(loss))

然后执行:

cd /home/ubuntu;

python sigmoid_cross_entropy_with_logits.py

执行结果:

[  3.13261688e-01   1.26928011e-01   4.85873516e-02   4.01814993e+00
   5.00671535e+00   2.47568514e-03   7.00091147e+00]

防止过拟合函数

过拟合

所谓过拟合(over-fitting)其实就是所建的机器学习模型或者是深度学习模型在训练样本中表现得过于优越,导致在验证数据集以及测试数据集中表现不佳。

Tf2-11.png

打个比喻就是当我需要建立好一个模型之后,比如是识别一只狗狗的模型,我需要对这个模型进行训练。恰好,我训练样本中的所有训练图片都是二哈,那么经过多次迭代训练之后,模型训练好了,并且在训练集中表现得很好。基本上二哈身上的所有特点都涵括进去,那么问题来了!假如我的测试样本是一只金毛呢?将一只金毛的测试样本放进这个识别狗狗的模型中,很有可能模型最后输出的结果就是金毛不是一条狗(因为这个模型基本上是按照二哈的特征去打造的)。所以这样就造成了模型过拟合,虽然在训练集上表现得很好,但是在测试集中表现得恰好相反,在性能的角度上讲就是协方差过大(variance is large),同样在测试集上的损失函数(cost function)会表现得很大。

参考文档:https://blog.csdn.net/qq_18254385/article/details/78428887

什么是DropOut

dropout是指在深度学习网络的训练过程中避免过拟合的一种方法,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。

Tf2-10.PNG

dropout于2012年ImageNet比赛的获胜模型AlexNet论文中首次提出的避免过拟合的方法。其操作方法如下图所示。

  • 在训练中以概率P(一般为50%)关掉一部分神经元,如图中的虚线的箭头。那么对于某些输出,并不是所有神经元会参与到前向和反向传播中。
  • 在预测的时候,将使用所有的神经元,但是会将其输出乘以0.5

参考文档:https://www.cnblogs.com/JimmyTY/p/5576951.html

功能说明

原理可参考 CS231n: Convolutional Neural Networks for Visual Recognition


参数列表

dropout(
    x,
    keep_prob,
    noise_shape=None,
    seed=None,
    name=None
)
参数名 	必选 	类型 	说明
x 	是 	tensor 	输出元素是 x 中的元素以 keep_prob 概率除以 keep_prob,否则为 0
keep_prob 	是 	scalar Tensor 	dropout 的概率,一般是占位符
noise_shape 	否 	tensor 	默认情况下,每个元素是否 dropout 是相互独立。如果指定 noise_shape,若 noise_shape[i] == shape(x)[i],该维度的元素是否 dropout 是相互独立,若 noise_shape[i] != shape(x)[i] 该维度元素是否 dropout 不相互独立,要么一起 dropout 要么一起保留
seed 	否 	数值 	如果指定该值,每次 dropout 结果相同
name 	否 	string 	运算名称


示例代码

现在您可以在 /home/ubuntu 目录下创建源文件 dropout.py,内容可参考:

示例代码:/home/ubuntu/dropout.py


import tensorflow as tf

a = tf.constant([1,2,3,4,5,6],shape=[2,3],dtype=tf.float32)
b = tf.placeholder(tf.float32)
c = tf.nn.dropout(a,b,[2,1],1)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    print (sess.run(c,feed_dict={b:0.75}))

然后执行:

cd /home/ubuntu;

python dropout.py

执行结果:

[[ 0.          0.          0.        ]
 [ 5.33333349  6.66666651  8.        ]]

卷积函数

tf.nn.conv2d


conv2d(
    input,
    filter,
    strides,
    padding,
    use_cudnn_on_gpu=True,
    data_format='NHWC',
    name=None
)

功能说明:

卷积的原理可参考 A guide to convolution arithmetic for deep learning

参数列表:

参数名 	必选 	类型 	说明
input 	是 	tensor 	是一个 4 维的 tensor,即 [ batch, in_height, in_width, in_channels ](若 input 是图像,[ 训练时一个 batch 的图片数量, 图片高度, 图片宽度, 图像通道数 ])
filter 	是 	tensor 	是一个 4 维的 tensor,即 [ filter_height, filter_width, in_channels, out_channels ](若 input 是图像,[ 卷积核的高度,卷积核的宽度,图像通道数,卷积核个数 ]),filter 的 in_channels 必须和 input 的 in_channels 相等
strides 	是 	列表 	长度为 4 的 list,卷积时候在 input 上每一维的步长,一般 strides[0] = strides[3] = 1
padding 	是 	string 	只能为 " VALID "," SAME " 中之一,这个值决定了不同的卷积方式。VALID 丢弃方式;SAME:补全方式
use_cudnn_on_gpu 	否 	bool 	是否使用 cudnn 加速,默认为 true
data_format 	否 	string 	只能是 " NHWC ", " NCHW ",默认 " NHWC "
name 	否 	string 	运算名称

conv2d

示例代码:

现在您可以在 /home/ubuntu 目录下创建源文件 conv2d.py,内容可参考:

示例代码:/home/ubuntu/conv2d.py

import tensorflow as tf

a = tf.constant([1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,1,1,0,0,1,1,0,0],dtype=tf.float32,shape=[1,5,5,1])
b = tf.constant([1,0,1,0,1,0,1,0,1],dtype=tf.float32,shape=[3,3,1,1])
c = tf.nn.conv2d(a,b,strides=[1, 2, 2, 1],padding='VALID')
d = tf.nn.conv2d(a,b,strides=[1, 2, 2, 1],padding='SAME')
with tf.Session() as sess:
    print ("c shape:")
    print (c.shape)
    print ("c value:")
    print (sess.run(c))
    print ("d shape:")
    print (d.shape)
    print ("d value:")
    print (sess.run(d))

然后执行:

cd /home/ubuntu;

python conv2d.py

执行结果:

c shape:
(1, 3, 3, 1)
c value:
[[[[ 4.]
   [ 3.]
   [ 4.]]

  [[ 2.]
   [ 4.]
   [ 3.]]

  [[ 2.]
   [ 3.]
   [ 4.]]]]
d shape:
(1, 5, 5, 1)
d value:
[[[[ 2.]
   [ 2.]
   [ 3.]
   [ 1.]
   [ 1.]]

  [[ 1.]
   [ 4.]
   [ 3.]
   [ 4.]
   [ 1.]]

  [[ 1.]
   [ 2.]
   [ 4.]
   [ 3.]
   [ 3.]]

  [[ 1.]
   [ 2.]
   [ 3.]
   [ 4.]
   [ 1.]]

  [[ 0.]
   [ 2.]
   [ 2.]
   [ 1.]
   [ 1.]]]]


池化函数

tf.nn.max_pool


max_pool(
    value,
    ksize,
    strides,
    padding,
    data_format='NHWC',
    name=None
)


功能说明

池化的原理可参考 CS231n: Convolutional Neural Networks for Visual Recognition


参数列表

参数名 	必选 	类型 	说明
value 	是 	tensor 	4 维的张量,即 [ batch, height, width, channels ],数据类型为 tf.float32
ksize 	是 	列表 	池化窗口的大小,长度为 4 的 list,一般是 [1, height, width, 1],因为不在 batch 和 channels 上做池化,所以第一个和最后一个维度为 1
strides 	是 	列表 	池化窗口在每一个维度上的步长,一般 strides[0] = strides[3] = 1
padding 	是 	string 	只能为 " VALID "," SAME " 中之一,这个值决定了不同的池化方式。VALID 丢弃方式;SAME:补全方式
data_format 	否 	string 	只能是 " NHWC ", " NCHW ",默认" NHWC "
name 	否 	string 	运算名称


示例代码

现在您可以在 /home/ubuntu 目录下创建源文件 max_pool.py,内容可参考:

示例代码:/home/ubuntu/max_pool.py

import tensorflow as tf

a = tf.constant([1,3,2,1,2,9,1,1,1,3,2,3,5,6,1,2],dtype=tf.float32,shape=[1,4,4,1])
b = tf.nn.max_pool(a,ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1],padding='VALID')
c = tf.nn.max_pool(a,ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1],padding='SAME')
with tf.Session() as sess:
    print ("b shape:")
    print (b.shape)
    print ("b value:")
    print (sess.run(b))
    print ("c shape:")
    print (c.shape)
    print ("c value:")
    print (sess.run(c))

然后执行:

cd /home/ubuntu;

python max_pool.py

执行结果:

b shape:
(1, 2, 2, 1)
b value:
[[[[ 9.]
   [ 2.]]

  [[ 6.]
   [ 3.]]]]
c shape:
(1, 2, 2, 1)
c value:
[[[[ 9.]
   [ 2.]]

  [[ 6.]
   [ 3.]]]]