import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
transform = transforms.Compose([transforms.ToTensor(), # 转为张量transforms.Normalize((0.5,), (0.5,)) # 归一化到 [-1, 1]
])
transforms.ToTensor():
将PIL图像或NumPy数组转换为PyTorch张量(Tensor)
自动将像素值从 [0, 255] 归一化到 [0, 1] 范围
将图像格式从 (H, W, C) 转换为 (C, H, W),即通道优先
transforms.Normalize((0.5,), (0.5,)) :
对图像进行标准化处理
输出范围:[(0-0.5)/0.5, (1-0.5)/0.5] = [-1, 1]
train_dataset = datasets.MNIST(root= './data',train= True,transform = transform,download=True)
test_dataset = datasets.MNIST(root='./data',train= False, transform= transform,download=True)
下载MNIST数据集:
transform = transform表示用上述定义的操作处理数据
train_loader = torch.utils.data.DataLoader(dataset= train_dataset,batch_size = 64,shuffle = True)
test_loader = torch.utils.data.DataLoader(dataset= test_dataset,batch_size = 64,shuffle = False)class SimpleCNN(nn.Module):def __init__(self):super(SimpleCNN,self).__init__()self.conv1 = nn.Conv2d(1,32,kernel_size=3,stride=1,padding=1)self.conv2 = nn.Conv2d(32,64,kernel_size=3,stride=1,padding=1)self.fc1 = nn.Linear(64*7*7,128)self.fc2 = nn.Linear(128,10)def forward(self,x):x = F.relu(self.conv1(x))x = F.max_pool2d(x,2)x = F.relu(self.conv2(x))x = F.max_pool2d(x,2)x = x.view(-1,64*7*7)x = F.relu(self.fc1(x))x = self.fc2(x)return x
Conv2d(输入通道数,输出通道数,核大小,步长,padding)
输入通道由输入图像通道数决定
输出通道数由核数决定
linear(x,y) x->y
model = SimpleCNN()criterion = nn.CrossEntropyLoss()#交叉熵损失函数
optimizer = optim.SGD(model.parameters(),lr=0.01,momentum=0.9)num_epochs= 5
model.train()for epoch in range(num_epochs):total_loss = 0for images,labels in train_loader:outputs = model(images)loss = criterion(outputs,labels)#criterion函数是用于计算模型预测值与真实值之间差距的损失函数。#先将梯度归零(optimizer.zero_grad()),然后反向传播计算得到每个参数的梯度值(loss.backward()),最后通过梯度下降执行一步参数 #更新(optimizer.step())optimizer.zero_grad()#使用mini-batch方法,所以如果不将梯度清零的话,梯度会与上一个batch的数据相关loss.backward()#如果你做完运算后使用tensor.backward(),所有的梯度就会自动运算,tensor的梯度将会累加到它的.grad属性里面去optimizer.step()#optimizer只负责通过梯度下降进行优化total_loss += loss.item()print(f"Epoch [{epoch + 1}/{num_epochs}], Loss: {total_loss / len(train_loader):.4f}")
model.eval()
correct = 0
total = 0with torch.no_grad():for images,labels in test_loader:outputs = model(images)_,predicted = torch.max(outputs,1)total += labels.size(0)correct +=(predicted == labels).sum().item()accuracy = 100*correct/total
print(f"Test Accuracy: {accuracy:.2f}%")dataiter = iter(test_loader)
images, labels = next(dataiter)
outputs = model(images)
_, predictions = torch.max(outputs,1)fig,axes = plt.subplots(1,6,figsize=(12,4))
for i in range(6):axes[i].imshow(images[i][0], cmap='gray')axes[i].set_title(f"Label: {labels[i]}\nPred: {predictions[i]}")axes[i].axis('off')
plt.show()