识别黑白图中的服装图案(Fashion-MNIST)
https://blog.csdn.net/qq_39237205/article/details/123379997
基于上述代码修改模型的组成
1 修改myConNet模型
1.1.1 修改阐述
将模型中的两个全连接层,变为全局平均池化层。
1.1.2 修改结果
### 1.5 定义模型类 class myConNet(torch.nn.Module): def __init__(self): super(myConNet, self).__init__() # 定义卷积层 self.conv1 = torch.nn.Conv2d(in_channels = 1 ,out_channels = 6,kernel_size = 3) self.conv2 = torch.nn.Conv2d(in_channels = 6,out_channels = 12,kernel_size = 3) self.conv3 = torch.nn.Conv2d(in_channels = 12, out_channels=10, kernel_size = 3) # 分为10个类 def forward(self,t): # 第一层卷积和池化处理 t = self.conv1(t) t = F.relu(t) t = F.max_pool2d(t, kernel_size=2, stride=2) # 第二层卷积和池化处理 t = self.conv2(t) t = F.relu(t) t = F.max_pool2d(t, kernel_size=2, stride=2) # 第三层卷积和池化处理 t = self.conv3(t) t = F.avg_pool2d(t,kernel_size = t.shape[-2:],stride = t.shape[-2:]) # 设置池化区域为输入数据的大小(最后两个维度),完成全局平均化的处理。 return t.reshape(t.shape[:2])
2 代码
import torchvision import torchvision.transforms as transforms import pylab import torch from matplotlib import pyplot as plt import torch.utils.data import torch.nn.functional as F import numpy as np import os os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE" # 定义显示图像的函数 def imshow(img): print("图片形状",np.shape(img)) img = img/2 +0.5 npimg = img.numpy() plt.axis('off') plt.imshow(np.transpose(npimg,(1,2,0))) ### 1.1 自动下载FashionMNIST数据集 data_dir = './fashion_mnist' # 设置存放位置 transform = transforms.Compose([transforms.ToTensor()]) # 可以自动将图片转化为Pytorch支持的形状[通道,高,宽],同时也将图片的数值归一化 train_dataset = torchvision.datasets.FashionMNIST(data_dir,train=True,transform=transform,download=True) print("训练集的条数",len(train_dataset)) ### 1.2 读取及显示FashionMNIST数据集中的数据 val_dataset = torchvision.datasets.FashionMNIST(root=data_dir,train=False,transform=transform) print("测试集的条数",len(val_dataset)) ##1.2.1 显示数据集中的数据 im = train_dataset[0][0].numpy() im = im.reshape(-1,28) pylab.imshow(im) pylab.show() print("当前图片的标签为",train_dataset[0][1]) ### 1.3 按批次封装FashionMNIST数据集 batch_size = 10 #设置批次大小 train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = torch.utils.data.DataLoader(val_dataset, batch_size=batch_size, shuffle=False) ### 1.4 读取批次数据集 ## 定义类别名称 classes = ('T-shirt', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle_Boot') sample = iter(train_loader) # 将数据集转化成迭代器 images,labels = sample.next() # 从迭代器中取得一批数据 print("样本形状",np.shape(images)) # 打印样本形状 # 输出 样本形状 torch.Size([10, 1, 28, 28]) print("样本标签",labels) # 输出 图片形状 torch.Size([3, 32, 302]) imshow(torchvision.utils.make_grid(images,nrow = batch_size)) # 数据可视化:make_grid()将该批次的图片内容组合为一个图片,用于显示,nrow用于设置生成图片中每行的样本数量 print(','.join('%5s' % classes[labels[j]] for j in range(len(images)))) # 输出 Trouser,Trouser,Dress, Bag,Shirt,Sandal,Shirt,Dress, Bag, Bag ### 1.5 定义模型类 class myConNet(torch.nn.Module): def __init__(self): super(myConNet, self).__init__() # 定义卷积层 self.conv1 = torch.nn.Conv2d(in_channels = 1 ,out_channels = 6,kernel_size = 3) self.conv2 = torch.nn.Conv2d(in_channels = 6,out_channels = 12,kernel_size = 3) self.conv3 = torch.nn.Conv2d(in_channels = 12, out_channels=10, kernel_size = 3) # 分为10个类 def forward(self,t): # 第一层卷积和池化处理 t = self.conv1(t) t = F.relu(t) t = F.max_pool2d(t, kernel_size=2, stride=2) # 第二层卷积和池化处理 t = self.conv2(t) t = F.relu(t) t = F.max_pool2d(t, kernel_size=2, stride=2) # 第三层卷积和池化处理 t = self.conv3(t) t = F.avg_pool2d(t,kernel_size = t.shape[-2:],stride = t.shape[-2:]) # 设置池化区域为输入数据的大小(最后两个维度),完成全局平均化的处理。 return t.reshape(t.shape[:2]) if __name__ == '__main__': network = myConNet() # 生成自定义模块的实例化对象 #指定设备 device = torch.device("cuda:0"if torch.cuda.is_available() else "cpu") print(device) network.to(device) print(network) # 打印myConNet网络 ### 1.6 损失函数与优化器 criterion = torch.nn.CrossEntropyLoss() #实例化损失函数类 optimizer = torch.optim.Adam(network.parameters(), lr=.01) ### 1.7 训练模型 for epoch in range(2): # 数据集迭代2次 running_loss = 0.0 for i, data in enumerate(train_loader, 0): # 循环取出批次数据 使用enumerate()函数对循环计数,第二个参数为0,表示从0开始 inputs, labels = data inputs, labels = inputs.to(device), labels.to(device) # optimizer.zero_grad() # 清空之前的梯度 outputs = network(inputs) loss = criterion(outputs, labels) # 计算损失 loss.backward() # 反向传播 optimizer.step() # 更新参数 running_loss += loss.item() ### 训练过程的显示 if i % 1000 == 999: print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss = 0.0 print('Finished Training') ### 1.8 保存模型 torch.save(network.state_dict(),'./models/CNNFashionMNist.PTH') ### 1.9 加载模型,并且使用该模型进行预测 network.load_state_dict(torch.load('./models/CNNFashionMNist.PTH')) # 加载模型 # 使用模型 dataiter = iter(test_loader) # 获取测试数据 images, labels = dataiter.next() inputs, labels = images.to(device), labels.to(device) imshow(torchvision.utils.make_grid(images, nrow=batch_size)) # 取出一批数据进行展示 print('真实标签: ', ' '.join('%5s' % classes[labels[j]] for j in range(len(images)))) # 输出:真实标签: Ankle_Boot Pullover Trouser Trouser Shirt Trouser Coat Shirt Sandal Sneaker outputs = network(inputs) # 调用network对输入样本进行预测,得到测试结果outputs _, predicted = torch.max(outputs, 1) # 对于预测结果outputs沿着第1维度找出最大值及其索引值,该索引值即为预测的分类结果 print('预测结果: ', ' '.join('%5s' % classes[predicted[j]] for j in range(len(images)))) # 输出:预测结果: Ankle_Boot Pullover Trouser Trouser Pullover Trouser Shirt Shirt Sandal Sneaker ### 1.10 评估模型 # 测试模型 class_correct = list(0. for i in range(10)) # 定义列表,收集每个类的正确个数 class_total = list(0. for i in range(10)) # 定义列表,收集每个类的总个数 with torch.no_grad(): for data in test_loader: # 遍历测试数据集 images, labels = data inputs, labels = images.to(device), labels.to(device) outputs = network(inputs) # 将每个批次的数据输入模型 _, predicted = torch.max(outputs, 1) # 计算预测结果 predicted = predicted.to(device) c = (predicted == labels).squeeze() # 统计正确的个数 for i in range(10): # 遍历所有类别 label = labels[i] class_correct[label] = class_correct[label] + c[i].item() # 若该类别正确则+1 class_total[label] = class_total[label] + 1 # 根据标签中的类别,计算类的总数 sumacc = 0 for i in range(10): # 输出每个类的预测结果 Accuracy = 100 * class_correct[i] / class_total[i] print('Accuracy of %5s : %2d %%' % (classes[i], Accuracy)) sumacc = sumacc + Accuracy print('Accuracy of all : %2d %%' % (sumacc / 10.)) # 输出最终的准确率
输出: Accuracy of T-shirt : 72 % Accuracy of Trouser : 96 % Accuracy of Pullover : 75 % Accuracy of Dress : 72 % Accuracy of Coat : 75 % Accuracy of Sandal : 90 % Accuracy of Shirt : 35 % Accuracy of Sneaker : 93 % Accuracy of Bag : 92 % Accuracy of Ankle_Boot : 92 % Accuracy of all : 79 %