Pytorch 目标检测学习 Day 1

1.nn.Module 类

建立一个三层简单的网络。首先定义线性Linear(即定义学习参数,到后面学习深度网络时候,实则是不需要的),然后进行前向传播定义(即网络层的定义)。

import torch
from torch import nn
class Linear(nn.Module):
    def __init__(self,in_dim,out_dim):
        super(Linear,self).__init__()
        #调用nn.Module 来构造函数
        #使用nn.Parameter来构造学习的参数
        self.w = nn.Parameter(torch.randn(in_dim,out_dim))
        self.b = nn.Parameter(torch.randn(out_dim))
    def forward(self,x):
        x = x.matmul(self.w)
        y = x + self.b.expand_as(x)
        #expand_as()这个函数就是把一个tensor变成和函数括号内一样形状的tensor
        return y
class Preception(nn.Module):
    def __init__(self,in_dim,hid_dim,out_dim):
        super(Preception,self).__init__()
        self.layer1 = Linear(in_dim,hid_dim)
        self.layer2 = Linear(hid_dim,out_dim)
    def forward(self,x):
        x=self.layer1(x)
        y=torch.sigmoid(x)
        x = self.layer2(y)
        y=torch.sigmodi(y)
        return y
print('success')
import torch
from perception import Preception

perception = Preception(2,3,2)
print(perception)
for name,parameter in perception.named_parameters():
    print(name,parameter)

data = torch.randn(4,2)
print(data)
output = perception(data)
print('output',output)

显示出的结果应该是:【4,2】维度,

Preception(
  (layer1): Linear()
  (layer2): Linear()
)
layer1.w Parameter containing:
tensor([[-0.8158,  0.7365,  0.4314],
        [-0.4744, -1.5293, -0.4451]], requires_grad=True)
layer1.b Parameter containing:
tensor([3.9662e-04, 3.8215e-01, 1.0424e+00], requires_grad=True)
layer2.w Parameter containing:
tensor([[-0.0472, -1.1446],
        [ 1.1377, -1.6229],
        [-0.4996, -0.4784]], requires_grad=True)
layer2.b Parameter containing:
tensor([-0.3921,  0.1505], requires_grad=True)
tensor([[ 0.7879,  1.0222],
        [ 0.2848,  0.7457],
        [-1.0298, -0.4632],
        [ 1.5001,  0.6287]])
output tensor([[0.4113, 0.2598],
        [0.4157, 0.2339],
        [0.4726, 0.1218],
        [0.4782, 0.1886]], grad_fn=<SigmoidBackward>)
torch.Size([4, 2])

2.nn.Sequential()模块

当模型中只是简单的前馈网络时,即上一层的输出直接作为下一层的输入,这时可以采用nn.Sequential()模块来快速搭建模型,而不必手动在forward()函数中一层一层地前向传播。因此,如果想快速搭建模型而不考虑中间过程的话,推荐使用nn.Sequential()模块。

3.损失函数

例如均方损失、交叉熵损失。torch.nn及torch.nn.functional中都提供了各种损失函数,通常来讲,由于损失函数不含有可学习的参数,因此这两者在功能上基本没有区别。

4.nn.optim

nn.Module模块提供了网络骨架,nn.functional提供了各式各样的损失函数,而Autograd又自动实现了求导与反向传播机制,这时还缺少一个如何进行模型优化、加速收敛的模块,nn.optim应运而生。

nn.optim中包含了各种常见的优化算法,包括随机梯度下降算法SGD(StochasticGradient Descent,随机梯度下降)、Adam(Adaptive MomentEstimation)、Adagrad、RMSProp,这里仅对常用的SGD与Adam两种算法进行详细介绍。

SGD梯度下降(Gradient Descent)是迭代法中的一种:

是指沿着梯度下降的方向求解极小值,一般可用于求解最小二乘问题。在深度学习中,当前更常用的是SGD算法,以一个小批次(Mini Batch)的数据为单位,计算一个批次的梯度,然后反向传播优化,并更新参数。SGD的表达式如式(2-1)与式(2-2)所示

