为什么自定义激活功能会导致网络零丢失和低精度?

时间:2017-10-14 07:26:29

标签: python tensorflow tflearn activation-function custom-build

我试图通过进行以下更改来使用tflearn构建自定义激活函数:

将我的自定义激活功能添加到activation.py

def my_activation(x):
    return tf.where(x >= 0.0, tf.div( x**2 , x + tf.constant(0.6)) , 0.01*x)

并将其添加到__init__.py

from .activations import linear, tanh, sigmoid, softmax, softplus, softsign,\
relu, relu6, leaky_relu, prelu, elu, crelu, selu, my_activation

由于张量流可以自动执行梯度计算,因此我不需要实现渐变功能。正如文章Deep Learning Programming Style中指出的那样,

  

过去,每当有人定义新模型时,他们必须手工制定衍生计算。虽然数学是相当简单的,但对于复杂的模型,它可能是耗时且繁琐的工作。所有现代深度学习库通过自动解决梯度计算问题,使从业者/研究人员的工作变得更加容易。

我使用以下代码在cifar10数据集上训练模型:https://github.com/tflearn/tflearn/blob/master/examples/images/convnet_cifar10.py 但将所有 relu 激活更改为 my_activation

可悲的是,这个简单的修改导致网络无法学到任何东西:

Training Step: 46  | total loss: 0.00002 | time: 1.434s
| Adam | epoch: 001 | loss: 0.00002 - acc: 0.0885 -- iter: 04416/50000
Training Step: 47  | total loss: 0.00002 | time: 1.448s
| Adam | epoch: 001 | loss: 0.00002 - acc: 0.0945 -- iter: 04512/50000
Training Step: 48  | total loss: 0.00001 | time: 1.462s
| Adam | epoch: 001 | loss: 0.00001 - acc: 0.0927 -- iter: 04608/50000
Training Step: 49  | total loss: 0.00001 | time: 1.476s
| Adam | epoch: 001 | loss: 0.00001 - acc: 0.0896 -- iter: 04704/50000
Training Step: 50  | total loss: 0.00001 | time: 1.491s
| Adam | epoch: 001 | loss: 0.00001 - acc: 0.0919 -- iter: 04800/50000
Training Step: 51  | total loss: 0.00001 | time: 1.504s
| Adam | epoch: 001 | loss: 0.00001 - acc: 0.0890 -- iter: 04896/50000
Training Step: 52  | total loss: 0.00001 | time: 1.518s
| Adam | epoch: 001 | loss: 0.00001 - acc: 0.0944 -- iter: 04992/50000
Training Step: 53  | total loss: 0.00001 | time: 1.539s
| Adam | epoch: 001 | loss: 0.00001 - acc: 0.0989 -- iter: 05088/50000
Training Step: 54  | total loss: 0.00001 | time: 1.553s
| Adam | epoch: 001 | loss: 0.00001 - acc: 0.0951 -- iter: 05184/50000
Training Step: 55  | total loss: 0.00000 | time: 1.567s
| Adam | epoch: 001 | loss: 0.00000 - acc: 0.0964 -- iter: 05280/50000
Training Step: 56  | total loss: 0.00000 | time: 1.580s
| Adam | epoch: 001 | loss: 0.00000 - acc: 0.0931 -- iter: 05376/50000
Training Step: 57  | total loss: 0.00000 | time: 1.594s
| Adam | epoch: 001 | loss: 0.00000 - acc: 0.0903 -- iter: 05472/50000
Training Step: 58  | total loss: 0.00000 | time: 1.613s
| Adam | epoch: 001 | loss: 0.00000 - acc: 0.0851 -- iter: 05568/50000
Training Step: 59  | total loss: 0.00000 | time: 1.641s
| Adam | epoch: 001 | loss: 0.00000 - acc: 0.0835 -- iter: 05664/50000
Training Step: 60  | total loss: 0.00000 | time: 1.674s
| Adam | epoch: 001 | loss: 0.00000 - acc: 0.0834 -- iter: 05760/50000

由于我只是一个初学者,我不知道导致网络变为零丢失和低精度的原因(NaN输出?无谓?)。谁能告诉我如何解决这个问题?谢谢!

请注意,我并未询问如何构建自定义激活功能。有关如何制作自定义功能的问题:

1 个答案:

答案 0 :(得分:1)

  

为什么自定义激活功能会导致网络零丢失和低精度?

因为此网络不会通过您的新激活进行反向传播。你所做的只是创建自定义激活功能的一个开始。请参阅this question:“......正如上面提到的来源中所解释的那样,使用tf.RegisterGradienttf.Graph.gradient_override_map来定义函数的渐变是一种破解......”。

我实际上不确定您的激活是否比tflearn.activations.leaky_relu好得多,但如果您真的想要提供自定义激活,则必须对渐变进行编码并如上所述进行注册。