一行一行讲解深度学习代码(零)如何利用pytorch搭建一个完整的深度学习项目——深度学习项目的大致结构

在这里插入图片描述

本文适合没有基础的pytorch深度学习小白python基础不太好的同学!!建议有基础的同学不要看~

不知道大家在初接触pytorch实现深度学习的时候有没有这样的烦恼,就是有的项目一个.py文件就能实现,有的则需要多个.py文件,这个问题可能略显低智,但确实是我在刚开始接触项目时候所碰到的一个问题。

因为如果是多个.py文件就会涉及到导入模块、编写类、类的初始化、类的继承等问题,而这对于一个python基础极差的人来说简直是致命打击qwq,因此本文将从深度学习项目结构基础开始讲解,直至构建起一个简单的(一个.py文件实现)深度学习项目和稍复杂的(多个.py文件实现)深度学习项目。

深度学习项目的大致结构

对于一个深度学习项目来说,大致要有以下几部分:

  • 数据集加载
  • 数据预处理
  • 模型构造
  • 模型训练
  • 模型保存与加载
  • 模型测试

打个比方,数据集加载相当于是买面粉(dataset),并且把它们整整齐齐地揉成了一个个面团(dataloader),然后进行面团发酵(数据预处理),以供面包机(模型构造) 后续的做面包活动(模型训练与测试)。那我们就开始一个部分一个部分地拆解吧~

(一)数据集加载

1.功能

因为在深度学习中,训练的数据通常数量十分巨大,不能一次性的把全部数据都传到模型中进行训练,所以要利用数据加载,将源数据的顺序打乱,进行分批和预处理后,最后将处理好的数据传给模型进行训练,这样才能保证模型训练的准确性。通常情况下,加载好的数据一般每一行是一个训练样本,每一列为一个样本特征。

2.工具

在使用Pytorch构建和训练模型的过程中,经常需要把原始数据(图片、文本等)转换为张量的格式。对于小数据集,我们可以手动导入,但是在深度学习中,数据集往往是比较大的,这时Pytorch的数据导入功能便发挥了作用,Pytorch导入数据主要依靠 DataLoaderDataset这两个类来完成,torch的utils工具下的data数据工具提供了两个类:Dataset、DataLoader。

打个比方,DataLoader相当于你拿一个水盆,而Dataset相当于泉水。DataLoader可以对小批量数据集进行处理。

(1)datasets

datasets: 是用来创建数据集的函数(一般称为数据集类),一般情况下,我们的数据集首先传给datasets,封装为数据集类。可以使用datasets自定义数据集的内容和标签。

在使用时,首先要引入torchvision.datasets,这里简单介绍下torchtorchvision

torch:torch 库是 PyTorch 的核心库,提供了张量操作、神经网络构建、自动微分等功能。主要功能包括:

  1. 张量操作:提供了张量(多维数组)的创建、操作和运算,支持 GPU 加速计算。
  2. 神经网络构建:包括各种类型的神经网络层、激活函数和优化器,方便用户构建和训练神经网络模型。
  3. 自动微分:PyTorch 的自动微分引擎可以自动计算张量的梯度,支持反向传播算法进行模型训练。

torchvision:torchvision 库是 PyTorch 的计算机视觉库,提供了一系列用于图像处理和计算机视觉任务的工具和数据集。主要功能包括:

  1. 数据加载:提供了常用的图像数据集(如 ImageNet、CIFAR-10 等)的加载和预处理功能。
  2. 图像变换:包括各种图像变换操作,如裁剪、缩放、旋转等,用于数据增强和预处理。
  3. 模型库:包含了一些经典的计算机视觉模型(如 ResNet、AlexNet 等),方便用户进行图像分类、目标检测等任务。

引入torchvision.datasets后,我们便可以使用datasets中的数据集,然后分别定义训练数据集以及测试数据集,这里以MNIST(手写数字数据集)为例,解释加载过程:

from torchvision.datasets import MNIST
# root是存储训练/测试数据的路径,关于root涉及到的文件路径讲解,请见我的另一篇文章:相对路径详解(./ ../ .../)
# train指定训练或测试数据集,当布尔值为True则为训练集,当布尔值为False则为测试集
# download=True从互联网下载数据(如果无法在本地获得)
# transform指定特征转换方式,target_transform指定标签转换方式,这里的transform实际上是数据预处理的步骤,具体见下文。
train_data = MNIST(root='./data',train=True,download=False,transform=transforms.ToTensor())
test_data = MNIST(root='./data',train=False,download=False,transform=transforms.ToTensor())
(2)DataLoader

