首页 » 人工智能 »

训练神经网络,numpy出现runtime warning的解决思路

2018年11月24日 / 91次阅读

打开支付宝首页,搜索“529018372”,即可领取红包!可重复领。

在使用numpy进行神经网络算法计算的时候,有的时候会遇到Runtime Warning,比如下面的这样的显示:

>> test.test5()
MNIST data is loaded.
/home/xinlin/repo/MNIST_lab/src/costfunc.py:29: RuntimeWarning: divide by zero encountered in log
(1-y)*np.log(1-a)))
/home/xinlin/repo/MNIST_lab/src/costfunc.py:29: RuntimeWarning: invalid value encountered in multiply
(1-y)*np.log(1-a)))
/home/xinlin/repo/MNIST_lab/src/f3cl_nn.py:54: RuntimeWarning: overflow encountered in double_scalars
for x in data)/len(data)
/home/xinlin/.local/share/virtualenvs/MNIST_lab-KQoRsFip/lib/python3.7/site-packages/numpy/core/fromnumeric.py:83: RuntimeWarning: overflow encountered in reduce
return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
Epoch 1: 989/10000, Cost: inf
/home/xinlin/repo/MNIST_lab/src/neuron.py:20: RuntimeWarning: overflow encountered in exp
return 1.0/(1.0+np.exp(-z))
/home/xinlin/repo/MNIST_lab/src/costfunc.py:28: RuntimeWarning: divide by zero encountered in log
return np.sum(np.nan_to_num(-y*np.log(a)-
/home/xinlin/repo/MNIST_lab/src/costfunc.py:28: RuntimeWarning: invalid value encountered in multiply
return np.sum(np.nan_to_num(-y*np.log(a)-

问题的原因是,数字太大了,溢出,计算过程出现inf,inf再做其它运算,大部分还是inf。

np.exp(800),区区800就会出现overflow,这时再计算sigmoid函数,就是0,然后再算np.log(0)(crossentropy),就会出现divied by zero ...

np.nan_to_num可以起一点作用,将inf转换成最大的浮点数,可以让计算继续下去,但是这么大的数,在后续计算的时候,还是会容易出现overflow encountered in double_scalars,这个doubel_scalars应该只是双精度的浮点数。还有的时候是显示overflow encountered in multiply。

 

一些解决方法和思考:

1, 我最先考虑的是,是否可以限制神经元函数的输出,比如sigmoid函数,将其限制在一个精度足够高的范围内;但是,存在的问题是,在output layer,如果多个神经元函数的输出都超限,经过处理之后,这多个神经元的输出就变成一样的了,就无法比较判断了。所以放弃了这个方法。

2, 经过测试发现,出现大量的这些runtime warning,主要是因为np.log这个函数;

这个函数被用来计算total cost,如果在训练过程中,不去计算cost,基本上所有这些warnning就没有了。

3, 如第2点,如果采用quadratic cost function,就没有这些warning出现。

4, sigmoid函数的np.exp overflow是不是可以忽略?因为不会出现inf和nan的情况。

np.log的warning显然不能忽视,后面的计算已经不能正常进行下去了。

 

5, 出现warning的网络配置:

(1)784:10,对,没有hidden layer,feedforward fully connected layered nn;

(2)cross-entropy cost function;

(3)learning rate = 2;

(4)网络中的w和b采用np.random.randn方式配置;

(5)sigmoid neuron;

(6)最极端的SGD,每一轮梯度下降,只随机取一个数据;(BGD,SGD,MBGD

(7)MNIST dataset;

-------

(a)以上配置,如果仅仅将网络修改为784:100:30:10,增加两个hidden layer,就没有warning了;

也就是说,这些warning可能不太重要,因为在production环境下,几乎不可能没有hidden layer。

(b)以上配置,如果仅仅将w和b全部初始化为0,warnning依然存在。

(c)以上配置,如果仅仅将SGD修改为BGD,warning消失;

其实,极端的SGD可能只有实验价值,并没有实用价值。

(d)以上配置,如果采用MBGD,mini batch size取不同的值,结果略有不同:

mini batch size = 100,没有warning;

mini batch size = 50,没有warning;

mini batch size = 30,没有warning;

mini batch size = 10,有warning,但明显感觉数量减少了一些。

似乎可以得出一个经验总结:在计算梯度的时候,越是平均,越不会出现这些烦人的warning。

 

6, 采用cross-entropy是为了解决learning slowdown的问题,在这个配置下,learning rate的设置一般要比quadratic cost要小一些。

我测试过,按照第5点的配置,只是将learning rate改为0.02,这些warning就消失了。

 

继续分析:

重新写了一段测试代码,直接观察在SGD的情况下,即只随机用一个数据来做梯度下降,然后停止计算cost,而是找一个数(我用的MNIST dataset的第一个数),计算output layer的a和z,然后将a和z打印出来,由于w和b是随机方式,我测试了几次,就发现了如下数据:

>> test.test6()
MNIST data is loaded.
[[-118.58708751]
[ 2.98852622]
[ -16.61383826]
[ 140.26884215]
[-116.31244446]
[-127.53373432]
[ -5.48993549]
[ -1.57377646]
[ -6.68414129]
[ -1.80108273]]
-----
[[3.14979486e-52]
[9.52053080e-01]
[6.09118363e-08]
[1.00000000e+00]
[3.06300138e-51]
[4.10018007e-56]
[4.11113925e-03]
[1.71678694e-01]
[1.24902616e-03]
[1.41719316e-01]]
>>> import numpy as np
>>> import neuron
>>> neuron.sigmoid(140.2689)
1.0
>>> np.exp(-140.2689)
1.2077881029207517e-61
>>> 1/(1+1.207788e-61)
1.0
>>>

发现一个a是1,这样如果计算cost,就是warning,算不出来;

这个a对应的z是140.2688这个数,我在下面有自己计算了一下,确实算sigmoid得到的是1.0.

以上测试,learning rate是2,这也解释了为什么将learning rate设置为0.02时,就没有warning,因为2太大了,加大了z值的变化幅度。区区140就让sigmoid饱和了,这个饱和的sigmoid神经元,可是有784个输入呀。。。

这个时候,softmax的优势就提现出来了,output layer不再使用sigmoid函数,就规避了这个问题。

output layer如果是sigmoid,就是取值最大的那个位置所代表的结果;

output layer如果是softmax,我们得到的是一个概率分布,哪个位置概率高,就是哪个结果。

用一个数来计算梯度,容易在那个数据的梯度上出现比较大值,如果learning rate也比较大,就容易导致z值过大,然后再计算np.log,就进入warning区域。

 

上面写的有点乱,总结一下:

只用一个数据来做梯度下降计算没有错,只是如果learning rate也比较大的话,容易导致warning的出现,导致无法在计算下去,64位的计算机,也是由计算上的限制的。增加hidden layer有效果,是因为cost的计算,只与output layer的输出有关,我上面的测试,距离output layer的那个hidden layer的神经元数量只有30。用mini batch来计算的思路是很不错的,比BGD快很多,而且也不容易出现各种warning。w和b的初始化,随机还是全零,在这个问题上没什么关系。使用quadratic cost function就是会导致learning slowdown,如果无惧slowdown,可以尽情地使用这个cost函数。softmax应该是更好的选择,下一个commit实现softmax。

同时,我也在质疑,为什么一定要计算cost的值?计算cost的值可能更多的只是实验方面的意义;cost的计算也不需要连续,网络连续计算,在output layer的所有输出都在某个限制内的时候,再计算一个cost的点值,这样行不行?其实,cost计算过程出现的各种warning,并没有影响网络中的梯度计算,从这个角度看,可以忽略计算过程中的warning(注意上文第4点)。

 

2018-12-03:

无视无惧numpy计算时的runtime warning...

本文链接:http://www.maixj.net/ai/numpy-warning-19356
云上小悟 麦新杰(QQ:1093023102)

评论是美德

《训练神经网络,numpy出现runtime warning的解决思路》有4条评论

无力满足评论实名制,评论对非实名注册用户关闭,有事QQ:1093023102.

  • 麦新杰

    貌似使用numba的JIT技术之后,warning被抑制了,但是cost计算还是会出现nan和inf。 [ ]

  • 麦新杰

    >>> 0*np.log(0)
    __main__:1: RuntimeWarning: divide by zero encountered in log
    __main__:1: RuntimeWarning: invalid value encountered in double_scalars
    nan
    >>>
    [ ]

    • 麦新杰

      当y为0时,a也为0,这时是一个正确的对应,说明在这一个点上,网络学习很成功。但是这时做计算,就会有warning,可以考虑换一种计算方式,y为0的时候,就不要算y*np.log(a),y为1时,就不要算(1-y)*np.log(1-a)。 [ ]

  • 麦新杰

    通过初始化更小的weight,warning的问题可以得到缓解,甚至消失不见。 [ ]


前一篇:
后一篇:

栏目精选

云上小悟,麦新杰的独立博客

Ctrl+D 收藏本页

栏目

AD

ppdai

©Copyright 麦新杰 Since 2014 云上小悟独立博客版权所有 备案号:苏ICP备14045477号-1。云上小悟网站部分内容来源于网络,转载目的是为了整合信息,收藏学习,服务大家,有些转载内容也难以判断是否有侵权问题,如果侵犯了您的权益,请及时联系站长,我会立即删除。

网站二维码
go to top