作者:小辉0110_737 | 来源:互联网 | 2023-06-05 23:45
在抑制过拟合的方法中,我们前面有讲到一个方法:抑制过拟合的方法之权值衰减 ,在某种程度上能够很好的抑制过拟合,如果神经网络的模型很复杂,只用权值衰减就难以应对了,这样的情况下,我们一般选择Dropout方法,也就是在训练的过程中,随机选出隐藏层的神经元,然后将其删除,被删除的神经元不再进行信号的传递。代码在权值衰减中有出现,layers.py里面,摘录出来
class Dropout:'''随机删除神经元self.mask:保存的是False和True的数组,False的值为0是删除的数据'''def __init__(self,dropout_ratio=0.5):self.dropout_ratio=dropout_ratioself.mask=Nonedef forward(self,x,train_flg=True):if train_flg:self.mask=np.random.rand(*x.shape)>self.dropout_ratioreturn x*self.maskelse:return x*(1.0-self.dropout_ratio)def backward(self,dout):return dout*self.mask
随机删除的意思是指每次正向传播时,self.mask中都会以False的形式保存要删除的神经元。
np.random.rand(2,3) 随机生成[0,1)形状为(2,3)的数组
np.random.rand(2,3)>0.5 把大于0.5的值设为True,其余为False(而不是删除一半的意思,因为数据是随机的)
x * self.mask 结果就是False为0,True还是x原来的值
正向传播时传递了信号的神经元,反向传播时按照原样传递信号,正向传播时没有传递信号的神经元,反向传播时信号将停在那里。
现在我们来比较使用Dropout和不使用Dropout的情况,还是基于MNIST数据集来测试
训练类(common.trainer.py)
import numpy as np
from common.optimizer import *class Trainer:'''把前面用来训练的代码做一个类'''def __init__(self,network,x_train,t_train,x_test,t_test,epochs=20,mini_batch_size=100,optimizer='SGD',optimizer_param={'lr':0.01},evaluate_sample_num_per_epoch=None,verbose=True):self.network=networkself.verbose=verbose#是否打印数据(调试或查看)self.x_train=x_trainself.t_train=t_trainself.x_test=x_testself.t_test=t_testself.epochs=epochsself.batch_size=mini_batch_sizeself.evaluate_sample_num_per_epoch=evaluate_sample_num_per_epochoptimizer_dict={'sgd':SGD,'momentum':Momentum,'nesterov':Nesterov,'adagrad':AdaGrad,'rmsprop':RMSprop,'adam':Adam}self.optimizer=optimizer_dict[optimizer.lower()](**optimizer_param)self.train_size=x_train.shape[0]self.iter_per_epoch=max(self.train_size/mini_batch_size,1)self.max_iter=int(epochs*self.iter_per_epoch)self.current_iter=0self.current_epoch=0self.train_loss_list=[]self.train_acc_list=[]self.test_acc_list=[]def train_step(self):batch_mask=np.random.choice(self.train_size,self.batch_size)x_batch=self.x_train[batch_mask]t_batch=self.t_train[batch_mask]grads=self.network.gradient(x_batch,t_batch)self.optimizer.update(self.network.params,grads)loss=self.network.loss(x_batch,t_batch)self.train_loss_list.append(loss)if self.verbose:print('训练损失值:'+str(loss))if self.current_iter%self.iter_per_epoch==0:self.current_epoch+=1x_train_sample,t_train_sample=self.x_train,self.t_trainx_test_sample,t_test_sample=self.x_test,self.t_testif not self.evaluate_sample_num_per_epoch is None:t=self.evaluate_sample_num_per_epochx_train_sample,t_train_sample=self.x_test[:t],self.t_test[:t] train_acc=self.network.accuracy(x_train_sample,t_train_sample)test_acc=self.network.accuracy(x_test_sample,t_test_sample) self.train_acc_list.append(train_acc)self.test_acc_list.append(test_acc)if self.verbose:print('epoch:'+str(self.current_epoch)+',train acc:'+str(train_acc)+' | test acc:'+str(test_acc))self.current_iter+=1def train(self):for i in range(self.max_iter):self.train_step()test_acc=self.network.accuracy(self.x_test,self.t_test)if self.verbose:print('最终测试的正确率:'+str(format(test_acc,'.2%')))
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from common.multi_layer_net_extend import MultiLayerNetExtend
from common.trainer import Trainer(x_train,t_train),(x_test,t_test)=load_mnist(normalize=True)
#截取少量数据,让它再现过拟合
x_train=x_train[:300]#(300,784)
t_train=t_train[:300]#构建7层神经网络(6个隐藏层)
epochsNum=300
network=MultiLayerNetExtend(inputSize=784,hiddenSizeList=[100,100,100,100,100,100],outputSize=10,use_dropout=True,dropout_ration=0.2)
trainer=Trainer(network,x_train,t_train,x_test,t_test,epochs=epochsNum,mini_batch_size=100,optimizer='sgd',optimizer_param={'lr':0.01},verbose=True)
trainer.train()#画图
train_acc_list,test_acc_list=trainer.train_acc_list,trainer.test_acc_list
x=np.arange(len(train_acc_list))
plt.plot(x,train_acc_list,marker='s',label='train',markevery=10)
plt.plot(x,test_acc_list,marker='d',label='test',markevery=10)
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.ylim(0,1.0)
plt.legend(loc='lower right')
plt.show()
不使用Dropout的情况,修改成use_dropout=False,我们会发现下图中,train数据过拟合了,所以很多时候我们都会优选Dropout来抑制过拟合。
其中需要用到的多层神经网络扩展版本(支持Dropout)multi_layer_net_extend.py
基于MNIST数据集的Batch Normalization(批标准化层)https://blog.csdn.net/weixin_41896770/article/details/121557928