DataLoader:接收Dataset作为输入,得到DataLoadr,它是一个迭代器,用于加载数据并进行批处理,方便我们去多线程地读取数据,并且可以实现batch以及shufle的读取等,可以拿出一个mini-batch这样一组数据来供我们训练时快速使用。

在使用时,首先要引入torch.utils.data中的DataLoader模块,然后分别加载训练数据集以及测试数据集,这里以MNIST(手写数字数据集)为例,解释处理过程:

from torchvision.datasets import MNIST
from torch.utils.data import DataLoader
train_data = MNIST(root='./data',train=True,download=False,transform=transforms.ToTensor())
test_data = MNIST(root='./data',train=False,download=False,transform=transforms.ToTensor())
# 数据集:要加载的数据集,也就是我们刚在dataset中获取到的训练与测试数据集
# batch_size:整数类型,表明每批要加载的样本数,默认为1
# shuffle:布尔类型,表明是否要洗牌
train_loader = DataLoader(train_data,shuffle=True,batch_size=64)
test_loader = DataLoader(test_data,shuffle=False,batch_size=64)

(二)数据预处理

1.功能

在深度学习中,数据预处理(preprocessing)的重要性体现在以下几个方面:

  • 数据质量: 原始数据通常包含错误、缺失值、异常值和噪声。预处理能够检测和处理这些问题,确保数据的质量,从而避免模型因低质量数据而产生错误的学习。
  • 特征缩放和归一化: 深度学习模型对输入数据的尺度敏感,不同尺度的特征可能导致模型收敛困难。通过特征缩放和归一化,可以将特征值调整到相近的范围,帮助模型更快地收敛并提高泛化能力。
  • 特征工程: 数据预处理阶段可以进行特征工程,即创建新特征或对现有特征进行转换,以提供更有信息量的输入给模型。这有助于模型更好地捕捉数据中的模式和规律。
  • 处理分类变量: 深度学习模型通常需要数值型输入,但实际数据中可能存在分类变量。数据预处理可以将分类变量转换为适当的数值表示,使其能够被模型使用。
  • 噪声降低: 预处理可以帮助消除无关信息或噪声,从而使模型能够专注于学习真正有意义的模式,提高模型的泛化能力。
  • 模型性能: 适当的数据预处理可以改善模型的性能。经过预处理的数据有助于模型更准确地捕获数据中的规律,提高模型在新数据上的表现。
  • 模型收敛: 如果输入数据分布不一致,模型可能会在训练过程中很难收敛。预处理可以帮助调整数据分布,使模型更容易收敛。

总之,数据预处理在深度学习中扮演着至关重要的角色,能够优化数据,提高模型的性能,同时也有助于避免一些常见的问题,如过拟合、训练不稳定等。一个经过良好预处理的数据集能够为模型提供更好的输入,从而帮助模型更好地理解和解决问题

2.工具

数据预处理的方式、方法其实有很多,在这一篇文章中是说不完的,本文试图将最常用、最重要的部分拿出来跟大家讲解,即使如此也是非常浅薄的,建议大家去看一些专门讲数据预处理的文章,并结合一些实战项目进行更深入的理解~

(1)torchvision.transforms

torchvision.transforms 是一个包含了常用的图像变化方法的工具包,该工具包主要用于图像预处理、数据增强等工作之中。下面,我们将介绍 torchvision.transforms 中常用的数据处理函数。

(2)Compose()

首先让我们先来学习 torchvision.transforms.Compose(),它的参数是一个由多个 transforms 包中的方法组成的列表。简单的说,该函数的主要目的就是将所有的预处理操作进行打包,当有数据来时,我们只需要将数据传入该函数中,就能一次性对数据进行所有的预处理操作。

举个例子:

from torchvision import transforms
# 预处理:将两个步骤整合在一起
transform = transforms.Compose({
    transforms.ToTensor(), # 转为Tensor,范围改为0-1
    transforms.Normalize((0.1307,),(0.3081)) # 数据归一化,即均值为0,标准差为1
})

上面我们定义了一个预处理的集合器,我们只需要将数据传入 composed 中,PyTorch 就会自动对数据进行 ToTensor() 和 Normalize() 操作。

