PyTorch识别手写数字 MNIST

一、PyTorch安装分两种
  1. pip Spyder可以使用;
  2. conda PyCharm可以使用;优点:能够方便显示子函数;
  3. 目前采用Spyder,PyCharm目前还没能安装成功。
二、整体思路
  1. 下载MNIST数据集
  2. 加载MNIST训练集(自动分割成batch,并且顺序随机打乱
  3. 采样并加载MNIST验证集测试集
    (分验证集和测试集,Sample是采样规则,之所以采样,是因为顺序没有被打乱)

到目前为止,我们就下载好了MNIST数据集:
(1)train_dataset:训练集,共10000个数据样本;
(2)test_dataset:测试集,共10000个数据样本;
前5000个样本为验证集,后5000个为测试集,

二、下载数据集
import torch
import torch.nn as nn
import torch.nn.functional as F

# torchvision 包收录了若干重要的公开数据集、网络模型和计算机视觉中的常用图像变换
import torchvision
import torchvision.transforms as transforms

import matplotlib.pyplot as plt
import numpy as np

# 超参数设置(即全局数据,参数:可变,用于训练中的权重)
num_epochs = 5   # 全数据集为5
num_classes = 10 # 总共分为10个类
batch_size = 64  # 批处理大小为64个样本
image_size = 28  # 图像的总尺寸28*28
learning_rate = 0.0001 # 学习率为0.001

# 下载训练集
train_dataset = torchvision.datasets.MNIST(root= './data',train=True,transform=transforms.ToTensor(),download=True)
# 下载测试集
test_dataset = torchvision.datasets.MNIST(root='./data',train=False,transform=transforms.ToTensor(),download=True)
三、加载数据集
# 训练数据集的加载器,自动将数据分割成batch,顺序随机打乱
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)

"""
接下来把测试数据中的前5000个样本作为验证集,后5000个样本作为测试集
"""

indices = range(len(test_dataset))
indices_val = indices[:5000]   # indices_val = 0:4999
indices_test = indices[5000:]  # indices_test = 5000:9999

# 通过下标对验证集和测试集进行采样
sampler_val = torch.utils.data.sampler.SubsetRandomSampler(indices_val)
sampler_test = torch.utils.data.sampler.SubsetRandomSampler(indices_test)

# 根据采样器来定义加载器,然后加载数据
# 根据采样的验证集sample_val 加载验证集
validation_loader = torch.utils.data.DataLoader(dataset =test_dataset,batch_size = batch_size,sampler = sampler_val)
# 根据采样的测试集sample_test 加载测试集
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,batch_size=batch_size,sampler = sampler_test)

#从数据集中读入一张图片,并绘制出来
idx = 8000

#dataset支持下标索引,其中提取出来的每一个元素为features,target格式,即属性和标签。[0]表示索引features
muteimg = train_dataset[idx][0].numpy()
#由于一般的图像包含rgb三个通道,而MINST数据集的图像都是灰度的,只有一个通道。因此,我们忽略通道,把图像看作一个灰度矩阵。

#用imshow画图,会将灰度矩阵自动展现为彩色,不同灰度对应不同颜色:从黄到紫

plt.imshow(muteimg[0,...])
print('标签是:',train_dataset[idx][1])

目前,我们把训练集:train_loader,验证集:validataion_loader、测试集:test_loader都加载到了内存中;

执行效果:

当前执行效果

四、构建卷积神经网络CNN
1. 卷积神经网络结构

(1)卷积层 (可以不止一个)
(2)池化层
(3)全连接层

2. 卷积运算目的:特征提取
(1)权重

1)一个权重,【3】 :能够扩大差异,使得差异更明显
2)两个权重,【1,0.3】左边仍旧保留,因为权重值高;右边因为略低的权重,有些丢失。

(2)权值矩阵

