pytorch(2)手写数字识别引入&Pytorch 数据类型

本文介绍手写数字识别的基本原理,使用MNIST数据集进行训练和测试,探讨onehot编码及PyTorch数据类型。通过构建深度学习模型,采用ReLU等非线性激活函数提高识别精度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、系列文章目录

(1)梯度下降
(2)手写数字识别引入&Pytorch 数据类型
(3)创建Tensor
(4)Broadcasting
(5)Tensor
(6)Tensor统计
(7)Where和Gather
(8)函数的梯度
(9)loss函数;自动求导



二、手写数字识别

1.MNIST数据集

10种数字0~9,每种数字有7000张图片,70k张图,每张图尺寸为28x28
train/test splitting :把这些图分为60k训练集和10k测试集。

把一张灰度图表示为一个28x28的矩阵,元素为像素值,范围0~1。打平成一维,是28x28=784个元素的向量。
类比简单线性问题y=wx+b,在手写数字识别问题中,x是[784]向量,y是0~9这些数字,但是不能用数字表示,因为这样数字间会存在大小关系,用one hot 编码。

2.one hot 编码

1 → [0,1,0,0,0,0,0,0,0,0]
2 → [0,0,2,0,0,0,0,0,0,0]
……
9 →[0,0,0,0,0,0,0,0,0,9]

嵌套模板

X = [v1,v2,……,v784]X是1行,784列
H1 = XW1 T+ b1W1是d1行,784列H1是1行,d1
H2 = H1W2 T+ b2W2是d2行,d1H2是1行,d2
H3 =H2 W3 T+ b3W3是d3行,d2H3是1行,d3

在这里H3 是1行10列

怎么计算loss呢?
假设得到一个H3=[0.1,0.8,0.01,……,0](意思是,识别的这个数字是0的概率为0.1,即P(X=0|X) = 0.1,是1 的概率为0.8,……,是9的概率为0)

而真实值是H3=[0,1,……,0] (该数字是1)
计算欧氏距离的平方作为loss,方法同二维一样

Non-linear Factor
虽然加了嵌套,但线性模型还是不能很好的完成识别任务,因此要加一个非线性部分。包括著名的relu函数、sigmoid函数