3.实战

这里我们来进行一个小实战(略微有点复杂,大家耐心看啦):葡萄酒数据加载与预处理,这个小实战要求我们定义数据集(上面我们获取MNIST数据集直接引入torchvision.datasets中的MNIST数据集,而在本实战中,我们要自己定义数据集),然后对数据进行预处理,其中包括归一化和转为张量操作,最后利用Compose() 对这两个预处理操作进行打包,那么我们现在就开始吧~

(1)定义数据集
from torch.utils.data import Dataset
import pandas as pd
 
 
class WineDataset(Dataset):
    # 一个数据集合继承 Dataset 即可
    
	# 初始化数据
    def __init__(self, transform):
        # 以pandas的形式读入数据
        xy = pd.read_csv("https://labfile.oss.aliyuncs.com/courses/2316/wine.csv", header=None)
        # csv数据的行数
        self.n_samples = xy.shape[0]
 
        # 这里我们就不做Tensor的转换了,将其全部放入 transform 中
        self.x_data = xy.values[:, 1:]
        self.y_data = xy.values[:, 0].reshape(-1,1) # 转为二维向量,和x匹配
        # 数据预处理集合
        self.transform = transform
 
    # 返回 dataset[index]
    def __getitem__(self, index):
        sample = self.x_data[index], self.y_data[index]
 
        if self.transform:
            sample = self.transform(sample)
 
        return sample
    
    # 返回数据长度
    def __len__(self):
        return self.n_samples
})
(2)数据预处理
  1. 数据归一化——Normalization()

谈到数据归一化,首先有一个问题就是——为什么要进行数据归一化?
在数据分析、深度学习中,经常需要对数据进行处理,数据处理时,会发现一个问题:不同维度的数据,数据范围偏差比较大,如

距离地铁的距离——房价的关系
海拔高度——氧气含量的关系

这类问题有一个共同点,就是不同维度之间数据范围相差极大,这会导致求解过程不平缓、函数收敛慢,也会导致相关性展示不明显,因此要进行数据归一化和标准化。

其中归一化就是指将数据样本中的数据进行处理,使它们处于同一量级。如 [0,1] 或者 [-1,1] 或者其它。归一化后,数据更具有可比性,如图是未进行归一化和归一化后的对比:
在这里插入图片描述
在这里插入图片描述
这会使得函数的求解过程比较平缓,更快求得最优解,如下图:
在这里插入图片描述
归一化主要有以下几种类型:

1. Min-max normalization (Rescaling)

最值归一化,归一化后的数据范围为 [0, 1],其中min max分别求样本数据的最小值和最大值。公式如下:
x ′ = x − m i n m a x − m i n x' = \frac{x-min}{max-min} x=maxminxmin
2. Mean normalization

均值归一化,归一化后的数据范围为 [-1, 1],其中mean、min、max为样本数据的平均值、最小值和最大值。公式如下:
x ′ = x − m e a n m a x − m i n x' = \frac{x-mean}{max-min} x=maxminxmean

3. Z-score normalization (Standardization)

标准差归一化,也成为标准化(标准化其实就是归一化的一种),归一化后的数据范围为实数集,其中mean、σ 分别为样本数据的均值和标准差。公式如下:
x ′ = x − m e a n σ x' = \frac{x-mean}{\sigma } x=σxmean

下面就让我们一起来看看归一化在预处理葡萄酒数据集上的应用吧~

class Normalization:
	#归一化操作
    def __call__(self, sample):
        inputs, targets = sample
        amin, amax = inputs.min(), inputs.max()  # 求最大最小值
        inputs = (inputs-amin)/(amax-amin)  # (矩阵元素-最小值)/(最大值-最小值)
        return inputs, targets
  1. 数据转化——ToTensor()
    数据的转化操作,即将原数据类型转为 Tensor,方便后续处理。
class ToTensor:
    def __call__(self, sample):
        inputs, targets = sample
        return torch.from_numpy(inputs), torch.from_numpy(targets)
  1. Compose()

最后,让我们使用这两个预处理操作,来处理葡萄酒数据。我们无需修改上面代码,只需将其封装到 Compose 中,再传入即可。

# 定义 composed
composed = torchvision.transforms.Compose([Normalization(), ToTensor()])
# 传入该参数,即可获得一系列预处理之后的数据
dataset = WineDataset(transform=composed)
(3)总结