1)特定信息过滤器
权值矩阵在图像里表现的像一个从原始图像矩阵中提取特定信息的过滤器。
2)矩阵用途
一个权值组合可能用来提取边缘(edge)信息,另一个可能是用来提取一个特定颜色,下一个就可能就是对不需要的噪点进行模糊化。
3)权值矩阵学习方法:
A 先对权值进行学习,然后损失函数可以被最小化,类似于多层感知机(MLP)。
B 因此需要通过对参数进行学习来从原始图像中提取信息,从而来帮助网络进行正确的预测。
C 当我们有多个卷积层的时候,初始层往往提取较多的一般特征,随着网络结构变得更深,权值矩阵提取的特征越来越复杂,并且越来越适用于眼前的问题。

(3) 步长

1)步长小,能够共享更多像素点

(4)sane padding

1)我们可以看见在我们给图像填加一层 0 边界后,图像的原始形状是如何被保持的。
2)由于输出图像和输入图像是大小相同的,所以这被称为 same padding。
same padding(意味着我们仅考虑输入图像的有效像素)。
3)中间的 4*4 像素是相同的。这里我们已经利用边界保留了更多信息,并且也已经保留了图像的原大小。
4)小技巧:
卷积核:3 * 3 padding = 1
卷积核:5 * 5 padding = 2 可以使得图像保持原来大小

