一、查看数据集图片
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'
from torchvision import datasets, transforms, utils
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
batch_size = 64
# transform预处理
'''ToTensor:将一个’PIL Image‘or‘numpy.ndarray’转化为tensor格式,PIL Image or numpy.ndarray的shape为(H x W x C),范围是[0, 255]
转化为shape为(C x H x W)范围在[0.0, 1.0]'''
'''Normalize:标准化函数,使用均值和标准差对tensor进行标准化
output[channel] = (input[channel] - mean[channel]) / std[channel]
'''
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))]) #(0.1307,)为均值,(0.3081,)为方差
# ./表示当前目录 ../表示父级目录 /表示根目录
# mnist数据集为1*28*28的单通道图像
train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, transform=transform, download=True)
train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, transform=transform, download=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)
# 查看测试集中的图片
test_loader_iter = iter(test_loader)
val_image, val_label = test_loader_iter.next()
classes = ('0','1','2','3','4','5','6','7','8','9')
def imshow(img):
img = img * 0.3081 + 0.1307 #按照公式转化回去
npimg = img.numpy() #将图像转化为numpy格式
plt.imshow(np.transpose(npimg, (1, 2, 0))) #将通道调整为C x H x W -> H x W x C
plt.show()
print(' '.join('%5s' % classes[val_label[j].item()] for j in range(64))) #一次查看64张图片
imshow(utils.make_grid(val_image))
二、Inception Module以及网络结构搭建
import torch.nn as nn
import torch
import torch.nn.functional as F
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'
from torchvision import datasets, transforms, utils
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
batch_size = 64
# transform预处理
'''ToTensor:将一个’PIL Image‘or‘numpy.ndarray’转化为tensor格式,PIL Image or numpy.ndarray的shape为(H x W x C),范围是[0, 255]
转化为shape为(C x H x W)范围在[0.0, 1.0]'''
'''Normalize:标准化函数,使用均值和标准差对tensor进行标准化
output[channel] = (input[channel] - mean[channel]) / std[channel]
'''
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))]) #(0.1307,)为均值,(0.3081,)为方差
# ./表示当前目录 ../表示父级目录 /表示根目录
# mnist数据集为1*28*28的单通道图像
train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, transform=transform, download=True)
train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, transform=transform, download=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=False)
'''
# 查看测试集中的图片
test_loader_iter = iter(test_loader)
val_image, val_label = test_loader_iter.next()
classes = ('0','1','2','3','4','5','6','7','8','9')
def imshow(img):
img = img * 0.3081 + 0.1307 #按照公式转化回去
npimg = img.numpy() #将图像转化为numpy格式
plt.imshow(np.transpose(npimg, (1, 2, 0))) #将通道调整为C x H x W -> H x W x C
plt.show()
print(' '.join('%5s' % classes[val_label[j].item()] for j in range(64)))
imshow(utils.make_grid(val_image))
'''
class InceptionA(torch.nn.Module):
def __init__(self, in_channels):
super(InceptionA, self).__init__()
self.branch_pool = torch.nn.Conv2d(in_channels, 24, kernel_size=1)
self.branch1x1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch5x5_1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch5x5_2 = torch.nn.Conv2d(16, 24, kernel_size=5, padding=2)
self.branch3x3_1 = torch.nn.Conv2d(in_channels, 16, kernel_size=1)
self.branch3x3_2 = torch.nn.Conv2d(16, 24, kernel_size=3, padding=1)
self.branch3x3_3 = torch.nn.Conv2d(24, 24, kernel_size=3, padding=1)
def forward(self, x): #InceptionA模块的正向传播过程
branch1x1 = self.branch1x1(x)
branch5x5 = self.branch5x5_2(self.branch5x5_1(x))
branch3x3 = self.branch3x3_3(self.branch3x3_2(self.branch3x3_1(x)))
branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
branch_pool = self.branch_pool(branch_pool)
outputs = [branch1x1, branch3x3, branch5x5, branch_pool]
return torch.cat(outputs, dim=1)
class Net(torch.nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
self.conv2 = torch.nn.Conv2d(88, 20, kernel_size=5)
self.incep1 = InceptionA(in_channels=10)
self.incep2 = InceptionA(in_channels=20)
self.mp = nn.MaxPool2d(2)
self.fc = torch.nn.Linear(1408, 10)
def forward(self, x): #网络的正向传播过程
in_size = x.size(0)
x = F.relu(self.mp(self.conv1(x)))
x = self.incep1(x)
x = F.relu(self.mp(self.conv2(x)))
x = self.incep2(x)
x = x.view(in_size, -1)
x = self.fc(x)
return x
net = Net() #实例化模型
#将模型迁移到GPU上
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net.to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.01)
# 训练部分
def train(epoch):
running_loss = 0.0
# 通过函数enumerate返回每一批数据data,以及索引index,因为start=0所以index从0开始
for batch_idx, data in enumerate(train_loader, start=0):
inputs, targets = data #将数据分为图像以及所对应的标签
inputs, targets = inputs.to(device), targets.to(device) #迁移到GPU上
optimizer.zero_grad() #将历史损失梯度清零
# forward
y_pred = net(inputs) #将训练图片输入网络得到输出
# backward
loss = criterion(y_pred, targets)
loss.backward()
# update
optimizer.step() #参数更新
running_loss += loss.item()
if batch_idx % 300 == 299: #每300个mini-batches打印一次
# epoch为第多少轮,batch_idx为这轮中第多少个mini-batche,running_loss/300为这300个mini-batche的平均损失
print("[%d,%d]loss:%.3f" % (epoch + 1, batch_idx + 1, running_loss / 300))
running_loss = 0.0
accuracy = []
# 测试部分
def test():
correct = 0
total = 0
with torch.no_grad(): #在下面一部分中不要去计算每个节点的误差损失梯度,测试过程不需要计算误差损失梯度
for data in test_loader:
images, labels = data #将数据分为图像以及所对应的标签
images, labels = images.to(device), labels.to(device) #迁移到GPU上
# 将预测图片输入网络得到输出,输出的shape为[batch, 10],因为要预测10个类别,所以经过最后的全连接层后输出的节点数为10
outputs = net(images) # [batch, 10]
# 在outputs的维度1上,也就是10上找到一个最大值(最大值具体为多少不重要,重要的是他的索引)及最大值的索引predicted
_, predicted = torch.max(outputs.data, dim=1)
# 测试样本的总数
total += labels.size(0)
# 预测正确的样本数
correct += (labels == predicted).sum().item()
print("accuracy on test set:%d %% [%d/%d]" % (100 * correct / total, correct, total))
accuracy.append(100 * correct / total)
if __name__ == "__main__":
for epoch in range(10):
train(epoch)
test()
# 保存权重
save_path = './InceptionA.pth'
# 通过torch.save函数将网络所有的参数进行保存,保存路径为save_path
torch.save(net.state_dict(), save_path)
# 画图
plt.plot(range(1,11), accuracy)
plt.xlabel("epoch")
plt.ylabel("accuracy")
plt.grid()
plt.show()
print("done")
结果展示
reference
《PyTorch深度学习实践》完结合集_哔哩哔哩_bilibili