用pytorch实现神经网络

章节设置:
一、实现自带数据并自定义神经网络进行训练
二、使用自带的模型进行训练以及测试
三、用自己定义神经网络

全局设定,指定了设备

事实证明,即使是1650这样的显卡也会比cpu运行得快很多,只要运行的时候显存够就行,在使用的时候有两种方式(注意——还有其他指定显卡的方式,比如cuda(),只是这种更通用,更熟悉而已):

  1. model.to(device)
  2. tensor变量.to(device)

device = "cuda" if torch.cuda.is_available() else "cpu"

print(f"Using {device} device")

用pytorch实现神经网络

一、实现官方数据集并自定义神经网络进行训练

放在这个示例的理解:获得dataset数据–>利用加载器进行数据加载–>设计神经网络的结构–>定义优化器以及损失函数–>遍历数据进行梯度下降迭代求解最佳的梯度值–>用模型进行预测得到预测值
通用理解:数据加载–>设计网络结构–>遍历数据进行梯度下降求解到损失值的最小值或者指定次数–>保存对应的梯度参数或者直接计算test情况
通过pytorch设计网络结构,需要完成以下几点:

  1. 定义网络结构,初始化函数init
  2. 定义网络节点连接方式forward函数

1. 获得dataset数据

通过从内置的数据集中获取数据,和之前的方式一样,只不过内置的给你写好了torchvision.datasets.mnist.MNIST.py,以下解释相关变量的定义

解释torchvision.datasets.mnist.MNIST. init .data相关定义以及是怎么来的

test_data = torchvision.datasets.MNIST('./mnist',train=False)

test_x = torch.unsqueeze(test_data.data, dim=1).type(torch.FloatTensor)[:2000] / 255.

对于这里面的 test_data.data的理解, torchvision.datasets.mnist.MNIST.__init__.data可以看他们的调用关系,它其实是通过MNIST类的__init__进行对象的建立,所以获得的是最终的对象,如下所示:

对象=torchvision.datasets.mnist.MNIST.__init__()
对象具有data属性,所以就可以调用对象.data
综合起来就是: torchvision.datasets.mnist.MNIST.__init__.data

在python的类只要函数里面调用了 self.属性=相关定义赋值,那么之后python的类就具有这样的功能。

之所以要进行维度的拓展就是因为cnn的输入是 1*28*28,所以数据需要转换为 batch_size*1*28*28,而扩展纬度就是通过unsqueeze,而有时候需要进行维度的统一就是通过unsqueeze以及expand,所以下面对unsqueeze以及expand的使用方法进行探究

  • unsqueeze可以增加一个纬度,但是维度的siz只是1而已,而expand就可以将数据进行复制,将数据变为n
import torch

nn1=torch.rand(1,3)
print(nn1)

nn1=nn1.unsqueeze(0)
print("*"*100)
print(nn1)

nn1=nn1.expand(1,3,3)
print("*"*100)
print(nn1)

用pytorch实现神经网络

2. 利用加载器进行数据加载

分为训练数据以及测试,由于训练数据需要分批次以及打乱操作等。所以加载方式会有所不同,或者可以可以测试数据的加载更加简单粗暴一些:

  1. 训练集数据的加载:通过dataset加载数据集–>将数据集加载进加载器中(加载中可以设置一批次迭代的次数还有是否打乱)
  2. 测试集数据的加载:可以直接加载数据以及对应的目标值就行

train_data=torchvision.datasets.MNIST(
    root='./mnist',
    train=True,
    transform=torchvision.transforms.ToTensor(),
    download=DOWNLOAD_MNIST
)
train_loader=Data.DataLoader(dataset=train_data,batch_size=BATCH_SIZE,shuffle=True,num_workers=0)

test_data = torchvision.datasets.MNIST('./mnist',train=False)

test_x = torch.unsqueeze(test_data.data, dim=1).type(torch.FloatTensor)[:2000] / 255.

test_y=test_data.targets[:2000]

3. 设计神经网络的结构

将神经网络中核心函数 init()以及 forward()函数实现就行

  1. init()是实现网络中有哪些层的;
  2. forward()是实现网络中不同连接的层的连接关系的;
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1=nn.Sequential(
            nn.Conv2d(
                in_channels=1,
                out_channels=16,
                kernel_size=5,
                stride=1,
                padding=2,
            ),
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2),
        )
        self.conv2=nn.Sequential(
            nn.Conv2d(16,32,5,1,2),
            nn.ReLU(),
            nn.MaxPool2d(2),
        )
        self.out=nn.Linear(32*7*7,10)

    def forward(self,x):
        x=self.conv1(x)
        x=self.conv2(x)
        x=x.view(x.size(0),-1)
        output=self.out(x)
        return output

4. 定义优化器以及损失函数

optimizer = torch.optim.Adam(cnn.parameters(),lr=LR)
print(cnn.parameters())
loss_func = nn.CrossEntropyLoss()

5. 遍历数据进行梯度下降

梯度下降+每到50次进行相关信息的输出或者一些处理