看到这里,我们可以看出出,其实在数据加载与预处理这里,关键的一句代码就是:

dataset = WineDataset(transform=composed)

其中WineDataset()函数是数据集加载,composed是数据预处理,其他都是对这两个函数、变量进行展开,其实就是数据加载与预处理的主要工作。

如上,我们使用了自定义的预处理方法,完成了 PyTorch 类型的数据集的预处理。当然,除了自定义的预处理方法外,PyTorch 还为我们提供了很多封装好的预处理操作。

(三)模型构造

1.基本结构

pytorch中神经网络模型的构造一般基于Moudle类的模型来完成,它让模型构造更加灵活。

Moudle类:是nn模块提供的一个模型构造类,是所有神经⽹网络模块的基类,我们可以继承它来定义我们想要的模型。下面继承 Module 类构造多层感知机。这里定义的 MLP 类重载了 Module 类的 init 函数和 forward 函数。它们分别用于创建模型参数定义正向传播

import torch
from torch import nn

class MLP(nn.Module):
  # 声明带有模型参数的层,这里声明了两个全连接层
  def __init__(self, **kwargs):
  	# 有关**kwargs的含义,请看我另一篇文章:Python中的参数**kwargs是什么含义?
    # 调用MLP父类Block的构造函数来进行必要的初始化。这样在构造实例时还可以指定其他函数
    super(MLP, self).__init__(**kwargs)
    #Linear()线性层,方法签名为:
    #torch.nn.Linear(in_features, # 输入的神经元个数
    			#out_features, # 输出神经元个数
    			#bias=True # 是否包含偏置)
    #定义隐藏层,使用Linear()
    self.hidden = nn.Linear(784, 256)
    #定义激活层,使用ReLU()激活函数
    self.act = nn.ReLU()
    #定义输出层,使用Linear()
    self.output = nn.Linear(256,10)
    
   # 定义模型的前向计算,即如何根据输入x计算返回所需要的模型输出
  def forward(self, x):
    o = self.act(self.hidden(x))
    return self.output(o)   

在以上的 MLP 类中⽆须定义反向传播函数。系统将通过⾃动求梯度⽽自动⽣成反向传播所需的 backward 函数。然后可以实例化 MLP 类得到模型变量 net 。然后把数据输入到net中,此时实际上调用了forward函数来实现前向计算。
另外,关于__init__()中的 super(子类, self).init() 函数,请见我另一篇文章:一文彻底搞懂super(子类, self).init()
让我们来测试一下这个网络模型:

#随机生成(2,784)大小的张量,其值在(0,1)内均匀分布
X = torch.rand(2,784)
#实例化网络模型
net = MLP()
#查看网络模型
print(net)
#输出结果为10个类别的概率
net(X)

这里大家可能会有一个问题,为什么在执行nex(X)时会自动执行forward(),不需要显式调用呢?是因为Module中定义了__call__()函数,该函数调用了forward()函数,当执行net(x)的时候,会自动调用__call__()函数。

关于__call__(),可以看我的另一篇文章:python中的 __call__以及其与自动调用forward()的关系

2.自定义层

深度学习的一个魅力在于神经网络中各式各样的层,例如全连接层、卷积层、池化层等等。虽然PyTorch提供了⼤量常用的层,但有时候我们依然希望⾃定义层。这里我们会介绍如何使用 Module 来自定义层,从而可以被反复调用。

(1)不含参层

我们先介绍如何定义一个不含模型参数的自定义层。下⾯构造的 MyLayer 类通过继承 Module 类自定义了一个将输入减掉均值后输出的层,并将层的计算定义在了 forward 函数里。这个层里不含模型参数。

import torch
from torch import nn
 
class MyLayer(nn.Module):
    def __init__(self,**kwargs):
        super(MyLayer,self).__init__(**kwargs)
    def forward(self, x):
        return x - x.mean() 

然后我们可以实例化网络模型,进行测试:

layer = MyLayer()
layer(torch.tensor([1, 2, 3, 4, 5], dtype=torch.float))

(2)含参层

我们还可以自定义含模型参数的自定义层。其中的模型参数可以通过训练学出。一般不需要学习得到的参数为超参

Parameter 类其实是 Tensor 的子类,如果一 个 Tensor 是 Parameter ,那么它会⾃动被添加到模型的参数列表里。所以在⾃定义含模型参数的层时,我们应该将参数定义成 Parameter ,除了直接定义成 Parameter 类外,还可以使⽤ ParameterList 和 ParameterDict 分别定义参数的列表和字典。

