尝试了一种新的激活函数(灭活函数),似乎效果还不错

这几天用神经网络做一个数据逼近,想用来在嵌入式系统上取代查表,对网络规模有限制,最多7层,每层不超过64个神经元。用了一堆激活函数,效果都不好,于是又从哲(直)学(觉)的角度想了想,神级网络到底是个啥?

我曾经在一个为什么relu效果比sigmoid好的问题下回答说,神经网络就是个拟合器。抛开神经网络,传统上的拟合都是分解出一组基函数,再加权求和,泰勒分解的基函数是幂函数,傅立叶分解的基函数是三角函数,拉氏变换则是复平面指数函数,这些基函数都是作用域在全定义域上的连续函数,他们的特点就是每个点上几乎都是所有基函数的叠加,所以相互的耦合特别严重,牵一发而动全身,这在工程上是很不好处理的。真正工程上实用的是什么呢?实际上都是采用分段拟合的方法,样条曲线是分段三次曲线,保证导数连续,有限元则更干脆,直接分段一次函数。他们的特点就是基函数互不重叠,只管自己这一段凑活上就行了,彼此井水不犯河水,所以实现更简单。

RELU函数就有这个特点,小于0的部分直接没了,不会干扰其它人,所以是个半分段拟合,效果就比全域的sigmoid好。但是呢,RELU大于0的部分还是会影响别人的,所以只能算半个分段拟合。此外还有个负段梯度消失的问题,所以又引入了一堆负段非0梯度的变体,不过总的来说效果都差不多吧。

于是我就想,能不能要做就做干脆点,把半拉子分段搞成完全分段的,也就是只在一段范围内有值,其它都为0的激活函数?于是我试了下这个最简单的形式:

nn.LeakyReLU(1e-6)( 1- x**2)

也就是输入在(-1,1)之间有正值,其它区间都为0(为了防止梯度消失,加了个LeakyReLU)。这下就成了一个完全分段的函数了。

试了一下,效果还不错,但是捏,显然这个函数,与其叫激活函数,不如叫灭活函数,多用几次大部分梯度就消失了,所以太极端了,于是我又改了一下,变成这个样子

w=linear(x)

w=nn.leakyRelu(1-w**2)

out=w*x

linear是一个全连接层,先把输入做一次全连接变换得到权重,再对权重激活(灭活),这样就好多了,多留了几个活口,而且实际上从二次分段函数变成了三次曲线,更贴近与工程上的样条曲线。

但是层数多了还是会梯度消失,所以最好是加上残差,但这个函数直接加残差,则由于w总是在(0,1)之间,加上残差总是正偏,效果不好,所以我又改成这样

w=linear1(x)

w=1-w**2

w=linear2(w)

out=w*x+x

用了两个全连接层,把灭活的权重再组合一次,得到范围更大的比例,再乘加输入,形成一个带残差的结果,这样就基本消除了梯度消失的问题了。

值得注意的是我为了减少计算量,对这两个全连接层采用了按比例降维——升维的操作,也就是w的维度先降个几倍,然后再升到和输入一样的维度。因为我觉得既然目标是灭活,所以大部分w都应该是0,也就没必要保持和输入一样的维度。我采用的降维比例是4,看起来效果没什么区别,大家可以自行测试。

总之我在我的数据拟合应用上测试了一下这个函数,效果比RELU好的太多了,各位可以试试,说不定有惊喜呢。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值