梯度下降

  1. 确定函数中优化器以及损失函数都已经设置好了
  2. 损失函数定义以及调用 loss = loss_func(output, y)
  3. 优化器的置零: optimizer.zero_grad()
  4. 反向传播: loss.backward()
  5. 梯度迭代更新: optimizer.step()

批量输出相关信息或者批量处理数据

批量处理数据,也就是epoch=50,这里没有设置相关的变量而是用 if step % 50 == 0:#表示已经进行了50的倍数了进行判断了,并且这里只做了相关的输出,并没有其他的操作(比如有时候可以对方差做一个汇总使得信息的整体性更强)

for epoch in range(EPOCH):
    for step, (x, y) in enumerate(train_loader):

        output = cnn(x)
        loss = loss_func(output, y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if step % 50 == 0:
            test_output = cnn(test_x)

            pred_y = torch.max(test_output, 1)[1].data.numpy()

            accuracy = sum(pred_y == test_y.data.numpy()) / test_y.size(0)
            print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.2f' % accuracy)

6. 用模型进行预测得到预测值

torch.max的使用见:https://blog.csdn.net/weixin_42295969/article/details/126352240?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22126352240%22%2C%22source%22%3A%22weixin_42295969%22%7D


test_output = cnn(test_x[:10])

pred_y = torch.max(test_output, 1)[1].data.numpy()
print(pred_y, 'prediction number')
print(test_y[:10].numpy(), 'real number')

代码:
链接:https://pan.baidu.com/s/1m6GE2Qkx6YZEYUcCnHn0ow?pwd=cu0s
提取码:cu0s

二、使用自带的模型进行训练以及测试

备注:与《一》使用相同的数据,代码在代码
与前面的对比(括号内是这个进行的改动):1、获得dataset数据–>2、利用加载器进行数据加载–>3、设计神经网络的结构(直接导入已有的神经网络结构)–>4、定义优化器以及损失函数–>5、遍历数据进行梯度下降求解–>6、用模型进行预测得到预测值
注意:核心关注3,这是与前面不同的地方,并且增加了6预测的对比,如果对预测感兴趣,可以参考6(文中已高亮标记)

1-2 获得dataset数据–>利用加载器进行数据加载

与之前的一样进行加载数据

3. 神经网络的设计

可以直接导入自带的神经网络,这里以导入ResNet网络为例:

'''
    随着模型的加深,需要训练的模型参数量增加,相同的训练次数下模型训练准确率起来得更慢
'''

'''        VGG系列    '''

'''        ResNet系列    '''

model = resnet101(pretrained=False, num_classes=5).to(device)

示例说明

from torchvision.models import resnet18, resnet34,resnet50, resnet101, resnet152
model = resnet101(pretrained=False, num_classes=5).to(device)
print(model)

用pytorch实现神经网络

4、定义优化器以及损失函数

与前面一样的定义方法,先定义后调用

5、遍历数据进行梯度下降求解

迭代进行训练以及测试,其中训练的函数 train里就保存了进行梯度下降求解的方法

包含梯度下降求解法的train

这里就将所有的数据训练了一轮就行,复杂的就会涉及到epoch以及batch_size的概念

  • 当一个完整的数据集通过了神经网络一次并且返回了一次,这个过程称为一个 epoch。
  • 在不能将数据一次性通过神经网络的时候,就需要将数据集分成几个 batch,所以下面的batch仅仅只是表示批次。

def train(dataloader, model, loss_fn, optimizer):
    size = len(dataloader.dataset)

    for batch, (X, y) in enumerate(dataloader):

        X, y = X.to(device), y.to(device)

        pred = model(X)

        loss = loss_fn(pred, y)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if batch % 10 == 0:
            loss, current = loss.item(), batch * len(X)
            print(f"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]")

6、用模型进行预测得到预测值

设置为测试模型并设置不计算梯度,进行测试数据集的加载,判断预测值与实际标签是否一致,统一正确信息个数

设置为测试模型并设置不计算梯度


model.eval()

with torch.no_grad():

    for X, y in dataloader:
        加载数据
        pred = model(X)

        test_loss += loss_fn(pred, y).item()

        correct += (pred.argmax(1) == y).type(torch.float).sum().item()
test_loss /= size
correct /= size
print(f"correct = {correct}, Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n")

7. 保存好训练好的模型

torch.save(model.state_dict(), "model_resnet101.pth")
print("Saved PyTorch Model Success!")

用pytorch实现神经网络
代码:https://gitee.com/sxh_and_ll/AI-CV/tree/master/proj/%E4%BD%BF%E7%94%A8pytorch%E8%87%AA%E5%B8%A6%E6%A8%A1%E5%9E%8B%E8%AE%AD%E7%BB%83%E4%BB%A5%E5%8F%8A%E6%B5%8B%E8%AF%95

三、使用自己定义神经网络

使用自己定义的神经网络仅仅只是要写神经网络结构就是,只需要将模型继承 nn.moudle类,另外实现 init以及 forward方法就行

Original: https://blog.csdn.net/weixin_42295969/article/details/126352278
Author: 徽先生
Title: 用pytorch实现神经网络

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/705905/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球