激活函数(relu,prelu,elu,+BN)对比on cifar10

最近做了个对比实验,通过修改激活函数观察对图片分类准确率的影响,现记录如下:


一.理论基础
1.1激活函数
这里写图片描述

1.2 elu论文(FAST AND ACCURATE DEEP NETWORK LEARNING BY
EXPONENTIAL LINEAR UNITS (ELUS))
1.2.1 摘要
    论文中提到,elu函数可以加速训练并且可以提高分类的准确率。它有以下特征:
1)elu由于其正值特性,可以像relu,lrelu,prelu一样缓解梯度消失的问题。
2)相比relu,elu存在负值,可以将激活单元的输出均值往0推近,达到
batchnormlization的效果且减少了计算量。(输出均值接近0可以减少偏移效应进而使梯
度接近于自然梯度。)
3)Lrelu和prelu虽然有负值存在,但是不能确保是一个噪声稳定的去激活状态。
4)Elu在负值时是一个指数函数,对于输入特征只定性不定量。
1.2.2.bias shift correction speeds up learning
    为了减少不必要的偏移移位效应,做出如下改变:(i)输入单元的激活可以
以零为中心,或(ii)可以使用具有负值的激活函数。 我们介绍一个新的
激活函数具有负值,同时保持正参数的特性,即elus。
1.2.4实验
    作者把elu函数用于无监督学习中的autoencoder和有监督学习中的卷积神经网络;
elu与relu,lrelu,SReLU做对比实验;数据集选择mnist,cifar10,cifar100.

2ALL-CNN for cifar-10
2.1结构设计
这里写图片描述
ALL-CNN结构来自论文(STRIVING FOR SIMPLICITY:
THE ALL CONVOLUTIONAL NET)主要工作是把pool层用stride=2的卷积来代替,提出了一些全卷积网络架构,kernel=3时效果最好,最合适之类的,比较好懂,同时效果也不错,比原始的cnn效果好又没有用到一些比较大的网络结构如resnet等。
附上:

Lrelu实现:
def lrelu(x, leak=0.2, name="lrelu"):
return tf.maximum(x, leak * x)

Prelu实现:
def parametric_relu(_x):
alphas = tf.get_variable('alpha', _x.get_shape()[-1],
initializer=tf.constant_initializer(0.25),
dtype = tf.float32
)
pos = tf.nn.relu(_x)
neg = alphas * (_x - abs(_x)) * 0.5
print(alphas)
return pos + neg

BN实现:     
def batch_norm(x, n_out,scope='bn'):
  """
  Batch normalization on convolutional maps.
  Args:
    x: Tensor, 4D BHWD input maps
    n_out: integer, depth of input maps
    phase_train: boolean tf.Variable, true indicates training phase
    scope: string, variable scope

  Return:
    normed: batch-normalized maps
  """
  with tf.variable_scope(scope):
    beta = tf.Variable(tf.constant(0.0, shape=[n_out]),
      name='beta', trainable=True)
    gamma = tf.Variable(tf.constant(1.0, shape=[n_out]),
      name='gamma', trainable=True)
    tf.add_to_collection('biases', beta)
    tf.add_to_collection('weights', gamma)

    batch_mean, batch_var = tf.nn.moments(x, [0,1,2], name='moments')
    ema = tf.train.ExponentialMovingAverage(decay=0.99)

    def mean_var_with_update():
      ema_apply_op = ema.apply([batch_mean, batch_var])
      with tf.control_dependencies([ema_apply_op]):
       return tf.identity(batch_mean), tf.identity(batch_var)
    #mean, var = control_flow_ops.cond(phase_train,
    # mean, var = control_flow_ops.cond(phase_train,
    #   mean_var_with_update,
    #   lambda: (ema.average(batch_mean), ema.average(batch_var)))
    mean, var = mean_var_with_update()
    normed = tf.nn.batch_normalization(x, mean, var,
      beta, gamma, 1e-3)
  return normed



在cifar10 上测试结果如下:

这里写图片描述

以loss所有结果如下:relu+bn>elu>prelu>elubn>relu
这里写图片描述

所有的测试准确率如下
这里写图片描述
这里写图片描述

relu+bn组合准确率最高,relu+bn>elu>prelu>elubn>relu
可见elu在激活函数里表现最好,但是它不必加BN,这样减少了BN的计算量。

3.ALL-CNN for cifar-100
cifar100数据集
CIFAR-100 python version,下载完之后解压,在cifar-100-python下会出现:meta,test和train
三个文件,他们都是python用cPickle封装的pickled对象
解压:tar -zxvf xxx.tar.gz
cifar-100-python/
cifar-100-python/file.txt~
cifar-100-python/train
cifar-100-python/test
cifar-100-python/meta
def unpickle(file):
import cPickle
fo = open(file, ‘rb’)
dict = cPickle.load(fo)
fo.close()
return dict
通过以上代码可以将其转换成一个dict对象,test和train的dict中包含以下元素:
data——一个nx3072的numpy数组,每一行都是(32,32,3)的RGB图像,n代表图像个数
coarse_labels——一个范围在0-19的包含n个元素的列表,对应图像的大类别
fine_labels——一个范围在0-99的包含n个元素的列表,对应图像的小类别
而meta的dict中只包含fine_label_names,第i个元素对应其真正的类别。
二进制版本(我用的)
<1 x coarse label><1 x fine label><3072 x pixel>

<1 x coarse label><1 x fine label><3072 x pixel>
网络结构直接在cifar10的基础上输出100类即可,只对cifar100的精细标签100个进行分类任务,因此代码里取输入数据集第二个值做为标签。(tensorflow的cifar10代码)