参考学习文档:机器之心
(5) 卷积函数:
import torch.nn as nn
conv1 = nn.Conv2d()
conv2 = nn.Conv2d()
最大池化层
pool = nn.MaxPool2d()
线性池化层
fc1 = nn.Linear()
fc2 = nn.Linear()
fc3 = nn.Linear()```

思考:
Conv1d:自然语言处理
Conv2d:图像处理
图像处理:X,Y,RGB(3) 3通道,X,Y负责定位;建立在二维平面上的3维特征
那么对于输入的股票数据呢?X是时间;建立在一维坐标轴上的多维特征;

3. 池化层目的:
4. 构建卷积神经网络
#定义两个卷积层的厚度(feature map的数量)
depth = [4, 8]
class ConvNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1,4,5,padding=2) # 1 input channel, 4 output channels, 5x5 square convolution kernel
        self.pool = nn.MaxPool2d(2, 2) #定义一个Pooling层
        self.conv2 = nn.Conv2d(depth[0],depth[1],5, padding = 2) #第二层卷积:4input channel, 8 output channels, 5x5 square convolution kernel
        self.fc1 = nn.Linear( depth[1] * image_size // 4 * image_size // 4 , 512) #线性连接层的输入尺寸为最后一层立方体的平铺,输出层512个节点
        self.fc2 = nn.Linear(512, num_classes) #最后一层线性分类单元,输入为512,输出为要做分类的类别数  
        
    def forward(self, x):
        # x尺寸:(batch_size, image_channels, image_width, image_height)
        x = F.relu(self.conv1(x))  #第一层卷积的激活函数用ReLu
        x = self.pool(x) #第二层pooling,将片变小
        
        #x的尺寸:(batch_size, depth[0], image_width/2, image_height/2)
        x = F.relu(self.conv2(x)) #第三层卷积,输入输出通道分别为depth[0]=4, depth[1]=8
        x = self.pool(x) #第四层pooling,将图片缩小到原大小的1/4
        
        #x的尺寸:(batch_size, depth[1], image_width/4, image_height/4)
        # view函数将张量x变形成一维的向量形式,总特征数batch_size * (image_size//4)^2*depth[1]不改变,为接下来的全连接作准备。
        x = x.view(-1, image_size // 4 * image_size // 4 * depth[1])
        
        #x的尺寸:(batch_size, depth[1]*image_width/4*image_height/4)
        x = F.relu(self.fc1(x)) #第五层为全链接,ReLu激活函数
        
        #x的尺寸:(batch_size, 512)
        x = F.dropout(x, training=self.training) #以默认为0.5的概率对这一层进行dropout操作,为了防止过拟合
        x = self.fc2(x) 
        
        #x的尺寸:(batch_size, num_classes)
        x = F.log_softmax(x, dim = 0) #输出层为log_softmax,即概率对数值log(p(x))。采用log_softmax可以使得后面的交叉熵计算更快
        return x
    
    def retrieve_features(self, x):
        #该函数专门用于提取卷积神经网络的特征图的功能,返回feature_map1, feature_map2为前两层卷积层的特征图
        feature_map1 = F.relu(self.conv1(x)) #完成第一层卷积
        x = self.pool(feature_map1)  # 完成第一层pooling
        print('type(feature_map1)=',feature_map1)
        feature_map2 = F.relu(self.conv2(x)) #第二层卷积,两层特征图都存储到了feature_map1, feature_map2中
        return (feature_map1, feature_map2)
    
"""计算预测正确率的函数,其中predictions是模型给出的一组预测结果,batch_size行num_classes列的矩阵,labels是数据之中的正确答案"""
def accuracy(predictions, labels):
    # torch.max的输出:out (tuple, optional维度) – the result tuple of two output tensors (max, max_indices)
    pred = torch.max(predictions.data, 1)[1] # 对于任意一行(一个样本)的输出值的第1个维度,求最大,得到每一行的最大元素的下标
    right_num = pred.eq(labels.data.view_as(pred)).sum() #将下标与labels中包含的类别进行比较,并累计得到比较正确的数量
    return right_num, len(labels) #返回正确的数量和这一次一共比较了多少元素
五、训练卷积神经网络
"""计算预测正确率的函数,其中predictions是模型给出的一组预测结果,batch_size行num_classes列的矩阵,labels是数据之中的正确答案"""
def accuracy(predictions, labels):
    # torch.max的输出:out (tuple, optional维度) – the result tuple of two output tensors (max, max_indices)
    pred = torch.max(predictions.data, 1)[1] # 对于任意一行(一个样本)的输出值的第1个维度,求最大,得到每一行的最大元素的下标
    right_num = pred.eq(labels.data.view_as(pred)).sum() #将下标与labels中包含的类别进行比较,并累计得到比较正确的数量
    return right_num, len(labels) #返回正确的数量和这一次一共比较了多少元素


net = ConvNet()

criterion = nn.CrossEntropyLoss() #Loss函数的定义,交叉熵
optimizer = torch.optim.SGD(net.parameters(), lr=0.001, momentum=0.9) #定义优化器,普通的随机梯度下降算法

record = [] #记录准确率等数值的list
weights = [] #每若干步就记录一次卷积核

for epoch in range(num_epochs):
    train_accuracy = [] #记录训练数据集准确率的容器
    
    # 一次迭代一个batch的 data 和 target
    for batch_id, (data,target) in enumerate(train_loader):
        net.train() # 给网络模型做标记,标志说模型正在训练集上训练,这种区分主要是为了打开关闭net的training标志,从而决定是否运行dropout
        
        output =  net(data) #forward 
        loss = criterion(output, target) 
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        accuracies = accuracy(output, target)
        train_accuracy.append(accuracies)
        
        if batch_id%100 ==0: #每间隔100个batch执行一次打印等操作
            net.eval() # 给网络模型做标记,将模型转换为测试模式。
            val_accuracy = [] #记录校验数据集准确率的容器
            
            for (data, target) in validation_loader: #计算校验集上面的准确度
                output = net(data) #完成一次前馈计算过程,得到目前训练得到的模型net在校验数据集上的表现
                accuracies = accuracy(output, target) #计算准确率所需数值,返回正确的数值为(正确样例数,总样本数)
                val_accuracy.append(accuracies)
                
            # 分别计算在已经计算过的训练集,以及全部校验集上模型的分类准确率
            
            #train_r为一个二元组,分别记录目前  已经经历过的所有  训练集中分类正确的数量和该集合中总的样本数,
            train_r = (sum([tup[0] for tup in train_accuracy]), sum([tup[1] for tup in train_accuracy]))
            #val_r为一个二元组,分别记录校验集中分类正确的数量和该集合中总的样本数
            val_r = (sum([tup[0] for tup in val_accuracy]), sum([tup[1] for tup in val_accuracy]))
            
            #打印准确率等数值,其中正确率为本训练周期Epoch开始后到目前batch的正确率的平均值
            print('Epoch [{}/{}] [{}/{} ({:.0f}%)]\tLoss: {:.6f}\t训练正确率: {:.2f}%\t校验正确率: {:.2f}%'.format(
                epoch+1,num_epochs, batch_id * batch_size, len(train_loader.dataset),
                100. * batch_id / len(train_loader), loss.item(), 
                100. * train_r[0] / train_r[1], 
                100. * val_r[0] / val_r[1]))

六、训练结果
runfile('H:/PyTorch/third.py', wdir='H:/PyTorch')
Epoch [1/5] [0/60000 (0%)]      Loss: 2.306378  训练正确率: 7.81%    校验正确率: 9.36%
Epoch [1/5] [6400/60000 (11%)]  Loss: 2.300146  训练正确率: 11.31%   校验正确率: 19.66%
Epoch [1/5] [12800/60000 (21%)] Loss: 2.288543  训练正确率: 13.09%   校验正确率: 34.32%
Epoch [1/5] [19200/60000 (32%)] Loss: 2.281700  训练正确率: 15.63%   校验正确率: 46.72%
Epoch [1/5] [25600/60000 (43%)] Loss: 2.241495  训练正确率: 18.23%   校验正确率: 55.34%
Epoch [1/5] [32000/60000 (53%)] Loss: 2.075073  训练正确率: 21.54%   校验正确率: 58.20%
Epoch [1/5] [38400/60000 (64%)] Loss: 1.332497  训练正确率: 25.47%   校验正确率: 67.48%
Epoch [1/5] [44800/60000 (75%)] Loss: 1.240580  训练正确率: 30.79%   校验正确率: 72.86%
Epoch [1/5] [51200/60000 (85%)] Loss: 0.692732  训练正确率: 35.94%   校验正确率: 78.48%
Epoch [1/5] [57600/60000 (96%)] Loss: 0.681386  训练正确率: 40.42%   校验正确率: 80.82%
Epoch [2/5] [0/60000 (0%)]      Loss: 0.595346  训练正确率: 78.12%   校验正确率: 81.04%
Epoch [2/5] [6400/60000 (11%)]  Loss: 0.473438  训练正确率: 79.21%   校验正确率: 82.86%
Epoch [2/5] [12800/60000 (21%)] Loss: 0.469020  训练正确率: 80.09%   校验正确率: 84.18%
Epoch [2/5] [19200/60000 (32%)] Loss: 0.482854  训练正确率: 81.05%   校验正确率: 84.90%
Epoch [2/5] [25600/60000 (43%)] Loss: 0.582667  训练正确率: 81.57%   校验正确率: 85.98%
Epoch [2/5] [32000/60000 (53%)] Loss: 0.465008  训练正确率: 82.28%   校验正确率: 86.84%
Epoch [2/5] [38400/60000 (64%)] Loss: 0.256229  训练正确率: 82.73%   校验正确率: 87.60%
Epoch [2/5] [44800/60000 (75%)] Loss: 0.383545  训练正确率: 83.40%   校验正确率: 88.04%
Epoch [2/5] [51200/60000 (85%)] Loss: 0.283119  训练正确率: 83.83%   校验正确率: 89.38%
Epoch [2/5] [57600/60000 (96%)] Loss: 0.403816  训练正确率: 84.30%   校验正确率: 89.72%
Epoch [3/5] [0/60000 (0%)]      Loss: 0.384087  训练正确率: 90.62%   校验正确率: 89.68%
Epoch [3/5] [6400/60000 (11%)]  Loss: 0.294257  训练正确率: 88.20%   校验正确率: 90.48%
Epoch [3/5] [12800/60000 (21%)] Loss: 0.520744  训练正确率: 88.75%   校验正确率: 90.84%
Epoch [3/5] [19200/60000 (32%)] Loss: 0.187293  训练正确率: 89.21%   校验正确率: 91.70%
Epoch [3/5] [25600/60000 (43%)] Loss: 0.149348  训练正确率: 89.35%   校验正确率: 91.64%
Epoch [3/5] [32000/60000 (53%)] Loss: 0.177097  训练正确率: 89.63%   校验正确率: 91.52%
Epoch [3/5] [38400/60000 (64%)] Loss: 0.283381  训练正确率: 89.85%   校验正确率: 92.32%
Epoch [3/5] [44800/60000 (75%)] Loss: 0.221938  训练正确率: 90.11%   校验正确率: 92.42%
Epoch [3/5] [51200/60000 (85%)] Loss: 0.168308  训练正确率: 90.35%   校验正确率: 93.24%
Epoch [3/5] [57600/60000 (96%)] Loss: 0.329505  训练正确率: 90.54%   校验正确率: 93.10%
Epoch [4/5] [0/60000 (0%)]      Loss: 0.188860  训练正确率: 93.75%   校验正确率: 93.12%
Epoch [4/5] [6400/60000 (11%)]  Loss: 0.150691  训练正确率: 92.30%   校验正确率: 93.04%
Epoch [4/5] [12800/60000 (21%)] Loss: 0.384889  训练正确率: 92.67%   校验正确率: 93.38%
Epoch [4/5] [19200/60000 (32%)] Loss: 0.117718  训练正确率: 92.86%   校验正确率: 93.68%
Epoch [4/5] [25600/60000 (43%)] Loss: 0.162536  训练正确率: 92.83%   校验正确率: 93.70%
Epoch [4/5] [32000/60000 (53%)] Loss: 0.140568  训练正确率: 92.98%   校验正确率: 94.08%
Epoch [4/5] [38400/60000 (64%)] Loss: 0.088605  训练正确率: 92.99%   校验正确率: 94.06%
Epoch [4/5] [44800/60000 (75%)] Loss: 0.287696  训练正确率: 93.13%   校验正确率: 94.14%
Epoch [4/5] [51200/60000 (85%)] Loss: 0.159704  训练正确率: 93.14%   校验正确率: 94.50%
Epoch [4/5] [57600/60000 (96%)] Loss: 0.298342  训练正确率: 93.20%   校验正确率: 94.58%
Epoch [5/5] [0/60000 (0%)]      Loss: 0.061918  训练正确率: 98.44%   校验正确率: 94.26%
Epoch [5/5] [6400/60000 (11%)]  Loss: 0.230948  训练正确率: 94.35%   校验正确率: 94.72%
Epoch [5/5] [12800/60000 (21%)] Loss: 0.057776  训练正确率: 94.08%   校验正确率: 94.74%
Epoch [5/5] [19200/60000 (32%)] Loss: 0.166323  训练正确率: 94.08%   校验正确率: 94.76%
Epoch [5/5] [25600/60000 (43%)] Loss: 0.310377  训练正确率: 94.10%   校验正确率: 94.84%
Epoch [5/5] [32000/60000 (53%)] Loss: 0.246734  训练正确率: 94.24%   校验正确率: 94.92%
Epoch [5/5] [38400/60000 (64%)] Loss: 0.085995  训练正确率: 94.30%   校验正确率: 94.56%
Epoch [5/5] [44800/60000 (75%)] Loss: 0.109112  训练正确率: 94.32%   校验正确率: 94.92%
Epoch [5/5] [51200/60000 (85%)] Loss: 0.112068  训练正确率: 94.36%   校验正确率: 95.22%
Epoch [5/5] [57600/60000 (96%)] Loss: 0.131915  训练正确率: 94.37%   校验正确率: 95.40%
七、新的知识点
1. epoch:全数据集
2. batch_size:批处理尺寸

(1)选取适中的batch_size,当然可以,这就是批梯度下降法(Mini-batches Learning)。因为如果数据集足够充分,那么用一半(甚至少得多)的数据训练算出来的梯度与用全部数据训练出来的梯度是几乎一样的。
(2)作用:用来解决数据量比较小,而准确率需要比较高的情形

3. MNIST数据集

(1)元素为【features,target】格式,即属性和标签,[0]表示属性features,[1]表示标签

idx=0  # 下标0,第0张图片
muteimg = train_dataset[idx][0].numpy # 第0张图片的第一个元素:属性,进行格式转换,便于输出图形
plt.imshow(muteing[0,...])
print('标签是:',train_dataset[idx][1]) # 第0张图片的第二个元素:标签
4. 加载器

(1)# 训练数据集的加载器,自动将数据分割成batch,顺序随机打乱

train_loader = 
	torch.utils.data.DataLoader(dataset=train_dataset,
		batch_size=batch_size,shuffle=True)
5. 采样器 Sample & BatchSample

(1)在实际应用中,数据并不一定是循规蹈矩的序惯访问,而需要随机打乱顺序来访问,或需要随机加权访问,

因此,按某种特定的规则来读取数据,就是采样操作,需要定义采样器:Sampler。

(2)另外,数据也可能并不是一个一个读取的,而需要一批一批的读取,即需要批量采样操作,定义批量采样器:BatchSampler。
(3) BatchSample = Sample +Batch_Size (相当于基址+偏移量)
(4)原来随机一次性读取一个Sample,后面随机一次性读取Batch_Size个Sample。

6. Conv2d()理解

(1)Conv2d(1,4,5,padding=2)
input channel = 1;输入的数据通道数是1,灰度图像,
output channel = 4,输出的数据通道数是4,即深度为4,等于4个卷积核。
square convulution kernel = 5;卷积矩阵=5*5;
padding = 2;外层填充两层0;
(2)

7. 参考资料:

(1) PyTorch1.0 在MNIST数据集上实现卷积神经网络
(2)谈谈深度学习中的 Batch_Size
(3)Pytorch数据读取详解

八、RGB3通道数据存储详解

1. 关于三通道彩色图像的存储方式理解

九、图像存储格式和股票数据存储格式转换
十、学习疑惑
  1. 对卷积层、池化层各个层次之间参数设置不清楚
# 超参数设置
image_size = 28
batch_size = 64 # 将 batch_size = 640 训练速度急剧下降
num_classes = 10 

depth = [4,8]
class ConvNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1,4,5,padding=2) # 1 input channel, 4 output channels,5*5 square convolution kernel
        # 1个输入通道 4个输出通道 5-5的平方卷积核
        # 1 是因为灰度为 1 5*5的卷积核 配上padding = 2,图像大小不变
        # 第一层卷积的结果 : 
        # 原先总特征数:batch_size * depth = 1 *image_weight * image_height 
        # 即 64 * 1 * 28 * 28
        # 第一层卷积后:batch_size * depth = 4 * image_weight * image_height
        # 即 64 * 4 * 28 * 28 总特征数变成了原来的4倍
        self.pool = nn.MaxPool2d(2,2) # 定义一个Pooling层 14*14*4
        # 第二层池化的结果:
        # 第二层池化:batch_size * depth = 4 * image_weight / 2 * image_height /2
        # 即:64 * 1 * 28 * 28 总特征数保持不变
        self.conv2 = nn.Conv2d(depth[0],depth[1],5,padding=2) # 第二层卷积:4 input channel,8 output channels, 5*5 squares convolution kernel
        # 第三层卷积结果:
        # batch_size * depth[1] = 8 * image_weight/2 * image_height/2 为原来总特征数的两倍
        # 这里似乎只考虑了深度,没有考虑图片大小? 14*14*8
        self.fc1 = nn.Linear(depth[1]*image_size//4*image_size//4,512) # 线性连接层的输入尺寸为最后一层立方体的平铺,输出层为512个节点
        # 8*8*8=512 立方体平铺成512个节点,然后512分类成num_classes
        self.fc2 = nn.Linear(512,num_classes) # 最后一层线性分类单元,输入为512,输出为要做分类的类别数
        
        # 最后一层要回归到分类树当中,是因为有两个卷积层,所以要有两个激活函数吗?
"""
若要保持总特征数不变,是否应该使得depth[1] = 16 呢?
在fc1当中,如果最后输出的立方体的总特征数并不等于512,这个数字是怎么得来的呢?
"""
  1. 对批处理大小:batch_size,对总数据集不太清楚:epochs
beta 1.0			# 1.0 版本
epochs = 5			# 总训练批次
batch_size = 64		# 

> https://blog.csdn.net/qq_36589234/article/details/89259744

beta 2.0			# 2.0 版本
epochs = 20			# 总训练批次
batch_size = 512	# 大概需要2G显存

>https://blog.csdn.net/wsp_1138886114/article/details/86633056
  1. enumerate():用于提取train_loader()当中的样本等数据
    enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
    示例代码:
>>>seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))       # 下标从 1 开始
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
  1. 新知识点:MNIST数据集
    图片格式:28 * 28 * 1
  2. 遇到了全连接层参数设置不太懂,前面的能够理解,后面的呢?
beta 1 # 版本1
self.fc1 = nn.Linear()
self.fc2 = nn.Linear()
beata 2 # 版本2 
self.fc1 = nn.Linear()
self.fc2 = nn.Linear()
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: PyTorch是一种用于深度学习的开源框架,可用于手写数字识别MNIST数据集。 MNIST数据集包含手写数字的图像和标签,可用于训练和评估深度学习模型。通过使用PyTorchMNIST数据集,可以构建和训练一个用于识别手写数字的模型。 ### 回答2: ### 回答3: PyTorch是一个非常流行的开源机器学习框架,它支持使用Python编程语言来构建深度学习模型。在本问题中,我们要使用PyTorch实现手写数字识别MNISTMNIST是一个非常著名的手写数字数据集,它包含了60000个训练样本和10000个测试样本。每张图片的大小是28x28像素,每个像素的值在0~255之间,表示灰度值。手写数字识别MNIST任务的目标是训练一个模型,输入一张黑白图片,输出它表示的数字。 下面是使用PyTorch实现MNIST的大致流程: 1. 下载MNIST数据集,使用PyTorch内置的dataset和dataloader来加载数据。 2. 构建一个神经网络模型,可以使用PyTorch提供的nn.Module和nn.Sequential搭建模型。在本例中,我们可以构建一个简单的卷积神经网络模型。 3. 定义损失函数,一般使用交叉熵损失函数。 4. 定义优化器,如Adam或SGD等。 5. 进行训练,即在数据集上反复迭代地进行前向传播和反向传播过程,更新模型的参数,使得损失函数最小化。可以使用PyTorch提供的自动微分机制来进行反向传播。 6. 在测试集上测试模型的精度,可以使用PyTorch提供的测试函数来对模型进行评估。 下面给出一个简单的示例代码框架: ``` # 导入PyTorch和相关库 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms # 定义数据转换器 transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))]) # 加载MNIST数据集 train_dataset = datasets.MNIST(root='data', train=True, transform=transform, download=True) train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=64, shuffle=True) test_dataset = datasets.MNIST(root='data', train=False, transform=transform, download=True) test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=64, shuffle=True) # 构建神经网络模型 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 32, 3, 1) self.conv2 = nn.Conv2d(32, 64, 3, 1) self.dropout1 = nn.Dropout2d(0.25) self.dropout2 = nn.Dropout2d(0.5) self.fc1 = nn.Linear(1600, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = self.conv1(x) x = nn.functional.relu(x) x = self.conv2(x) x = nn.functional.relu(x) x = nn.functional.max_pool2d(x, 2) x = self.dropout1(x) x = torch.flatten(x, 1) x = self.fc1(x) x = nn.functional.relu(x) x = self.dropout2(x) x = self.fc2(x) output = nn.functional.log_softmax(x, dim=1) return output # 定义模型、损失函数和优化器 model = Net() criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 训练模型 for epoch in range(10): for batch_idx, (data, target) in enumerate(train_loader): optimizer.zero_grad() output = model(data) loss = criterion(output, target) loss.backward() optimizer.step() if batch_idx % 10 == 0: print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format( epoch, batch_idx * len(data), len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item())) # 测试模型 model.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: output = model(data) test_loss += criterion(output, target).item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) print('Test set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)'.format( test_loss, correct, len(test_loader.dataset), 100. * correct / len(test_loader.dataset))) ``` 这段代码定义了一个包含两个卷积层和两个全连接层的卷积神经网络模型,使用交叉熵损失函数和Adam优化器来进行训练。在每个训练周期中,程序会遍历整个训练集,进行参数更新;在训练结束后,程序会在测试集上进行测试,计算模型的精度。 总的来说,使用PyTorch实现手写数字识别MNIST是一个非常典型的深度学习问题,这个例子也展示了如何使用PyTorch进行模型构建、数据处理和训练测试。通过这个例子,我们可以更好地了解深度学习的基本流程和PyTorch的使用方法,也可以为我们后续的深度学习项目提供一些参考。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值