当前位置: 首页 > 后端技术 > Python

【Pytorch入门】第一波:搭建第一个神经网络

时间:2023-03-26 00:12:15 Python

第一步:安装Pytorch我的电脑在pip上下载Pytorch报错,所以用Anaconda下载,这里不再赘述。第二步:准备数据,搭建框架。首先,我们同意尝试构建一个双层神经网络。数据量$N=64$。输入层、隐藏层、输出层的维度为:$d_{in}=1000,H=100,d_{out}=10$因为是Demo,尽量直接使用一些随机数据进行测试:#64个数据,1000-dim,中间层100-dim,输出10-dimx=torch.randn(N,d_in,requires_grad=True)y=torch.randn(N,d_out,requires_grad=True)注意你这个时候需要写requires_grad=True,这样就可以直接使用.grad属性来计算梯度了。下一步是定义模型。我们打算为此模型使用双层神经网络。首先,官方文档中定义了torch.nn.module的用法:Baseclassforallneuralnetworkmodules。你的模型也应该继承这个类。查看Doc,有几点应该使用:torch.nn.module应该是所有神经网络的基类,如果你写一个神经网络,你也应该继承它。如果你想把这个模型应用到GPU上,你也可以使用.cuda()函数。对于__init__,就是勾勒出整个模型的框架。我们首先需要调用基类的构造函数,然后定义这个模型需要的函数。因为我们要做一个二层神经网络,所以我们分别声明了一个二层线性函数。对于forward来说,必须重写所有的子类,代表了前向传播的逐层映射关系。对于激活函数,我们同意使用ReLu,即.clamp(min=0)。所以我们可以这样写:classTwoLayerNet(torch.nn.module):#defineinitandforwardtogiveamodel#init相当于给这个frameworkdef__init__(self,d_in,H,d_out):super(TwoLayerNet,self).__init__()self.linear1=nn.Linear(d_in,H)self.linear2=nn.Linear(H,d_out)#forward是定义前向传播的部分defforward(self,x):y_pred=self.linear2(self.linear1(x).clamp(min=0))returny_pred第三步:应用模型的前向传播主要有两个方面,第一是在应用中定义上面定义的框架,第二就是给出学习率和损失函数。#初始化模型model=TwoLayerNet(d_in,H,d_out)#指定损失函数loss_fn=nn.MSELoss(reduction='sum')#指定学习率learning_rate=1e-4反向传播部分首先我们约定反向传播的模型为A像SGD这样比较简单的模型:optimizer=torch.optim.Adam(model.parameters(),lr=learning_rate)loss_list=[]#为了画出到目前为止的训练迭代部分,我们需要对模型有一个直观的认识,对于整个模型而言$x\rightarrowH\rightarrowy_{pred}$为前向传播路径,损失函数为:$$loss=\sqrt{y_{pred}^2-y^2}$$为每一层神经网络,我用网络图来说明关系:第一层神经网络是输入部分:所以权重矩阵$w_1$应该是$d_{in}\timesH$的维度,同理,第二层神经网络输出的权重矩阵应该是$H\timesd_{out}$维。我们的下一步是执行训练迭代。我们首先同意训练$200$代并观察收敛效果。foritinrange(200):#forwardpassy_pred=model(x)#计算损失loss=loss_fn(y_pred.float(),y.float())print(it,loss.item())loss_list.append(loss)#backwardpassoptimizer.zero_grad()loss.backward()optimizer.step()forwardpass部分是将自变量$x$输入到模型中,computeloss是计算损失值。需要注意以下几点:loss_fn(y_pred.float(),y.float())不能写成loss_fn(y_pred-y),否则使用一个目标参数loss.item()输出值包含在losstensor和backwardpass中,我们需要注意的是在每次梯度下降之前,我们需要清除之前的梯度。原因是如果不清除梯度,会在每次迭代时自动叠加。这种自动叠加的好处是对于一些链来说梯度计算比较方便,但是每一代都需要手动清零。Step4:收尾和简单分析最后我们只需要简单的画出迭代图,效果大概是这样的:plt.plot(range(200),loss_list)plt.show()大概$10$代已经收敛了,效果还是不错的。迭代次数可以根据第一次运行的结果进行调整。完整代码附在下面:importtorchimporttorch.nnasnnimportnumpyasnpimportmatplotlib.pyplotaspltN,d_in,H,d_out=64,1000,100,10#随机创建一些训练数据x=torch.randn(N,d_in,requires_grad=True)y=torch.randn(N,d_out,requires_grad=True)classTwoLayerNet(torch.nn.module):#定义init和forward给一个模型#init相当于给这个Frameworkdef__init__(self,D_in,H,D_out):super(TwoLayerNet,self).__init__()self.linear1=nn.Linear(D_in,H)self.linear2=nn.Linear(H,D_out)#转发是defforward(self,x):y_pred=self.linear2(self.linear1(x).clamp(min=0))returny_pred#初始化模型model=TwoLayerNet(d_in,H,d_out)#规定损失函数loss_fn=nn.MSELoss(reduction='sum')#指定学习率learning_rate=1e-4#定义优化器进行优化optimizer=torch.optim.Adam(model.parameters(),lr=learning_rate)loss_list=[]foritinrange(200):#forwardpassy_pred=model(x)#计算损失loss=loss_fn(y_pred.float(),y.float())打印(it,loss.item())loss_list.append(loss)#backwardpassoptimizer.zero_grad()loss.backward()optimizer.step()plt.plot(range(200),loss_list)plt.show()参考数据pytorch官方文档最好的PyTorch入门实战教程(16小时实战)