神经网络优化-正则化&DropOut

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Bazingaea/article/details/83474408

实现正则化主要需要在两个地方做出修改:

1.cost计算(L2 regularization)

    #正则化
    n = len(parameters)//2
    cost_extra = 0
    for x in range(n):
        w = parameters['w'+str(x+1)]
        cost_extra += np.sum(np.multiply(w,w))
        
    cost_extra=np.squeeze(cost_extra)
    
    cost=cost+lambd/(2*m)*cost_extra

2.更新参数w

说明一下,这里修改的主要目的是要更新参数,实际上由于cost的改变,对其参数w求偏导得到的dw必然也会改变,然后再执行

w=w-dw的时候,把更改的dw带进来,但是这里代码实现的时候,用了原来的dw,然后直接w=w-dw-正则项

这样处理的原因是在得到dw值得时候,是从后往前反向传播的,而由于输出层与隐藏层使用的激活函数不同,所以在计算dw的

时候是分开计算的,在原本计算上加上正则项代码太冗余,所以把它放在更新时处理。

#只改变参数w的更新,b的不变 
parameters['w'+str(l+1)] = parameters['w'+str(l+1)]
     - alphs * grads['dw'+str(l+1)] 
     - alphs * (lambd/m) * parameters['w'+str(l+1)]

这需要改动的两个集中的地方,至于函数参数的改变自己调整一下,就不贴代码了。

在第一课第四周构建的模型的基础上,加上不同参数值得正则处理,看看情况如何

n=train_data_finalX.shape[0]
layer_dims=[n,20,4,1]
parameters1,costs1=model(train_data_finalX,train_data_finalY,layer_dims,iter_times=2500,alphs=0.05,lambd=0.01,print_flag=True)
parameters2,costs2=model(train_data_finalX,train_data_finalY,layer_dims,iter_times=2500,alphs=0.05,lambd=0.001,print_flag=True)
parameters3,costs3=model(train_data_finalX,train_data_finalY,layer_dims,iter_times=2500,alphs=0.05,lambd=0.005,print_flag=True)
import matplotlib.pyplot as plt
plt.plot(costs1,label=0.01)
plt.plot(costs2,label=0.001)
plt.plot(costs3,label=0.005)
plt.xlabel('per 100 iters')
plt.ylabel('cost')
plt.title('For different lambd')
plt.legend()

plt.figure()

再分别看看训练得到的模型在训练数据和测试数据上的准确度:

y_pred_train=predict(train_data_finalX,parameters1)
print('Example one train acc is ',np.mean(y_pred_train == train_data_finalY)*100,'%')     
y_pred_test=predict(test_data_finalX,parameters1)
print('Example one test acc is ',np.mean(y_pred_test == test_data_finalY)*100,'%')

y_pred_train=predict(train_data_finalX,parameters2)
print('Example two train acc is ',np.mean(y_pred_train == train_data_finalY)*100,'%')     
y_pred_test=predict(test_data_finalX,parameters2)
print('Example two test acc is ',np.mean(y_pred_test == test_data_finalY)*100,'%')

y_pred_train=predict(train_data_finalX,parameters3)
print('Example three train acc is ',np.mean(y_pred_train == train_data_finalY)*100,'%')     
y_pred_test=predict(test_data_finalX,parameters3)
print('Example three test acc is ',np.mean(y_pred_test == test_data_finalY)*100,'%')

得到的结果是:

Example one train acc is  94.73684210526315 %
Example one test acc is  74.0 %
Example two train acc is  96.17224880382776 %
Example two test acc is  76.0 %
Example three train acc is  71.29186602870813 %
Example three test acc is  38.0 %

可以看到,当参数lambda过大时,拟合度有所下降,但是测试数据的准确度却没有上升,第二个lambda相对而言是起到了很小的作用的,可以看到正确率有略微的提升,尽管结果依然不好,但这个例子说明了正则化确实对过度拟合起到一定的修正作用。