Relu函数:比0小的值都记为0
在这里插入图片描述
这样H1 = Relu(XW1 T+ b1

pred = H3 = [(XW1 T+ b1 )W2 T+ b2]W3 T+ b3
(每层都有Relu函数,没写出来)

怎么得到预测值

假设得到 H3=[0.1,0.8,0.01,……,0]

max(pred) = 0.8 ; argmax(pred) = 1(得到其索引号)

3.pytorch数据类型

张量 Tensor
python中的string,在pytorch中内部没有自带的表示方法。于是用 One-hot 或 Embedding
所谓One-hot 就是用一组数字表示string,处理字母还不错
但是处理一句话这种复杂问题,用onehot会出现很多0,编码特别系稀疏,而且不能很好的区分Ilike和Ilove这类相关性的语义,这就用到了Embedding,包括Word2vec和glove。(没有讲具体怎么用,just科普。。)

pytorch中同一个数据放在不同位置类型可能不同,例如CPU中是torch.DoubleTensor,而GPU中是torch.cuda.DoubleTensor

类型推断

>>> import torch
>>> a = torch.randn(2,3)   #初始化一个2行3列的Tensor,随即正态分布,N(0,1)
>>> a.type()
'torch.FloatTensor'
>>> type(a)
<class 'torch.Tensor'>
>>> isinstance(a, torch.FloatTensor) #注意大小写哦
True

Dimension为0——标量(在pytorch0.3以前这种标量不存在,会用长度为1的向量来表示)

例 :loss

>>> torch.tensor(1.)
tensor(1.)
>>> torch.tensor(1.3)
tensor(1.3000)

Dimension为1——向量

例 :Bias & Linear Input

>>> torch.tensor([1.1]) #.tensor 指定具体数据
tensor([1.1000])
>>> torch.tensor([1.1,2.2])
tensor([1.1000, 2.2000])
>>> torch.FloatTensor(1)#.FloatTensor 指定长度即可
tensor([1.4013e-45])

用numpy生成向量

>>> import numpy as np
>>> data = np.ones(2)  #长度为2
>>> data
array([1., 1.])
>>> torch.from_numpy(data)
tensor([1., 1.], dtype=torch.float64)

Dimension为2

例 : linear input batch

 a = torch.randn(2,3) #两个向量,每个向量三个元素
>>> a
tensor([[ 0.1278, -0.0195, -0.6048],
        [ 1.9171, -1.5575, -0.7346]])

  • .shape
  • .size ()
  • .dtype 每个元素的数据类型
>>> a.size()  #几行几列
torch.Size([2, 3])
>>> a.size(0) #行数
2
>>> a.size(1)#列数
3

Dimension为3

例 :RNN Input Batch
10个词,每个词用100维向量onehot编码。一次送入20句话。[10,20,100]

>>> a = torch.rand(1,2,3)  # 均匀分布  1个二维,2行3列
>>> a
tensor([[[0.4427, 0.4094, 0.5362],
         [0.8530, 0.9553, 0.8837]]])

>>> b = torch.rand(2,3,4)  #  2个二维,3行4列
>>> b
tensor([
		[[0.8693, 0.4930, 0.1753, 0.0178],
         	[0.1094, 0.0488, 0.6811, 0.1096],
         	[0.6810, 0.0232, 0.4389, 0.2236]],
         
		 [[0.1498, 0.3657, 0.7056, 0.3712],
        	 [0.8516, 0.6231, 0.6993, 0.9023],
        	 [0.1346, 0.4388, 0.3456, 0.4780]]
         						])

Dimension为3

例 :CNN Input [b,c,h,w]

>>> c = torch.rand(2,3,4,5)  #  2个 3个二维的,4行5列
>>> c
tensor([
	      [
		[[0.5392, 0.1227, 0.4322, 0.6111, 0.0510],
        	 [0.2036, 0.3861, 0.5874, 0.8121, 0.2122],
          	 [0.4505, 0.6176, 0.4609, 0.5874, 0.8680],
         	 [0.2151, 0.2715, 0.1207, 0.5023, 0.6157]],
          
	         [[0.4368, 0.8560, 0.8352, 0.5122, 0.2710],
                  [0.4357, 0.6816, 0.5046, 0.8598, 0.9712],
                  [0.6830, 0.8281, 0.0184, 0.0172, 0.7933],
                  [0.9043, 0.5431, 0.7087, 0.3712, 0.7319]],
          
	        [[0.8600, 0.5627, 0.7063, 0.1658, 0.3914],
                [0.1920, 0.6904, 0.2216, 0.4201, 0.0345],
                [0.3745, 0.4559, 0.5951, 0.5464, 0.9667],
                [0.8550, 0.7814, 0.1153, 0.0309, 0.6290]]
                                                            ],
                   …………
      								])

### PyTorch 实现手写数字识别 为了实现基于MNIST数据集的手写数字识别,以下是详细的Python代码示例以及解释: #### 1. 引入库文件 首先需要导入必要的库来支持后续的操作。 ```python import torch from torchvision import datasets, transforms from torch.utils.data import DataLoader import torch.nn as nn import torch.optim as optim import torch.nn.functional as F ``` 这些库提供了访问MNIST数据集的能力,并允许定义和训练神经网络模型[^2]。 #### 2. 加载并预处理数据集 接着配置数据加载器以获取经过适当变换的数据批次。 ```python transform = transforms.Compose([ transforms.ToTensor(), # 将图像转换为张量 transforms.Normalize((0.5,), (0.5,)) ]) train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform) test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform) train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True) test_loader = DataLoader(dataset=test_dataset, batch_size=1000, shuffle=False) ``` 这里使用`transforms.ToTensor()`方法将输入图片从PIL Image对象或numpy数组形式转化为PyTorch中的FloatTensor类型;而`transforms.Normalize()`则用于标准化像素值到[-1, 1]区间内[^5]。 #### 3. 定义简单的全连接神经网络结构 构建一个多层感知机作为分类器。 ```python class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.fc1 = nn.Linear(28 * 28, 512) # 输入维度为784(即28*28),隐藏层有512个节点 self.fc2 = nn.Linear(512, 256) self.fc3 = nn.Linear(256, 10) # 输出层对应十个类别 def forward(self, x): x = x.view(-1, 28 * 28) # 展平每一张图象成为一维向量 x = F.relu(self.fc1(x)) x = F.dropout(x, training=self.training) x = F.relu(self.fc2(x)) x = self.fc3(x) return F.log_softmax(x, dim=1) ``` 此部分展示了如何通过继承自`nn.Module`类来自定义一个具有三层线性映射加ReLU激活函数的前馈神经网络。特别注意的是,在forward函数里调用了`.view()`操作来调整输入特征矩阵的形式以便于计算[^1]. #### 4. 设置优化算法与损失函数 指定使用的优化策略及其对应的代价衡量标准。 ```python model = Net().to('cpu') # 如果GPU可用,则可改为.to('cuda') optimizer = optim.Adam(model.parameters()) criterion = nn.CrossEntropyLoss() ``` 此处选择了Adam优化器配合交叉熵误差来进行梯度下降求解最小化目标函数的过程[^4]。 #### 5. 开始训练循环 执行多次迭代直到满足收敛条件为止。 ```python for epoch in range(1, epochs + 1): model.train() # 切换至训练模式 for data, target in train_loader: optimizer.zero_grad() # 清除之前的梯度信息 output = model(data) # 获取当前批样本预测结果 loss = criterion(output, target) # 计算这批样本上的平均损失 loss.backward() # 反向传播累积梯度 optimizer.step() # 更新权重参数 print(f'Epoch {epoch}, Loss: {loss.item()}') print("Training finished!") ``` 上述代码片段实现了完整的单轮次遍历整个训练集合完成一次正向传递、反向传播及参数更新的动作序列。 #### 6. 测试性能表现 最后利用独立验证集中未见过的新样本来检验最终得到的最佳模型效果。 ```python def test(): model.eval() # 进入评估状态 correct = 0 with torch.no_grad(): # 不记录任何梯度信息 for data, target in test_loader: output = model(data) pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() accuracy = 100. * correct / len(test_loader.dataset) print(f'Test Accuracy: {accuracy:.2f}%') test() ``` 这段脚本负责统计测试阶段正确率指标的具体数值,从而直观反映出所建立的学习系统的泛化能力水平。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值