提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
@pytorch学习笔记第一天
前言
一、MNIST手写数字识别
看十遍不如手敲一遍。
二、使用步骤
模型结构
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import datasets as mnist
from torchvision import transforms
from torch.utils.data import DataLoader
import torch.optim as optim
class Mnist_NN(nn.Module):
def __init__(self):
super().__init__()
self.hidden1 = nn.Linear(784,128)
self.hidden2 = nn.Linear(128,256)
self.hidden3 = nn.Linear(256,512)
self.out = nn.Linear(512,10)
self.dropout = nn.Dropout(0.5)
def forward(self, x):
# 展平4维输入为2维(batch_size, 784)
# x = x.view(x.size(0), -1) # 或 x = torch.flatten(x, start_dim=1)
x = F.relu(self.hidden1(x))
x = self.dropout(x)
x = F.relu(self.hidden2(x))
x = self.dropout(x)
x = F.relu(self.hidden3(x))
x = self.out(x)
return x
net = Mnist_NN()
2.读入数据
代码如下(示例):
train_batch = 128
test_batch =128
#下载数据集
transform = transforms.Compose([
transforms.ToTensor(), # 输出维度:(1, 28, 28)
# 正确展平:保持batch_size在前,展平后维度为(batch_size, 784)
transforms.Normalize([0.5], [0.5]), # 对784个特征进行归一化
transforms.Lambda(lambda x: x.view(-1)) # -1表示展平所有维度,得到(784,)
])
data_train = mnist.MNIST('D:/my/mnist/data',train=True, transform=transform, target_transform=None, download=True)
data_test = mnist.MNIST('D:/my/mnist/data',train=False, transform=transform, target_transform=None, download=True)
#加载数据集
train_loader = DataLoader(data_train, batch_size=train_batch,shuffle=True)
test_loader = DataLoader(data_test, batch_size=test_batch,shuffle=True)
3.设置模型参数
#设置训练次数
num_epochs = 10
#定义损失函数
criterion = nn.CrossEntropyLoss()
#定义学习率
LR = 0.001
optimizer = optim.Adam(net.parameters(), LR)
#
train_losses = []
train_acces = []
#测试
eval_losses = []
eval_acces = []
4.模型训练
#模型训练
#模型训练
for epoch in range(num_epochs):
#初始化统计量,每轮开始时重置损失和准确率。
train_loss = 0
train_acc = 0
#设置训练模式
net.train()
for data, label in train_loader:
# print('数据维度',data.shape)
out = net(data) # 前向传播
loss = criterion(out, label) # 计算损失
optimizer.zero_grad() # 清空梯度
loss.backward() # 反向传播
optimizer.step() # 更新参数
train_loss += loss.item()
_, pred = out.max(1) # 获取预测类别
num_correct = (pred == label).sum().item() # 正确预测数
acc = num_correct / data.shape[0] # 准确率
train_acc += acc # 累加准确率
train_losses.append(train_loss / len(train_loader))
train_acces.append(train_acc / len(train_loader))
# 测试阶段
net.eval()
eval_loss, eval_acc = 0.0, 0.0
with torch.no_grad():
for img, label in test_loader:
out = net(img)
loss = criterion(out, label)
eval_loss += loss.item()
_, pred = out.max(1)
eval_acc += (pred == label).sum().item() / img.size(0)
# 记录结果
train_loss /= len(train_loader)
train_acc /= len(train_loader)
eval_loss /= len(test_loader)
eval_acc /= len(test_loader)
train_losses.append(train_loss)
train_acces.append(train_acc)
eval_losses.append(eval_loss)
eval_acces.append(eval_acc)
# 输出
print(f"epoch:{epoch}, Train Loss:{train_loss:.4f}, Train Acc:{train_acc:.4f}, "
f"Test Loss:{eval_loss:.4f}, Test Acc:{eval_acc:.4f}")
总结
完整源码
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import datasets as mnist
from torchvision import transforms
from torch.utils.data import DataLoader
import torch.optim as optim
class Mnist_NN(nn.Module):
def __init__(self):
super().__init__()
self.hidden1 = nn.Linear(784,128)
self.hidden2 = nn.Linear(128,256)
self.hidden3 = nn.Linear(256,512)
self.out = nn.Linear(512,10)
self.dropout = nn.Dropout(0.5)
def forward(self, x):
# 展平4维输入为2维(batch_size, 784)
# x = x.view(x.size(0), -1) # 或 x = torch.flatten(x, start_dim=1)
x = F.relu(self.hidden1(x))
x = self.dropout(x)
x = F.relu(self.hidden2(x))
x = self.dropout(x)
x = F.relu(self.hidden3(x))
x = self.out(x)
return x
net = Mnist_NN()
train_batch = 128
test_batch =128
#下载数据集
# 修正数据预处理中的展平操作(关键修复点)
transform = transforms.Compose([
transforms.ToTensor(), # 输出维度:(1, 28, 28)
# 正确展平:保持batch_size在前,展平后维度为(batch_size, 784)
transforms.Normalize([0.5], [0.5]), # 对784个特征进行归一化
transforms.Lambda(lambda x: x.view(-1)) # -1表示展平所有维度,得到(784,)
])
data_train = mnist.MNIST('E:/code/map_code/data',train=True, transform=transform, target_transform=None, download=True)
data_test = mnist.MNIST('E:/code/map_code/data',train=False, transform=transform, target_transform=None, download=True)
#加载数据集
train_loader = DataLoader(data_train, batch_size=train_batch,shuffle=True)
test_loader = DataLoader(data_test, batch_size=test_batch,shuffle=True)
#设置训练次数
num_epochs = 10
#定义损失函数
criterion = nn.CrossEntropyLoss()
#定义学习率
LR = 0.001
optimizer = optim.Adam(net.parameters(), LR)
#
train_losses = []
train_acces = []
#测试
eval_losses = []
eval_acces = []
#模型训练
for epoch in range(num_epochs):
#初始化统计量,每轮开始时重置损失和准确率。
train_loss = 0
train_acc = 0
#设置训练模式
net.train()
for data, label in train_loader:
# print('数据维度',data.shape)
out = net(data) # 前向传播
loss = criterion(out, label) # 计算损失
optimizer.zero_grad() # 清空梯度
loss.backward() # 反向传播
optimizer.step() # 更新参数
train_loss += loss.item()
_, pred = out.max(1) # 获取预测类别
num_correct = (pred == label).sum().item() # 正确预测数
acc = num_correct / data.shape[0] # 准确率
train_acc += acc # 累加准确率
train_losses.append(train_loss / len(train_loader))
train_acces.append(train_acc / len(train_loader))
# 测试阶段
net.eval()
eval_loss, eval_acc = 0.0, 0.0
with torch.no_grad():
for img, label in test_loader:
out = net(img)
loss = criterion(out, label)
eval_loss += loss.item()
_, pred = out.max(1)
eval_acc += (pred == label).sum().item() / img.size(0)
# 记录结果
train_loss /= len(train_loader)
train_acc /= len(train_loader)
eval_loss /= len(test_loader)
eval_acc /= len(test_loader)
train_losses.append(train_loss)
train_acces.append(train_acc)
eval_losses.append(eval_loss)
eval_acces.append(eval_acc)
# 输出
print(f"epoch:{epoch}, Train Loss:{train_loss:.4f}, Train Acc:{train_acc:.4f}, "
f"Test Loss:{eval_loss:.4f}, Test Acc:{eval_acc:.4f}"))