label_bytes =2 # 2 for CIFAR-100
#取第二个标签100维
result.label = tf.cast(
tf.strided_slice(record_bytes, [1], [label_bytes]), tf.int32)

在all CNN 9层上,大约50k步,relu+bn组合测试的cifar100 test error为0.36

<think>好的,我现在需要回答用户关于代码中F.elu(x)的问题。首先,用户可能已经看过之前的代码解释,现在想了解激活函数部分的作用。 首先,我应该回忆一下代码的结构。在STGNN模型中,GATConv层后面跟着F.elu(x),然后第二个GATConv层。用户问的是F.elu(x)是什么,所以需要解释这个函数的作用和为什么在这里使用。 ELU全称是Exponential Linear Unit,即指数线性单元。我应该先给出它的数学表达式,比如ELU(x) = max(0,x) + min(0, α*(exp(x)-1)),其中α通常为1。然后说明它在负区间的非线性特性,帮助缓解梯度消失问题。 接下来需要解释在代码中F.elu(x)的作用。这里可能是在两个GAT层之间加入激活函数,增加非线性,使得模型能够学习更复杂的模式。同时,ELU相比ReLU,在处理负数输入时会有非零输出,可能有助于稳定训练。 还要注意用户可能的背景。他们可能对激活函数有一定了解,但需要具体到ELU和代码中的应用。可能需要比较ELU与其他激活函数(如ReLU、LeakyReLU)的不同,说明为什么在这里选择ELU。 另外,需要结合模型的上下文。例如,在第一个GAT层后使用ELU激活,可能为了在保留特征的同时引入非线性,为后续的GAT层提供更好的输入分布。 最后,要确保回答结构清晰,分点说明,可能包括定义、作用、为什么使用、与其他激活函数对比等。可能还要提到PyTorch中的具体实现,即torch.nn.functional.elu,并注意是否需要参数设置,比如alpha的值,默认是否为1。 需要检查是否有技术细节错误,例如数学公式是否正确,函数名称是否正确,以及是否解释了在深度学习模型中的典型应用场景。可能还需要举一个例子,比如输入经过GAT后的张量,应用ELU后的变化,帮助用户直观理解。 总之,回答需要涵盖定义、作用、代码中的位置、选择理由、与其他激活函数对比,以及实际应用中的注意事项,确保用户不仅知道这是什么,还明白为什么在这里使用它。</think>以下是关于代码中`F.elu(x)`的详细解释: --- ### 一、基本定义 `F.elu(x)`是PyTorch中实现的**指数线性单元激活函数**(Exponential Linear Unit),其数学表达式为: $$ \text{ELU}(x) = \begin{cases} x & \text{if } x \geq 0 \\ \alpha(e^x - 1) & \text{if } x < 0 \end{cases} $$ 其中默认参数$\alpha=1$。在代码中直接使用`torch.nn.functional.elu`无需显式设置参数。 --- ### 二、在代码中的作用 ```python x = F.elu(x) # 位于两个GAT层之间 ``` 1. **引入非线性** - 使模型能够学习复杂的时空图关系 - 打破层间线性变换的局限性 2. **改善梯度流动** - 负值区域具有软饱和特性(对比ReLU的硬截止) - 缓解梯度消失问题,公式推导: $$ \frac{d}{dx}\text{ELU}(x) = \begin{cases} 1 & x \geq 0 \\ \text{ELU}(x) + \alpha & x < 0 \end{cases} $$ 3. **保持特征中心化** - 负值输出均值接近0(对比ReLU的纯非负输出) - 有利于后续图卷积层的特征传播 --- ### 三、与其他激活函数对比 | 激活函数 | 优点 | 缺点 | 适用场景 | |---------|------|------|---------| | **ReLU** | 计算简单 | 神经元死亡问题 | 浅层网络 | | **LeakyReLU** | 缓解死亡问题 | 需要调参 | 深层网络 | | **ELU** | 自归一化特性 | 指数计算耗时 | 需要稳定训练时 | | **GELU** | 符合神经特性 | 计算复杂 | Transformer | --- ### 四、具体应用分析 在示例代码中的工作流程: ```text GATConv1输出 → ELU激活 → GATConv2 ``` 1. **特征转换过程** - 输入:`[batch, 64]`(来自LSTM的最后时间步) - 输出:`[batch, 16]`(经过两次图卷积) 2. **数值示例演示** ```python # 假设GAT1输出包含正负值 gat1_output = tensor([[0.8, -1.2], [2.1, -0.3]]) # 应用ELUelu_output = tensor([[0.8000, -0.6988], # -1.2 → e^{-1.2}-1 ≈ -0.6988 [2.1000, -0.2592]]) # -0.3 → e^{-0.3}-1 ≈ -0.2592 ``` --- ### 五、调参建议 1. **α参数调整**(需显式设置) ```python x = F.elu(x, alpha=0.7) # 更平缓的负值区域 ``` 2. **与批归一化配合使用** ```python self.bn = nn.BatchNorm1d(32) x = self.gat1(x, edge_index) x = self.bn(x) x = F.elu(x) ``` 3. **监控激活分布** ```python print(torch.mean(x)) # 理想值接近0 print(torch.min(x)) # 应大于-1(当α=1时) ``` --- ### 六、可视化理解 ![ELU激活函数示意图](https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/ELU_activation_function.svg/1280px-ELU_activation_function.svg.png) (示意图说明:左侧为ELU函数曲线,右侧为其导数。注意负数区域的平滑过渡特性) --- 通过这种设计,模型能够在图神经网络的传播过程中更好地保持特征信息的完整性和可区分性,特别适用于需要捕获复杂时空依赖关系的工业故障检测场景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值