值得一提的是,由于神经网络的可变超级参数实在太多了,没有参照,又没有足够经验的变来变去会导致训练结果越来越糟,

浪费很多时间,所以我的建议确定好神经网络的规模以后,一般不要再改动这个维度,然后先修改学习因子,大规模的神经网

络学习因子不适宜设置很高,会导致cost收敛的时候跳动幅度很大,很有可能出现梯度爆炸不能收敛的问题,然后修改正则化的

参数,当然可以多训练几个模型,只设置一个变量不同为参照,看模型的训练情况。

Drop out

简单说一下drop out是做了一件什么事,在神经网络训练过程中,如果隐藏层的单元数量很多,在数据不足的情况下,很容易出现过拟合的情况,过拟合就是分别对训练数据和测试数据做预测,训练数据的准确度很高,而测试数据准确度很低,这就表明你训练的模型太过拟合训练数据,已经不是平滑的曲线,而是过度扭曲了。

drop out作为正则化的一种技术,可以改善这种过拟合情况。

它所实现的就是在每一次迭代过程中,对每一层随机的删除一些处理单元,这个过程在先前传播和向后传播中都要用到,一会代码会详细说一下。

那为什么删掉处理单元会改善过拟合呢,首先我们应该会有一种直觉,处理单元变少了,他的拟合程度自然会降低,想象原本有10个处理单元对它进行约束,牵引它往正确值靠近,现在只有8个,牵引力度自然减少了,这种说法自然是不准确的,只是为了方便理解,其实你先大概了解它是在做什么,然后试验一下,慢慢就会更深入的理解,它这样处理的深层原理。

这只是其中一方面的原因,换句话来说,这是在正向传播它所起到的作用,上面也提到了在反向传播的时候也会用到dropout,这时它就会对参数w产生影响。减少了下一层单元对上一层单元的依赖,因为每次删除节点是随机的,这样的话这一次删掉1,3,5节点,下一层依赖其他节点,下一次删掉2,4,6,下一层又会依赖除此以外的节点。

贴代码看一下:

#向前传播
if drop_flag:
    #drop out
    d = np.random.rand(A.shape[0],A.shape[1]) < keep_prob
    drops['d'+str(i)]=d
    A = A*d
    A = A /keep_prob #rescale,使得A是我们期望看到的值



#向后传播
d=drops['d'+str(i)]
dA*=d
dA/=keep_prob


#这里有个细节问题,在向前传播的时候,最好判断是否进行drop out的,在预测的时候方便关闭
#forward_pro(original arguments,keep_drop=1,drop_flag=False)
#当然不设置flag只将keep_drop设置为1也可以关闭drop,但测试的时候还是要计算一遍,没必要

接上一篇第四周作业,当时迭代次数为 2500 ,学习因子是 0.05,在这个基础加上drop-out效果非常差,所以做了一些调整,见下表,但可以说明的是dropout确实可以改善过拟合的问题

再解释一下这个keep_prob参数,这是保留的节点比例,比如为0.8,就是说保留了80%的节点

迭代次数 学习因子 keep_prob train acc test acc
2500 0.05 0.9 65% 34%
2500 0.05 0.8 65% 34%
2500 0.08 0.8 65% 34%
1500 0.05 0.8 86% 68%
1500 0.05 0.9 88% 78%

开启了drop  out以后cost值就不会是稳步收敛下降的,这时候cost降低曲线参考意义不大,可以关闭

TIPS:关于迭代过程中出现cost值为NAN的解决方法:

在计算cost值是,log(y^)中y^可能为0,导致计算结果为无穷小,所以cost值为NAN

log(y^+np.power(10.0,-10))给他加上一个很小的数,对cost值不会造成很大影响,也不会出现NAN的情况

猜你喜欢

转载自blog.csdn.net/Bazingaea/article/details/83474408