代码引用:
一:
用PyTorch实现MNIST手写数字识别(最新,非常详细)_mnist pytorch-CSDN博客
Sample Code 添加模型测试:
设立单独Test 测试分析
import torch
import torchvision
from PIL import Image
from torch import nn
###定义训练的设备
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"当前使用设备为: {device}")
image_path = "./imgs/6.png"
image =Image.open(image_path)
print(image)
image = image.convert('L')
transform = torchvision.transforms.Compose([torchvision.transforms.Resize((28, 28)),
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize((0.1307,), (0.3081,))
])
image = transform(image)
print(image.shape)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = torch.nn.Sequential(
torch.nn.Conv2d(1, 10, kernel_size=5),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2),
)
self.conv2 = torch.nn.Sequential(
torch.nn.Conv2d(10, 20, kernel_size=5),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2),
)
self.fc = torch.nn.Sequential(
torch.nn.Linear(320, 50),
torch.nn.Linear(50, 10),
)
def forward(self, x):
batch_size = x.size(0)
x = self.conv1(x) # 一层卷积层,一层池化层,一层激活层(图是先卷积后激活再池化,差别不大)
x = self.conv2(x) # 再来一次
x = x.view(batch_size, -1) # flatten 变成全连接网络需要的输入 (batch, 20,4,4) ==> (batch,320), -1 此处自动算出的是320
x = self.fc(x)
return x # 最后输出的是维度为10的,也就是(对应数学符号的0~9)
model = Net()
# 加载状态字典
state_dict = torch.load('./model_Mnist.pth', map_location=device)
model.load_state_dict(state_dict)
# 将模型移动到正确的设备并设置为评估模式
model = model.to(device)
model.eval()
# 将图像移到正确的设备
image = image.to(device)
print(model)
model.eval()
with torch.no_grad():
output = model(image)
print(output)
print("预测的数字是:", output.argmax(1).item())
Sample Code分析:
图像预处理:
将PIL RGB三色图像或者 NumPy 数组 像素值缩放到 [0.0, 1.0] 范围
使用 ToTensor() 的主要优势是它能够将各种格式的图像数据统一转换为 PyTorch 可以直接使用的标准格式,简化了数据预处理流程,使得后续的模型训练和推理更加方便。
transforms.ToTensor()
对张量进行标准化操作
- 对输入张量的每个通道分别进行标准化。
- 使用预定义的均值(mean)和标准差(standard deviation)
- mean: 各通道的均值序列
- std: 各通道的标准差序列
- transforms.Normalize(mean,std)
transforms.Normalize((0.1307,), (0.3081,))
对于特定的训练集,其均值(mean)和标准差(std)是固定的。
MNIST数据集:mean=(0.1307,), std=(0.3081,)
ImageNet数据集:mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)
标准化与归一化 :
标准化公式:
output[c] = (input[c] - mean[c]) / std[c]
- mean: 各通道的均值序列
- std: 各通道的标准差序列
- input:输入
使用示例:
-
对于RGB彩色图像(3通道):
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) -
对于灰度图像(单通道):
transforms.Normalize(mean=[0.5], std=[0.5]) -
常见的简化形式(对所有通道使用相同的值):
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
若输入的值都在0~1中,通过 transforms.Normalize((0.5,0.5,0.5),(0.5,0.5,0.5))
那么输出变成((0,1)-0.5))/0.5=(-1,1)。
广义区别
- 归一化:将数据缩放到特定范围,通常是[0, 1]或[-1, 1]。
- 标准化:将数据转换为均值为0,标准差为1的分布。
- 归一化:X_norm = (X - X_min) / (X_max - X_min)
- 标准化:X_stand = (X - μ) / σ (μ是均值,σ是标准差)
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
- 这行代码先进行了归一化(ToTensor 的缩放过程),然后又进行了标准化(Normalize 操作)。首先将数据归一化到一个固定范围,使得不同图像之间的尺度一致。然后通过标准化,进一步调整数据分布,使其更适合神经网络的训练。
联系:
标准化(normalization)是将数据按比例缩放(scale),使之落入一个小的特定区间。在某些比较和评价的指标处理中经常会用到,去除数据的单位限制,将其转化为无量纲的纯数值,便于不同单位或量级的指标能够进行比较和加权。
最典型的就是数据的归一化处理,即将数据统一映射到[0,1]区间上。也就是归一化是标准化的特例,标准化的子集。