深度学习与图像识别38 PyTorch实现神经网络图像分类MNI
第一个案例我们使用MNIST数据集来进行手写数字的识别。 1.数据准备 数据准备其实非常容易,PyTorch已经为我们准备了完整的MNIST数据集供我们下载,实现代码具体如下:
import torch
from torch.utils.data import DataLoader
import torchvision.datasets as dsets
import torchvision.transforms as transforms
batch_size = 100
# MNIST dataset
train_dataset = dsets.MNIST(root = '/pymnist', #选择数据的根目录
train = True, #选择训练集
transform = transforms.ToTensor(), #转换成Tensor变量 download = True) #从网络上下载图片
test_dataset = dsets.MNIST(root = '/pymnist', #选择数据的根目录
train = False, #选择测试集
transform = transforms.ToTensor(), #转换成Tensor变量
download = True) #从网络上下载图片
#加载数据
train_loader = torch.utils.data.DataLoader(dataset = train_dataset,
batch_size = batch_size, #使用批次数据
shuffle = True) #将数据打乱
test_loader = torch.utils.data.DataLoader(dataset = test_dataset,
batch_size = batch_size,
shuffle = True) 下面我们来查看下原始数
据以及打乱后的批次数据,具体如下: #原始数据
print("train_data:", train_dataset.train_data.size())
print("train_labels:", train_dataset.train_labels.size())
print("test_data:", test_dataset.test_data.size())
print("test_labels:", test_dataset.test_labels.size())
#数据打乱取小批次
print('批次的尺寸:',train_load er.batch_size)
print('load_train_data:',train_loader.dataset.train_data.shape)
print('load_train_labels:',train_loader.dataset.train_labels.shape) 输出结果具体如下: train_data: torch.Size([60000, 28, 28])
train_labels: torch.Size([60000])
test_data: torch.Size([10000, 28, 28])
test_labels: torch.Size([10000])
批次的尺寸: 100
load_train_data: torch.Size([60000, 28, 28])
load_train_labels: torch.Size([60000])
从输出结果中,我们可以看到原始数据和数据打乱按照批次读取的数据集的总行数是一样的,实际操作的时候,train_loader以及test_loader将作为神经网络的输入数据源。
2.定义神经网络 在讲解完如何通过PyTorch加载数据源之后,接下来我们看一下如何通过PyTorch定义一个简单的神经网络。示例代码如下:
import torch.nn as nn
import torch
input_size = 784 #mnist的像素为28*28
hidden_size = 500
num_classes = 10 #输出为10个类别分别对应于0~9 #创建神经网络模型
class Neural_net(nn.Module):
#初始化函数,接受自定义输入特征的维数,隐含层特征维数以及输出层特征维数
def __init__(self, input_num,hidden_size, out_put):
super(Neural_net, self).__init__()
self.layer1 = nn.Linear(input_num, hidden_size) #从输入到隐藏层的线性处理
self.layer2 = nn.Linear(hid den_size, out_put) #从隐藏层到输出层的线性处理
def forward(self, x):
out = self.layer1(x) #输入层到隐藏层的线性计算
out = torch.relu(out) #隐藏层激活
out = self.layer2(out) #输出层,注意,输出层直接接Loss
return out
net = Neural_net(input_size, hidden_size, num_classes)
print(net)
上述代码中为了方便读者理解,加入了很多注释,现在就来对上述代码做额外的补充解释:自定义神经网络模型在PyTorch中需要继承Module,然后用户自己重写Forward方法完成前向计算,因此我们的类Neural_net必须继承torch.nn.Module。
网络结构打印的输出结果具体如下:
Neural_net( (layer1): Linear(in_features=784, out_features=500, bias=True)
(layer2): Linear(in_features=500, out_features=10, bias=True)
)
3.训练 用于训练的示例代码具体如下:
# optimization
from torch.autograd import Variable import numpy as np
learning_rate = 1e-1 #学习率
num_epoches = 5
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr = learning_rate)#使用随机梯度下降
for epoch in range(num_epoches):
print('current epoch = %d' % epoch)
for i, (images, labels) in enu
merate(train_loader): #利用enumerate取出一个
可迭代对象的内容
images = Variable(images.view(-1, 28 * 28))
labels = Variable(labels)
outputs = net(images) #将数据集传入网络做前向计算
loss = criterion(outputs, labels) #计算Loss
optimizer.zero_grad() #在做反向传播之前先清除下网 络状态
loss.backward() #Loss反向传播
optimizer.step() #更新参数
if i % 100 == 0:
print('current loss = %.5f' % loss.item())
print('finished training')
4.测试集准确度测试 我们接着来测试下,各层 的权重通过随机梯度下降法更新Loss之后,针对测试集数字分类的准确率,具体代码如下:
#做prediction
total = 0
correct = 0
for images, labels in test_loader:
images = Variable(images.view(-1, 28 * 28))
outputs = net(images)
_, predicts = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicts == labels).sum()
print('Accuracy = %.2f' % (100 * correct / total))
最后的准确率大约在96%左右,比之前我们用KNN方法得到的(95%)效果还要更好些。