class MyListDense(nn.Module):
    def __init__(self):
        super(MyListDense, self).__init__()
        self.params = nn.ParameterList([nn.Parameter(torch.randn(4, 4)) for i in range(3)])
        self.params.append(nn.Parameter(torch.randn(4, 1)))

    def forward(self, x):
        for i in range(len(self.params)):
            x = torch.mm(x, self.params[i])
        return x

# 实例化
net = MyListDense()
print(net)

另外,还有一些神经网络中常见的层,例如卷积层、池化层、以及AlexNet、LeNet等,让我们一起来实现一下~

  1. 卷积层

二维卷积层将输入和卷积核做互相关运算,并加上一个标量偏差来得到输出。卷积层的模型参数包括了卷积核和标量偏差。在训练模型的时候,通常我们先对卷积核随机初始化,然后不断迭代卷积核和偏差。

import torch
from torch import nn


def corr2d(X, K): #@save
    '''计算二维互相关运算'''
    h, w = K.shape
    X, K = X.float(), K.float()
    Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            Y[i, j] = (X[i: i + h, j: j + w] * K).sum()
    return Y

# 二维卷积层
class Conv2D(nn.Module):
    def __init__(self, kernel_size):
        super(Conv2D, self).__init__()
        self.weight = nn.Parameter(torch.randn(kernel_size))
        self.bias = nn.Parameter(torch.randn(1))

    def forward(self, x):
        return corr2d(x, self.weight) + self.bias

  1. 池化层

池化层每次对输入数据的一个固定形状窗口(⼜称池化窗口)中的元素计算输出。不同于卷积层里计算输⼊和核的互相关性,池化层直接计算池化窗口内元素的最大值或者平均值。该运算也 分别叫做最大汇聚层或平均汇聚层。在二维最⼤池化中,池化窗口从输入数组的最左上方开始,按从左往右、从上往下的顺序,依次在输⼊数组上滑动。当池化窗口滑动到某⼀位置时,窗口中的输入子数组的最大值即输出数组中相应位置的元素。

import torch
from torch import nn

def pool2d(X, pool_size, mode='max'):
    p_h, p_w = pool_size
    Y = torch.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1))
    for i in range(Y.shape[0]):
        for j in range(Y.shape[1]):
            if mode == 'max':
                Y[i, j] = X[i: i + p_h, j: j + p_w].max()
            elif mode == 'avg':
                Y[i, j] = X[i: i + p_h, j: j + p_w].mean()
    return Y

#测试
X = torch.tensor([[0, 1, 2], [3, 4, 5], [6, 7, 8]], dtype=torch.float)
pool2d(X, (2, 2))

(四)模型训练

模型训练其实就是将dataloader加载好的一批一批数据送入模型中进行训练,不同项目的训练代码有很大差异,不过大致可以分为以下几步:

1.加载数据

在数据预处理中,我们已经通过dataloader得到了train_loader

    for index,data in enumerate(train_loader):
        input,target = data # input为输入数据,target为目标值

2.模型预测

将输入输进模型

y_predict = model(input) # 模型预测

3.计算损失

提前定义交叉熵损失

criterion = nn.CrossEntropyLoss() # 交叉熵损失,相当于Softmax+Log+NllLoss

计算损失

loss = criterion(y_predict,target) # 计算损失

4.反向传播与参数更新

在反向传播这里,我们需要用到backward()函数,backward() 函数是PyTorch框架中自动求梯度功能的一部分,它负责执行反向传播算法以计算模型参数的梯度。

当调用 .backward() 时,PyTorch会从当前张量开始沿着计算图回溯,根据链式法则计算每个叶子节点(即最初具有 requires_grad=True 属性的输入张量)对当前目标张量(这里是 tensor)的梯度。

在完成反向传播后,我们就可以对参数进行更新了。

        loss.backward() # 反向传播
        optimizer.step() # 更新参数

5.打印输出

为了观察损失的变化,我们可以在训练的时候,每隔一段时间就打印一次损失

print("损失值为:%.2f" % loss.item())

全部代码如下:

# 模型训练
model = Model()
criterion = nn.CrossEntropyLoss() # 交叉熵损失,相当于Softmax+Log+NllLoss
optimizer = torch.optim.SGD(model.parameters(),0.8) # 第一个参数是初始化参数值,第二个参数是学习率

