资讯详情

【Pytorch学习笔记】5.总结一下一个深度学习模型的实现过程(以Softmax回归从零实现为例)

文章目录

    • 首先要考虑解决什么问题
    • 1 获取和读取数据
      • 获取数据
      • 读取数据
    • 2 构建模型
      • 模型参数的初始化
      • 定义模型和损失函数
    • 3 定义优化算法
    • 4 训练模型
      • 定义训练函数中注意的要素
      • 定义步骤
    • 5 评估模型
    • 完整版代码(不需要安装d2l)

一些简单的深度学习模型从零开始看教程似乎很简单,敲代码过去了,但仍然做出自己的初步总结。思维过程适用于未来的任何问题,包括实现的基本步骤、如何反映代码的模型概念、定义培训过程中需要的参数等。

本文以Softmax以零实现为例,总结一个深度学习模型的实现过程,每一步都附上自己的总结思路。

首先要考虑解决什么问题

比如我们想用Softmax回归模型,实现图片分类问题。 后面是目的,前面是手段。 然后脑海中需要出现几个解决问题的基本步骤:

  • 获取和读取数据
  • 定义模型:①根据模型初始化模型参数,②定义模型和损失函数
  • 定义优化算法(如SGD)用于学习参数
  • 训练模型
  • 评估模型

1 获取和读取数据

获取数据

  • 首先,我们需要创建一个数据集对象Dataset()

对于获取数据,一般来说,初学者些获取数据的人通常会使用数据pytorch一些相关库的方法。 例如,我们想读 FashionMNIST 用于通过的数据集Softmax模型解决数据集的分类问题(或评估)Softmax模型的分类性能,Whatever,不同的表达)。

我们通常使用它torchvision.datasets下一类创建数据集,有很多公共数据集可以直接下载获取,如果我们需要的话FashionMNIST数据集:

# 对于机器学习问题,通常会生成训练集和测试集 mnist_train = torchvision.datasets.FashionMNIST(     root='~/Datasets/FashionMNIST', train=True, download=True,      transform=transforms.ToTensor()) mnist_test = torchvision.datasets.FashionMNIST(     root='~/Datasets/FashionMNIST', train=False, download=True,      transform=transforms.ToTensor()) 

注意其中的transform数据转换器(位于参数中torchvision.transforms下),常用的有ToTensor()该方法将图像数据转换为尺寸(C x H x W)大小位于[0.0, 1.0]的float32数据类型的Tensor。 创建的数据集对象属于torch.utils.data.Dataset的子类。

读取数据

  • 然后创建数据集对象Dataset()进入数据加载器Dataloader()

我们创造一个Dataset一般后直接传入torch.utils.data.Dataloader() 生成一个Dataloader对象。

batch_size = 256 train_iter = torch.utils.data.DataLoader(     mnist_train, batch_size=batch_size, shuffle=True, num_workers=0) test_iter = torch.utils.data.DataLoader(     mnist_test, batch_size
       
        =batch_size
        , shuffle
        =
        False
        , num_workers
        =
        0
        ) 
        # 这里的num_workers表示数据读取的线程数,Windows系统一般默认设0,这里更多信息可以自行搜索学习。 
       

生成Dataloader后,就可以使用for循环读取批量数据了,一次循环是一个batch_size数量的数据。 batch_size是一个重要的超参数,横贯机器学习过程的始终,不仅方便计算机按批次读取数据减少内存开销,并且在计算梯度时,使用一个batch_size的数据进行迭代更新,大大减少计算量。

我们也可以使用next(iter(dataloader))手工读取一个批次的数据。

Dataloader是一个可迭代对象,它通过生成迭代器,来读取批量数据。 对于一些数据,我们还可以构建生成器来读取批量数据,这部分扩展阅读可以参考我这篇文章。

2 构建模型

  • 将模型的数学表达转换成代码表达

我们选择Softmax回归模型时,心中需要构思好这个模型的数学表达,见下。 需要注意的是,softmax回归本身是一个单层神经网络,并且和线性回归一样是全连接的: 在这里插入图片描述这里提示我们要有一个思维:把一个数学模型用深度神经网络去构建解释。

