PyTorch可以说是三大主流框架中最适合初学者学习的了,相较于其他主流框架,PyTorch的简单易用性使其成为初学者们的首选。这样我想要强调的一点是,框架可以类比为编程语言,仅为我们实现项目效果的工具,也就是我们造车使用的轮子,我们重点需要的是理解如何使用Torch去实现功能而不要过度在意轮子是要怎么做出来的,那样会牵扯我们太多学习时间。以后就出一系列专门细解深度学习框架的文章,但是那是较后期我们对深度学习的理论知识和实践操作都比较熟悉才好开始学习,现阶段我们最需要的是学会如何使用这些工具。
深度学习的内容不是那么好掌握的,包含大量的数学理论知识以及大量的计算公式原理需要推理。且如果不进行实际操作很难够理解我们写的代码究极在神经网络计算框架中代表什么作用。不过我会尽可能将知识简化,转换为我们比较熟悉的内容,我将尽力让大家了解并熟悉神经网络框架,保证能够理解通畅以及推演顺利的条件之下,尽量不使用过多的数学公式和专业理论知识。以一篇文章快速了解并实现该算法,以效率最高的方式熟练这些知识。
博主专注数据建模四年,参与过大大小小数十来次数学建模,理解各类模型原理以及每种模型的建模流程和各类题目分析方法。此专栏的目的就是为了让零基础快速使用各类数学模型、机器学习和深度学习以及代码,每一篇文章都包含实战项目以及可运行代码。博主紧跟各类数模比赛,每场数模竞赛博主都会将最新的思路和代码写进此专栏以及详细思路和完全代码。希望有需求的小伙伴不要错过笔者精心打造的专栏。
MNIST(Modified National Institute of Standards and Technology)是一个手写数字数据集,通常用于训练各种图像处理系统。
它包含了大量的手写数字图像,这些数字从0到9。每个图像都是一个灰度图像,大小为28x28像素,表示了一个手写数字。
MNIST数据集分成两部分:训练集和测试集。训练集通常包含60,000张图像,用于训练模型。测试集包含10,000张图像,用于评估模型的性能。
MNIST数据集是一个非常受欢迎的数据集,被用于测试和验证各种机器学习和深度学习模型,特别是在图像识别任务中。大家可以直接访问官网下载或者是在程序中使用torchvision下载数据集。
一共4个文件,训练集、训练集标签、测试集、测试集标签:
文件名称 | 大小 | 内容 |
---|---|---|
train-labels-idx1-ubyte.gz | 9,681 kb | 55000张训练集,5000张验证集 |
train-labels-idx1-ubyte.gz | 29 kb | 训练集图片对应的标签 |
t10k-images-idx3-ubyte.gz | 1,611 kb | 10000张测试集 |
t10k-labels-idx1-ubyte.gz | 5 kb | 测试集图片对应的标签 |
程序加载MNIST数据集:
- from torch.utils.data import DataLoader
- import torchvision.datasets as dsets
-
- transform = transforms.Compose([
- transforms.Grayscale(num_output_channels=1), # 将图像转为灰度
- transforms.ToTensor(), # 将图像转为张量
- transforms.Normalize((0.1307,), (0.3081,))
- ])
-
- #MNIST dataset
- train_dataset = dsets.MNIST(root = '/ml/pymnist', #选择数据的根目录
- train = True, #选择训练集
- transform = transform, #不考虑使用任何数据预处理
- download = True #从网络上下载图片
- )
- test_dataset = dsets.MNIST(root = '/ml/pymnist',#选择数据的根目录
- train = False,#选择测试集
- transform = transform, #不考虑使用任何数据预处理
- 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
- )
图片展示:
- import matplotlib.pyplot as plt
- digit = train_dataset.train_data[0]
- plt.imshow(digit,cmap=plt.cm.binary,interpolation='none')
- plt.title("Labels: {}".format(train_dataset.train_labels[0]))
- plt.show()
之后需要切分数据集,分为训练集和测试集,MNIST数据集已经做好了直接使用就好了:
- 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())
train_data: torch.Size([60000, 28, 28]) train_labels: torch.Size([60000]) test_data: torch.Size([10000, 28, 28]) test_labels: torch.Size([10000])
还需要确定批次的尺寸,在神经网络训练中,batch_size
是指每次迭代训练时,模型同时处理的样本数量。它在训练过程中起到了几个重要作用:
总的来说,合理选择合适的batch_size
可以使训练过程更加高效、稳定,并且能够提高模型的泛化能力。然而,过大的batch_size
可能会导致内存溢出或训练速度变慢,过小的batch_size
可能会导致模型收敛困难。因此,选择合适的batch_size
需要在实践中进行调试和优化。
- print("批次的尺寸:",train_loader.batch_size)
- print("load_train_data:",train_loader.dataset.train_data.shape)
- print("load_train_labels:",train_loader.dataset.train_labels.shape)
批次的尺寸: 100 load_train_data: torch.Size([60000, 28, 28]) load_train_labels: torch.Size([60000])
从输出结果中,可以看到原始数据集和数据打乱按照批次读取的数据集的总行数是一样的,实际操作中train_loader以及test_loader将作为神经网络的输入数据源。
在前面的文章中已经带着大家搭建过好几遍神经网络了,注意初始化网络和对应的输入层,隐藏层和输出层。
- 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(hidden_size,out_put) #从隐藏层到输出层的线性处理
-
- def forward(self,x):
- x = self.layer1(x) #输入层到隐藏层的线性计算
- x = torch.relu(x) #隐藏层激活
- x = self.layer2(x) #输出层,注意,输出层直接接loss
- return x
-
- net = Neural_net(input_size,hidden_size,num_classes)
- print(net)
Neural_net( (layer1): Linear(in_features=784, out_features=500, bias=True) (layer2): Linear(in_features=500, out_features=10, bias=True) )
super(Neural_net, self).init() 是 Python 中用于调用父类的方法或属性的一种方式。在这里,Neural_net 是你定义的神经网络模型的类名,它继承了 nn.Module 类,而 nn.Module 是 PyTorch 中用于构建神经网络模型的基类。也就是说,你的神经网络模型会继承 nn.Module 的所有属性和方法,这样你可以在 Neural_net 类中使用 nn.Module 中定义的各种功能,比如添加神经网络层、指定损失函数等。
只有要注意一下Variable,之前的文章中又提到过Variable。
Variable是PyTorch早期版本(0.4版本之前)中用于构建计算图的抽象,它包含了data、grad和grad_fn等属性,可以用于构建计算图,并在反向传播时自动计算梯度。但从PyTorch 0.4版本开始,Variable被官方废弃,而Tensor直接支持了自动求导功能,不再需要显式地创建Variable。
因此,Autograd是PyTorch实现自动求导的核心机制,而Variable是早期版本中用于构建计算图的一种抽象,现在已经被Tensor所取代。 Autograd会自动追踪Tensor上的操作,并在需要时计算梯度,从而实现反向传播。
- #optimization
- import numpy as np
- from torchvision import transforms
-
- learning_rate = 1e-3 #学习率
- 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 enumerate(train_loader,0):
- images=images.view(-1,28*28)
- outputs = net(images) #将数据集传入网络做前向计算
- labels = torch.tensor(labels, dtype=torch.long)
-
- 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')
current epoch = 1 current loss = 0.27720 current loss = 0.23612 current loss = 0.39341 current loss = 0.24683 current loss = 0.18913 current loss = 0.31647 current loss = 0.28518 current loss = 0.18053 current loss = 0.34957 current loss = 0.31319 current epoch = 2 current loss = 0.15138 current loss = 0.30887 current loss = 0.24257 current loss = 0.46326 current loss = 0.30790 current loss = 0.17516 current loss = 0.32319 current loss = 0.32325 current loss = 0.32066 current loss = 0.24271
各层的权重通过随机梯度下降法更新Loss之后,针对测试集数字分类的准确率:
- #prediction
- total = 0
- correct =0
- acc_list_test = []
- for images,labels in test_loader:
- images=images.view(-1,28*28)
- outputs = net(images) #将数据集传入网络做前向计算
-
- _,predicts = torch.max(outputs.data,1)
- total += labels.size(0)
- correct += (predicts == labels).sum()
- acc_list_test.append(100 * correct / total)
-
- print('Accuracy = %.2f'%(100 * correct / total))
- plt.plot(acc_list_test)
- plt.xlabel('Epoch')
- plt.ylabel('Accuracy On TestSet')
- plt.show()
以上就是本期全部内容。我是fanstuck ,有问题大家随时留言讨论 ,我们下期见。