公式中,gt代表了参数的梯度,η代表了学习率(Learning Rate),即梯度影响参数更新的程度,是训练中非常重要的一个超参数。

SGD优化算法的好处主要有两点:·分担训练压力:当前数据集通常数量较多,尺度较大,使用较大的数据同时训练显然不现实,SGD则提供了小批量训练并优化网络的方法,有效分担了GPU等计算硬件的压力。·加快收敛:由于SGD一次只采用少量的数据,这意味着会有更多次的梯度更新,在某些数据集中,其收敛速度会更快。

缺点:

初始学习率难以确定:SGD算法依赖于一个较好的初始学习率,但设置初始学习率并不直观,并且对于不同的任务,其初始值也不固定。·容易陷入局部最优:SGD虽然采用了小步快走的思想,但是容易陷入局部的最优解,难以跳出。

有效解决局部最优的通常做法是增加动量(momentum),其概念来自于物理学,在此是指更新的时候一定程度上保留之前更新的方向,同时利用当前批次的梯度进行微调,得到最终的梯度,可以增加优化的稳定性,降低陷入局部最优难以跳出的风险。其函数如式(2-3)与式(2-4)所示。

公式中的μ为动量因子,当此次梯度下降方向与上次相同时,梯度会变大,也就会加速收敛。当梯度方向不同时,梯度会变小,从而抑制梯度更新的震荡,增加稳定性。在训练的中后期,梯度会在局部极小值周围震荡,此时gt接近于0,但动量的存在使得梯度更新并不是0,从而有可能跳出局部最优解。

Adam方法

Adam利用了梯度的一阶矩与二阶矩动态地估计调整每一个参数的学习率,是一种学习率自适应算法。

Adam的优点在于,经过调整后,每一次迭代的学习率都在一个确定范围内,使得参数更新更加平稳。此外,Adam算法可以使模型更快收敛,尤其适用于一些深层网络,或者神经网络较为复杂的场景

5.搭建三层感知器

使用nn.Sequential()定义三层网络:

1.先定义网络结构

2.进行前向传播

3.定义model

4.输入数据

5.Optim 进行优化

6.生成loss

7.optimizer.zero_grad()

loss.backward()

optimizer.step()

8.计算精度

from torch import nn
class MLP(nn.Module):
    def __init__(self,in_dim,hid_dim1,hid_dim2,out_dim):
        super(MLP,self).__init__()
        self.layer = nn.Sequential(
            nn.Linear(in_dim,hid_dim1),
            nn.ReLU(),
            nn.Linear(hid_dim1,hid_dim2),
            nn.ReLU(),
            nn.Linear(hid_dim2,out_dim),
            nn.ReLU()
        )
    def forward(self,x):
        x = self.layer(x)
        return x
#print(MLP)

进行测试:

import torch 
from mpl import MLP
from torch import nn
from torch import optim

model = MLP(28*28,300,200,10)
print(model)
#print('model parameters',model.parameters())
optimizer = optim.SGD(params = model.parameters(),lr = 0.001)
data = torch.randn(10,28*28)
output = model(data)
label = torch.Tensor([1,0,4,7,9,3,4,5,3,2]).long()
criterion = nn.CrossEntropyLoss()
loss = criterion(output,label)
print(loss)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(loss)

输出结果

MLP(
  (layer): Sequential(
    (0): Linear(in_features=784, out_features=300, bias=True)
    (1): ReLU()
    (2): Linear(in_features=300, out_features=200, bias=True)
    (3): ReLU()
    (4): Linear(in_features=200, out_features=10, bias=True)
    (5): ReLU()
  )
)
model parameters <generator object Module.parameters at 0x0000023C5C845D48>
tensor(2.2948, grad_fn=<NllLossBackward>)
tensor(2.2948, grad_fn=<NllLossBackward>)

不同参数层分配不同的学习率:优化器也可以很方便地实现将不同的网络层分配成不同的学习率,即对于特殊的层单独赋予学习率,其余的保持默认的整体学习率,具体示例如下:

 

 

 

 

 

 

 

 

 

おすすめ

転載: blog.csdn.net/abc123mma/article/details/112105605