我们的Softmax回归数学模型是(以4像素图片,3分类标签为例): o ( i ) = x ( i ) W + b y ^ ( i ) = softmax ⁡ ( o ( i ) ) p = arg max ⁡ p y ^ p \begin{aligned} \boldsymbol{o}^{(i)} &=\boldsymbol{x}^{(i)} \boldsymbol{W}+\boldsymbol{b} \\ \hat{\boldsymbol{y}}^{(i)} &=\operatorname{softmax}\left(\boldsymbol{o}^{(i)}\right) \end{aligned} \\ p = \underset{p}{\argmax } \hat{y}_{p} o(i)y^​(i)​=x(i)W+b=softmax(o(i))​p=pargmax​y^​p​ x ( i ) = [ x 1 ( i ) x 2 ( i ) x 3 ( i ) x 4 ( i ) ] , o ( i ) = [ o 1 ( i ) o 2 ( i ) o 3 ( i ) ] , y ^ ( i ) = [ y ^ 1 ( i ) y ^ 2 ( i ) y ^ 3 ( i ) ] \boldsymbol{x}^{(i)}=\left[x_{1}^{(i)} \quad x_{2}^{(i)} \quad x_{3}^{(i)} \quad x_{4}^{(i)}\right], \boldsymbol{o}^{(i)}=\left[\begin{array}{lll} o_{1}^{(i)} & o_{2}^{(i)} & o_{3}^{(i)} \end{array}\right], \\ \hat{\boldsymbol{y}}^{(i)}=\left[\begin{array}{lll} \hat{y}_{1}^{(i)} & \hat{y}_{2}^{(i)} & \hat{y}_{3}^{(i)} \end{array}\right] x(i)=[x1(i)​x2(i)​x3(i)​x4(i)​],o(i)=[o1(i)​​o2(i)​​o3(i)​​],y^​(i)=[y^​1(i)​​y^​2(i)​​y^​3(i)​​] 参数: W = [ w 11 w 12 w 13 w 21 w 22 w 23 w 31 w 32 w 33 w 41 w 42 w 43 ] , b = [ b 1 b 2 b 3 ] \boldsymbol{W}=\left[\begin{array}{lll}w_{11} & w_{12} & w_{13} \\ w_{21} & w_{22} & w_{23} \\ w_{31} & w_{32} & w_{33} \\ w_{41} & w_{42} & w_{43}\end{array}\right], \quad \boldsymbol{b}=\left[\begin{array}{lll}b_{1} & b_{2} & b_{3}\end{array}\right] W=⎣⎢⎢⎡​w11​w21​w31​w41​​w12​w22​w32​w42​​w13​w23​w33​w43​​⎦⎥⎥⎤​,b=[b1​​b2​​b3​​]

初始化模型参数

本例中,我们需要学习的模型系数是 矩阵和偏倚项。 我们将28281大小的图片拉伸为28×28=784长度的向量(输入的是一个batch的,即X形状为256×784),输出的是10分类,因此的形状为:784×10 偏倚项的形状为10×1

然后,我们一般使用(0,0.01)的正态分布去初始化参数的数值:

num_inputs = 784
num_outputs = 10
W = torch.tensor(
    np.random.normal(loc=0, scale=0.01, size=(num_inputs, num_outputs)), 
    dtype=torch.float)
b = torch.zeros(num_outputs , dtype=torch.float)

最后,最重要的一步,W和b,因为我们需要学习这个参数!

# 设上梯度
W.requires_grad_(requires_grad=True)
b.requires_grad_(requires_grad=True)

定义模型、损失函数

先定义softmax:

def softmax(X):
    X_exp = X.exp()
    partition = X_exp.sum(dim=1, keepdim=True)
    return X_exp / partition  # 这里使用了广播机制

def net(X):
    return softmax(torch.mm(X.view((-1, num_inputs)), W) + b)

def cross_entropy(y_hat, y):
    return -torch.log(y_hat.gather(dim=1, index=y.view(-1,1)))
# y就是待传入的那个批量的label数据

(定义交叉熵损失函数的细节可以参考我这篇文章)

我们在定义模型和损失函数时,在心中对模型的最好有个大致的把握。 我们可以先看看本模型损失函数的梯度节点可视化: (可视化可参考我的这篇文章) 可以看到在这个损失函数的计算图里,我们要求的是顶端的两个参数W,b,整个损失函数是关于参数的函数。DivBackward0节点及以上部分是模型计算结果y_hat,节点以下部分流向损失函数的计算。

3 定义优化算法

  • 定义优化器以优化参数

本例中我们依然可使用随机梯度下降法(SGD)作为Optimizer,届时在训练时每个batch数据计算完后梯度后,利用当前梯度迭代更新一次参数。 优化器除了需要传入的待学习参数(本例为W,b)外,还需要传入一些超参数。

# lr是学习率。作为超参数。
def sgd(params, lr, batch_size):
    for param in params:
        param.data -= lr * param.grad / batch_size

4 训练模型

接下去就是重头戏的训练环节了,我们一般定义一个训练函数train()作为一套训练的过程的打包。

定义训练函数注意的要素

  1. :lr(学习率),num_epochs(训练轮数),batch_size 超参数一般根据经验设置,比如本例设lr=0.1,num_epochs=5 在深度学习模型中,一般需要训练多轮epoch才有比较好的效果
  2. : 训练集的Dataloader:train_iter 测试集的Dataloader:test_iter(视情况非必须) 模型名net:net 损失函数loss:cross_entropy 训练参数params:[W, b] 优化器Optimizer:None(我们直接在函数中封入SGD作为默认优化器,就可以不用再手动传)

定义步骤

  1. 从训练集Dataloader获得一个X,y批次; 通过模型net算出预测值y_hat; 通过损失函数loss算出损失值l

记得回顾上面那张计算图,只有待学习的参数W,b带梯度,是届时需要传入优化器更新的。 同时注意损失函数定义时一般返回的是一个batch_size长度的向量,对齐求sum()转换成标量以方便求导(见下方代码)。

  1. 对参数W,b梯度清零
  2. l.backward()针对这一批量的数据结果,反向传播,求出当前梯度
  3. 之后W,b中就带有了梯度信息,这时传入优化器sgd对参数进行一次迭代更新:

W . d a t a = W . d a t a − l r ∗ W . g r a d / b a t c h s i z e W.data = W.data -lr * W.grad / batchsize W.data= 标签: 5w33kr电阻5w33r精密电阻

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台