Pytorch入门实战(2) 您所在的位置:网站首页 pytorch搭建bp神经网络分类 Pytorch入门实战(2)

Pytorch入门实战(2)

#Pytorch入门实战(2)| 来源: 网络整理| 查看: 265

代码地址

上一篇:Pytorch入门实战(1) - 实现线性回归

涉及知识点

Pytorch nn.Module的基本使用

Pytorch nn.Linear的基本用法

PytorchVision Transforms的基本使用

Pytorch中DataLoader的基本用法

Pytorch详解NLLLoss和CrossEntropyLoss

如何确定神经网络的层数和隐藏层神经元数量

本文内容

本文将会使用BP神经网络(就是最普通的神经网络)实现一个MNIST手写数据集的实现。话不多说,直接开始。

首先先导入需要的包:

import os import numpy as np import torch import torchvision import matplotlib.pyplot as plt from time import time from torchvision import datasets, transforms from torch import nn, optim

定义transform对象,其定义了数据集中的图片应该做怎样的处理:

transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,)),])

加载和下载训练数据集,这里使用pytorch提供的API进行下载:

train_set = datasets.MNIST('train_set', # 下载到该文件夹下 download=not os.path.exists('train_set'), # 是否下载,如果下载过,则不重复下载 train=True, # 是否为训练集 transform=transform # 要对图片做的transform ) train_set Dataset MNIST Number of datapoints: 60000 Root location: train_set Split: Train StandardTransform Transform: Compose( ToTensor() Normalize(mean=(0.5,), std=(0.5,)) )

等待一段时间下载成功后,可以看到训练集中一共有6w个数据,接下来下载测试数据集:

test_set = datasets.MNIST('test_set', download=not os.path.exists('test_set'), train=False, transform=transform ) test_set Dataset MNIST Number of datapoints: 10000 Root location: test_set Split: Test StandardTransform Transform: Compose( ToTensor() Normalize(mean=(0.5,), std=(0.5,)) )

测试数据集包含1w条数据

接下来构建训练数据集和测试数据集的DataLoader对象:

train_loader = torch.utils.data.DataLoader(train_set, batch_size=64, shuffle=True) test_loader = torch.utils.data.DataLoader(test_set, batch_size=64, shuffle=True) dataiter = iter(train_loader) images, labels = dataiter.next() print(images.shape) print(labels.shape) torch.Size([64, 1, 28, 28]) torch.Size([64])

在上面,我们将其分成64个一组的图片,每个图片只有一个通道(灰度图),大小为28x28。抽一张绘制一下:

plt.imshow(images[0].numpy().squeeze(), cmap='gray_r');

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y9mFdvWM-1644145945684)(output_16_0.png)]

到这里,前期准备工作就结束了。

开始定义神经网络

class NerualNetwork(nn.Module): def __init__(self): super().__init__() """ 定义第一个线性层, 输入为图片(28x28), 输出为第一个隐层的输入,大小为128。 """ self.linear1 = nn.Linear(28 * 28, 128) # 在第一个隐层使用ReLU激活函数 self.relu1 = nn.ReLU() """ 定义第二个线性层, 输入是第一个隐层的输出, 输出为第二个隐层的输入,大小为64。 """ self.linear2 = nn.Linear(128, 64) # 在第二个隐层使用ReLU激活函数 self.relu2 = nn.ReLU() """ 定义第三个线性层, 输入是第二个隐层的输出, 输出为输出层,大小为10 """ self.linear3 = nn.Linear(64, 10) # 最终的输出经过softmax进行归一化 self.softmax = nn.LogSoftmax(dim=1) # 上述动作可以直接使用nn.Sequential写成如下形式: self.model = nn.Sequential(nn.Linear(28 * 28, 128), nn.ReLU(), nn.Linear(128, 64), nn.ReLU(), nn.Linear(64, 10), nn.LogSoftmax(dim=1) ) def forward(self, x): """ 定义神经网络的前向传播 x: 图片数据, shape为(64, 1, 28, 28) """ # 首先将x的shape转为(64, 784) x = x.view(x.shape[0], -1) # 接下来进行前向传播 x = self.linear1(x) x = self.relu1(x) x = self.linear2(x) x = self.relu2(x) x = self.linear3(x) x = self.softmax(x) # 上述一串,可以直接使用 x = self.model(x) 代替。 return x model = NerualNetwork()

神经网络定义完后,开始定义损失函数,这里选用负对数似然损失函数(NLLLoss, negative log likelihood loss),其常用于分类任务。详情可参考链接

criterion = nn.NLLLoss()

接下来定义优化器,这里使用随机梯度下降法,学习率设置为0.003,momentum取默认的0.9(用于防止过拟合)

optimizer = optim.SGD(model.parameters(), lr=0.003, momentum=0.9)

准备工作完毕,开始训练数据集:

time0 = time() # 记录下当前时间 epochs = 15 # 一共训练15轮 for e in range(epochs): running_loss = 0 # 本轮的损失值 for images, labels in train_loader: # 前向传播获取预测值 output = model(images) # 计算损失 loss = criterion(output, labels) # 进行反向传播 loss.backward() # 更新权重 optimizer.step() # 清空梯度 optimizer.zero_grad() # 累加损失 running_loss += loss.item() else: # 一轮循环结束后打印本轮的损失函数 print("Epoch {} - Training loss: {}".format(e, running_loss/len(train_loader))) # 打印总的训练时间 print("\nTraining Time (in minutes) =",(time()-time0)/60) Epoch 0 - Training loss: 0.6462286284117937 Epoch 1 - Training loss: 0.27847810615418056 Epoch 2 - Training loss: 0.21768317640081905 Epoch 3 - Training loss: 0.17949896098088736 Epoch 4 - Training loss: 0.1514430489978874 Epoch 5 - Training loss: 0.12892813527329103 Epoch 6 - Training loss: 0.11302738852882341 Epoch 7 - Training loss: 0.09980541475113235 Epoch 8 - Training loss: 0.08899609394905679 Epoch 9 - Training loss: 0.0805584444001174 Epoch 10 - Training loss: 0.07290568387211323 Epoch 11 - Training loss: 0.06743549962075296 Epoch 12 - Training loss: 0.06314737589380491 Epoch 13 - Training loss: 0.056689855163551565 Epoch 14 - Training loss: 0.05361823974547586 Training Time (in minutes) = 2.9436919848124186

最终在我这台机器上,花费了2分多钟完成了训练。可以看到,损失是越来越小的。

接下来进行模型的评估

correct_count, all_count = 0, 0 model.eval() # 将模型设置为评估模式 # 从test_loader中一批一批加载图片 for images,labels in test_loader: # 循环检测这一批图片 for i in range(len(labels)): logps = model(images[i]) # 进行前向传播,获取预测值 probab = list(logps.detach().numpy()[0]) # 将预测结果转为概率列表。[0]是取第一张照片的10个数字的概率列表(因为一次只预测一张照片) pred_label = probab.index(max(probab)) # 取最大的index作为预测结果 true_label = labels.numpy()[i] if(true_label == pred_label): # 判断是否预测正确 correct_count += 1 all_count += 1 print("Number Of Images Tested =", all_count) print("\nModel Accuracy =", (correct_count/all_count)) Number Of Images Tested = 10000 Model Accuracy = 0.9741

最终,本次训练在测试数据集上的精准率为97.41%

参考资料

Handwritten Digit Recognition Using PyTorch — Intro To Neural Networks: https://towardsdatascience.com/handwritten-digit-mnist-pytorch-977b5338e627



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有