def train():
    for index,data in enumerate(train_loader):
        input,target = data # input为输入数据,target为目标值
        optimizer.zero_grad() # 梯度清零
        y_predict = model(input) # 模型预测
        loss = criterion(y_predict,target) # 计算损失
        loss.backward() # 反向传播
        optimizer.step() # 更新参数
        if index % 100 == 0: # 每一百次保存一次模型,打印损失
            torch.save(model.state_dict(),"./model/model.pkl") # 保存模型
            torch.save(optimizer.state_dict(),"./model/optimizer.pkl")
            print("损失值为:%.2f" % loss.item())

(五)模型保存与加载

训练模型时,最好将模型与参数保存,可以每隔一段时间保存一次,也可以全部训练完再保存,这里有两种方法:

1.方法一:同时保存模型和参数

# 保存(vgg16是模型,vgg16_methond1.pth是保存的名称)
torch.save(vgg16,"vgg16_methond1.pth")
# 加载
model = torch.load("vgg16_methond1.pth")

2.方法二:仅保存参数(推荐)

# 保存
torch.save(vgg16.state_dict(),"vgg16_methond2.pth")
# 加载
model2= vgg16(classes=2019)                  # 初始化网络结构
vgg16_dict = torch.load("vgg16_methond2.pth")# 加载参数
model2.load_state_dict(vgg16_dict )          # 将参数加载到网络中去

在阅读一些Pytorch项目代码时,我们会发现,有的模型文件后缀为.pt,有的是.pth,.pkl,那么这几种模型文件在格式上有什么区别吗?

答案是:它们并不存在格式上的区别,只是后缀名不同而已。在用torch.save()函数保存模型文件的时候,有些人喜欢用.pt后缀,有些人喜欢用.pth或 .pkl,用相同的 torch.save()语句保存出来的模型文件没有什么不同

(六)模型测试

测试和训练的套路很相似,无非就是将train_loader的数据换位test_loader,这里给出测试代码。

# 模型测试
def test():
    correct = 0 # 正确预测的个数
    total = 0 # 总数
    with torch.no_grad(): # 测试不用计算梯度
        for data in test_loader:
            input,target = data
            output=model(input) # output输出10个预测取值,其中最大的即为预测的数
            probability,predict=torch.max(output.data,dim=1) # 返回一个元组,第一个为最大概率值,第二个为最大值的下标
            total += target.size(0) # target是形状为(batch_size,1)的矩阵,使用size(0)取出该批的大小
            correct += (predict == target).sum().item() # predict和target均为(batch_size,1)的矩阵,sum()求出相等的个数
        print("准确率为:%.2f" % (correct / total))

到这里,深度学习项目结构基础的内容大致就讲完了~ 在下两篇文章里,我们会继续来看一个简单的(一个.py文件实现)深度学习项目和稍复杂的(多个.py文件实现)深度学习项目。本文很多地方概括得还不够全面,在未来的学习中,我也会尽可能地不断地完善,感谢大家关注!

写在后面

这个专栏主要是我在实现深度学习项目中总结的一些问题,以备未来笔试和面试之需,本篇文章聚焦于深度学习项目实现基础的内容,其中参考了很多博主的总结(见下方参考文章),不过由于学习的不深入,也只是走马观花,很多问题总结得也不是很透彻,望读者见谅,如果有错误和不足之处,还望大家在评论区指出。希望能给大家的学习带来一点帮助,共同进步!!!

参考文章:
[1] CSDN文章:【深度学习】——利用pytorch搭建一个完整的深度学习项目(构建模型、加载数据集、参数配置、训练、模型保存、预测): 链接
[2] CSDN文章:基于CNN的MINIST手写数字识别项目代码以及原理详解: 链接
[3] CSDN文章:PyTorch 深度学习框架 torch、torchvision、libtorch 库,以及将 PyTorch 模型导出为 TorchScript(.ts 文件): 链接
[4] CSDN文章:深度学习数据预处理: 链接
[5] CSDN文章:【PyTorch】第八节:数据的预处理: 链接
[6] CSDN文章:【深度学习】数据归一化/标准化 Normalization/Standardization: 链接
[7] CSDN文章: 深度学习——模型构建 Normalization/Standardization: 链接

  • 41
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值