卷积神经网络(CNN)激活函数的设置

 

@author tanggy

 

 

  • 前言
  • Java代码中如何更改激活函数
  1. 更改前向传播forward()中卷积层激活函数。
  2. 更改输出层梯度计算公式
  3. 反向传播求激活函数微分
  • 激活函数与标签值的修改

 

 

一、前言:

 

本文探讨在卷积神经网络结构中,如何去处理激活函数的问题。

1、如何在前向传播的时候更改卷积层的激活函数。

2、对输出层损失函数梯度求解时,因输出层激活函数选择不同,梯度会产生变化,并如何正确修改。

3、对于反向传播的时候,根据激活函数的不同,对应反向传播的梯度公式会发生变化。

 

 

https://i-blog.csdnimg.cn/blog_migrate/cce5342e2c4bcc958b63f150c13cf04f.png

图片 1

 

java代码为例,一个神经网络 包含一个输入层、两个卷积层,两个池化层、一个全连接层。

 

LayerBuilder builder = new LayerBuilder();

builder.addLayer(Layer.buildInputLayer(new Size(28,28)));

builder.addLayer(Layer.buildConvLayer(6, new Size(5, 5)));

builder.addLayer(Layer.buildSampLayer(new Size(2, 2)));

builder.addLayer(Layer.buildConvLayer(12, new Size(5, 5)));

builder.addLayer(Layer.buildSampLayer(new Size(2, 2)));

builder.addLayer(Layer.buildOutputLayer(10));//输出层;

CNN cnn = new CNN(builder, 10);

 

Learningrate = 0.85, batchSize = 10。采用mnist数据集测试

 

首先对两个卷积层设置激活函数为sigmoid激活函数     

// 设置激活函数

layer.setActivation(new Sigmoid());

再设置输出层激活函数为tanh激活函数

// 设置激活函数

layer.setActivation(new Tanh());

 

这里注意最后一层tanh激活函数取值范围为 -1~1;(而我们之前用的是sigmoid,取值范围为0~1)

 

 

 

 

 

 

 

 

二、Java代码中如何更改激活函数

 

1、更改前向传播forward()中卷积层激活函数。

 

首先是输出层第L层。注意到输出层的W,b满足下式:

 

aL = σ(zL) = σ(WLaL-1 + bL)

 

注:σ表示当前层激活函数、W为权值、b为偏置。

 

``Java

final double bias = layer.getBias(j);

sum = Util.matrixOp(sum, new Operator() {

  private static final long serialVersionUID = 2469461972825890810L;

                  

  @Override

  public double process(double value) {

      return layer.getActivation().active(value + bias);

  }

                  

});

``

这里卷积层我们采用了sigmoid激活函数,这里激活公式为:

 

  1. / (1 + Math.pow(Math.E, -x))

 

 

2、更改输出层梯度计算公式

 

这里我们采用的是均方差计算公式。

 

Lost = ||a-y||2/2;

 

a = σ(z);

 

这里均方差代价函数求导得到

 

F‘(x) = (a-y)σ’(z);

 

根据求导结果,我们只要知道激活函数的导数,我们就能求出输出层的梯度了。

而这里的梯度是我预先设定好的。

 

``Java

double gradient = outputLayer.getActivation().gradient(outmaps[m]);

            

outputLayer.setError(m, 0, 0, gradient*(target[m] - outmaps[m])); //sigmoid

 

``

 

 

3、反向传播求激活函数微分

 

只是更改前向传播是不够的。反向传播求梯度时,会因激活函数选择不同,梯度公式也会产生变化。

   

    Output = f……(g(z));

 

 

前向传播通过复杂的函数映射计算出最后的output,而我们采用梯度下降法,去寻找合适的那个映射,所以我们根据这个复杂的映射求微分。

 

Gradient = F’g’(z);

 

而这里采用最大值池化以及sigmoid激活函数;

所以求导结果应该是

 

Gradient = σ‘(x)*Max’∑1nai

 

也就是激活函数的与最大池化导数Hadamard乘积。

 

``Java

outMatrix = Util.matrixOp(map, new Operator() {

                        

    private static final long serialVersionUID = 1L;

 

    @Override

    public double process(double value) {

        return layer.getActivation().gradient(value);

    }

                        

});

                    

 //这里的输出结果应该除以scale(卷积核面积)

outMatrix = Util.matrixOp(outMatrix,

    Util.kronecker(nextError, scale, sampPos), null, null, Util.multiply);

``

 

 

 

  • 激活函数与标签值的修改

 

这里最后一层选取激活函数的时候需要注意一个点。

因为sigmoid取值范围为0~1,我们标签值也是1.所以能契合sigmoid函数。

但是当我们改为tanh激活函数的时候,tanh取值范围为-1~1.所以为了契合标签值,我将tanh函数,以及它的梯度做了个变化。 à 0.5x + 0.5;梯度变为原先的1/2,然后发现也是能正确运行的。

 

待解决:

Q:如果我不对激活函数但是我更改标签值的时候发现,我将标签改为2.然后我发现无法得到正确结果。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值