我试图通过进行以下更改来使用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输出?无谓?)。谁能告诉我如何解决这个问题?谢谢!
请注意,我并未询问如何构建自定义激活功能。有关如何制作自定义功能的问题:
答案 0 :(得分:1)
为什么自定义激活功能会导致网络零丢失和低精度?
因为此网络不会通过您的新激活进行反向传播。你所做的只是创建自定义激活功能的一个开始。请参阅this question:“......正如上面提到的来源中所解释的那样,使用tf.RegisterGradient
和tf.Graph.gradient_override_map
来定义函数的渐变是一种破解......”。
我实际上不确定您的激活是否比tflearn.activations.leaky_relu
好得多,但如果您真的想要提供自定义激活,则必须对渐变进行编码并如上所述进行注册。