神经网络常见层Numpy封装参考(4):优化器
目录前置层优化器SGD优化器Adam优化器测试演示完整代码下载 神经网络常见层Numpy封装参考 - 常见层前置层- 神经网络常见层Numpy封装参考1损失层- 神经网络常见层Numpy封装参考2线性层- 神经网络常见层Numpy封装参考3激活层优化器SGD优化器classSGD:SGD优化器支持动量和权重衰减def__init__(self,params:List[Parameter],lr:float0.01,momentum:float0.0,weight_decay:float0.0,nesterov:boolFalse): Args: params: 参数列表 lr: 学习率 momentum: 动量因子 weight_decay: 权重衰减系数 nesterov: 是否使用Nesterov动量 self.paramsparams self.lrlr self.momentummomentum self.weight_decayweight_decay self.nesterovnesterov self.state{}# 存储每个参数的状态如动量缓冲区defstep(self):更新参数foridx,paraminenumerate(self.params):ifparam.gradisNone:continue# 获取梯度gradparam.grad.copy()# 权重衰减ifself.weight_decay!0:gradgradself.weight_decay*param.data# 获取或创建动量缓冲区ifself.momentum!0:ifidxnotinself.state:self.state[idx]{momentum_buffer:np.zeros_like(param.data)}momentum_bufferself.state[idx][momentum_buffer]# 更新动量缓冲区momentum_bufferself.momentum*momentum_buffer-self.lr*gradifself.nesterov:# Nesterov动量: 使用校正后的梯度param.dataself.momentum*momentum_buffer-self.lr*gradelse:param.datamomentum_buffer self.state[idx][momentum_buffer]momentum_bufferelse:# 标准SGDparam.data-self.lr*graddefzero_grad(self):forparaminself.params:param.zero_grad()def__repr__(self):returnself.__class__.__name__()Adam优化器classAdam:Adam优化器支持权重衰减def__init__(self,params:List[Parameter],lr:float0.001,betas:tuple(0.9,0.999),eps:float1e-8,weight_decay:float0.0): Args: params: 参数列表 lr: 学习率 betas: 动量衰减系数 (beta1, beta2) eps: 数值稳定项 weight_decay: 权重衰减系数 self.paramsparams self.lrlr self.betasbetas self.epseps self.weight_decayweight_decay self.state{}# 存储每个参数的状态一阶动量、二阶动量、时间步self.t0# 全局时间步用于偏差校正defstep(self):更新参数self.t1# 每调用一次 step时间步加 1beta1,beta2self.betasforidx,paraminenumerate(self.params):ifparam.gradisNone:continue# 获取梯度gradparam.grad.copy()# 权重衰减L2 正则化ifself.weight_decay!0:gradgradself.weight_decay*param.data# 初始化状态如果尚未初始化ifidxnotinself.state:self.state[idx]{m:np.zeros_like(param.data),# 一阶动量v:np.zeros_like(param.data)# 二阶动量}# 取出动量缓冲区mself.state[idx][m]vself.state[idx][v]# 更新一阶动量带指数衰减mbeta1*m(1-beta1)*grad# 更新二阶动量带指数衰减vbeta2*v(1-beta2)*(grad**2)# 偏差校正m_hatm/(1-beta1**self.t)v_hatv/(1-beta2**self.t)# 更新参数param.data-self.lr*m_hat/(np.sqrt(v_hat)self.eps)# 保存更新后的动量self.state[idx][m]m self.state[idx][v]vdefzero_grad(self):清零所有参数的梯度forparaminself.params:param.zero_grad()def__repr__(self):返回优化器的字符串表示returnself.__class__.__name__()测试%matplotlib inline# 数据点满足非线性关系xnp.linspace(0,1,500).reshape(-1,1)y2*x**30.25*np.random.randn(500).reshape(-1,1)plt.scatter(x,y)plt.show()# 定义模型和损失函数modelSequential(Linear(1,10),Tanh(),Linear(10,1),)criterionMSELoss()# 定义优化器optimizer1SGD(paramsmodel.parameters(),lr1e-2,momentum0.8,weight_decay0)optimizer2Adam(paramsmodel.parameters(),lr1e-2)# 训练流程forepochinrange(1000):y_predmodel(x)loss,gradcriterion(y_pred,y)model.backward(grad)optimizer2.step()optimizer2.zero_grad()if(epoch%2000):print(loss)1.1548328265032672 0.11623908399811281 0.10961048087231211 0.07929787391344985 0.06122113711571879%matplotlib inline# 检验拟合效果x_plotnp.linspace(0,1.2,50).reshape(-1,1)plt.plot(x_plot,model(x_plot),cr)plt.scatter(x,y)plt.show()演示frommpl_toolkits.mplot3dimportAxes3Dimportcopyfromtqdmimporttqdmclassgrad_descent_demo:def__init__(self,optimizers:List,surface_type:strlinear,init_pos:int0): Args: optimizers: 传入需要模拟的优化器列表定义时参数设为空数组即可 surface_type: 3D表面类型可选linear和unlinear init_pos: 路径点初始位置可选0~3 self.optimizersoptimizers# 使用MSE损失self.criterionMSELoss()# 最优解self.target_w118self.target_w2-8# 100个二维数据self.Xnp.random.randn(100,2)# 线性目标值self.y(self.target_w1*self.X[:,0]self.target_w2*self.X[:,1]).reshape(-1,1)# 线性层if(surface_typelinear):modelSequential(Linear(2,1,biasFalse),)# 模拟前向传播过程self.forward_fnlambdaw1,w2:(w1*self.X[:,0]w2*self.X[:,1]).reshape(-1,1)# 线性层Tanh层elif(surface_typeunlinear):modelSequential(Linear(2,1,biasFalse),Tanh(),)self.forward_fnlambdaw1,w2:np.tanh(w1*self.X[:,0]w2*self.X[:,1]).reshape(-1,1)else:raiseValueError(Unsupported surface type!)# 每个优化器独立创建一个模型self.models[copy.deepcopy(model)foroptiminself.optimizers]# 为每个优化器关联对应的模型fori,optiminenumerate(self.optimizers):optim.paramsself.models[i].parameters()# 最优损失self.target_loss,_criterion(self.forward_fn(self.target_w1,self.target_w2),self.y)# 初始位置if(init_pos0):passelif(init_pos1):formodelinself.models:model[0].weight.datanp.array([[-5.0,7.0]])elif(init_pos2):formodelinself.models:model[0].weight.datanp.array([[-8.0,-20.0]])elif(init_pos3):formodelinself.models:model[0].weight.datanp.array([[2.0,-10.0]])else:raiseValueError(Unidentified initial position!)# 预计算损失曲面网格w1_rangenp.linspace(-15,50,25)w2_rangenp.linspace(-30,15,25)self.W1,self.W2np.meshgrid(w1_range,w2_range)self.Znp.zeros_like(self.W1)# 取出网格中的每个数据点计算损失foriinrange(self.W1.shape[0]):forjinrange(self.W1.shape[1]):y_predself.forward_fn(self.W1[i,j],self.W2[i,j])loss,_self.criterion(y_pred,self.y)self.Z[i,j]loss# 模拟阶段用于储存路径点self.w1_dict{}self.w2_dict{}self.loss_dict{}defstep(self,epoches:int60): 模拟梯度下降产生路径点 self.epochesepoches# 遍历每个模型和优化器fori,(model,optimizer)inenumerate(zip(self.models,self.optimizers)):w1_arr[]w2_arr[]loss_arr[]forepochintqdm(range(epoches)):# 训练流程y_predmodel(self.X)loss,gradself.criterion(y_pred,self.y)model.backward(grad)optimizer.step()optimizer.zero_grad()# 储存w1_arr.append(model[0].weight.data[0][0].copy())w2_arr.append(model[0].weight.data[0][1].copy())loss_arr.append(loss)# 每个索引储存一个优化器和对应模型的路径数据self.w1_dict[i]w1_arr self.w2_dict[i]w2_arr self.loss_dict[i]loss_arr# 绘制模拟图defplot(self): 绘制路径点动画 if(self.w1_dict{}):raiseValueError(Please run step() first!)# 开启交互模式plt.ion()# 创建固定图形对象figplt.figure(figsize(6,6))axfig.add_subplot(111,projection3d)# 绘制损失曲面ax.plot_surface(self.W1,self.W2,self.Z,cmapcoolwarm,alpha0.8,linewidth0)# 绘制最低点ax.scatter(self.target_w1,self.target_w2,self.target_loss,cg,s2)# 绘制文字说明ax.set_xlabel(w1)ax.set_ylabel(w2)ax.set_zlabel(MSE Loss)plt.show()# 为每个优化器创建一个路径点和路径线points[]lines[]colors[red,blue,green,orange,purple,brown,pink,gray]foridx,(w1_key,w2_key,loss_key)inenumerate(zip(self.w1_dict.keys(),self.w2_dict.keys(),self.loss_dict.keys())):# 图例说明直接获取优化器类名labelstr(self.optimizers[idx])[:-2]# 循环使用颜色列表colorcolors[idx%len(colors)]# 路径点和路径线point,ax.plot(self.w1_dict[w1_key][0],self.w2_dict[w2_key][0],self.loss_dict[loss_key][0],o,markersize4,colorcolor)line,ax.plot(self.w1_dict[w1_key][0],self.w2_dict[w2_key][0],self.loss_dict[loss_key][0],colorcolor,labellabel)# 储存points.append(point)lines.append(line)# 添加图例axplt.gca()ax.legend()# 更新运动轨迹forepochinrange(self.epoches):# 更新标题ax.set_title(fCurrent epoch:{epoch1}/{self.epoches},fontsize12)# 取出对应的路径数据和路径点forw1_key,w2_key,loss_key,point,lineinzip(self.w1_dict.keys(),self.w2_dict.keys(),self.loss_dict.keys(),points,lines):# 更新路径点point.set_xdata([self.w1_dict[w1_key][epoch]])point.set_ydata([self.w2_dict[w2_key][epoch]])point.set_3d_properties([self.loss_dict[loss_key][epoch]])# 更新路径线line.set_xdata(self.w1_dict[w1_key][:epoch])line.set_ydata(self.w2_dict[w2_key][:epoch])line.set_3d_properties(self.loss_dict[loss_key][:epoch])# 重新绘图plt.draw()# 暂停以实现动画效果plt.pause(0.05)# plt.savefig(imgstr(epoch).png)# 关闭交互模式plt.ioff()%matplotlib tk# 模拟三种优化器optimizer1SGD(params[],lr1e-1,momentum0,weight_decay0.6)optimizer2SGD(params[],lr1e-1,momentum0.92,weight_decay0)optimizer3Adam(params[],lr1,betas(0.9,0.99))# 初始化gddgrad_descent_demo([optimizer1,optimizer2,optimizer3],surface_typeunlinear,init_pos2)# 模拟gdd.step(epoches60)# 绘图gdd.plot()100%|███████████████████████████████████████████████████████████████████████████████| 60/60 [00:0000:00, 10899.49it/s] 100%|███████████████████████████████████████████████████████████████████████████████| 60/60 [00:0000:00, 13318.77it/s] 100%|███████████████████████████████████████████████████████████████████████████████| 60/60 [00:0000:00, 30009.33it/s]下一篇 - 神经网络常见层Numpy封装参考5其他层
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2552095.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!