深度学习-CNN案例_图像分类
CIFAR-10数据集5万张训练图像、1万张测试图像、10个类别、每个类别有6k个图像,图像大小32×32×3。下图列举了10个类,每一类随机展示了10张图片:
CNN搭建流程
案例:
演示CNN的综合案例,图像分类
回顾:深度学习项目的步骤
1.准备数据集.
这里我们用的时候 计算机视觉模块 torchvision 自带的 CIFAR10数据集,包含6W张(32,32,3)的图片,5W张训练集,1W张测试集,10个分类,每个分类6K张图片
需要单独安装一下torchvison 包,即pip install torchvision
2. 搭建(卷积)神经网络
3.模型训练
4.模型测试
卷积层:
提取图像的局部特征 ——>特征图(Feature Map),计算方式: N = math.floor(W-F+2P)//S + 1
池化层:
降维:有最大池化 和 平均池化
池化只在HW上做调整,通道上不改变
导包
import torch
import torch.nn as nn
from torchvision.datasets import CIFAR10
from torchvision.transforms import ToTensor # pip install torchvision -i https://mirrors.aliyun.com/pypi/simple/
import torch.optim as optim
from torch.utils.data import DataLoader
import time
import matplotlib.pyplot as plt
from torchsummary import summary
# 每批次样本数
BATCH_SIZE = 8
1. 准备数据集合
def create_dataset():
# 1. 获取数据集
# 参1:数据集路径;参2:是否是训练集;参3:数据预处理——>张量数据;参4:是否联网下载(若没有就会联网)
train_dataset = CIFAR10(root='./data', train=True,transform=ToTensor(), download=True)
# 2. 获取测试集
test_dataset = CIFAR10(root='./data', train=False,transform=ToTensor(), download=True)
# 3. 返回数据集
return train_dataset, test_dataset
2. 搭建(卷积)神经网络
class ImageModel(nn.Module):
# 1. 初始化父类成员,搭建神经网络
def __init__(self):
# 1.1 初始化父类成员
super().__init__()
# 1.2 搭建神经网络
# 第1个卷积层. 输入3通道,输出6通道,卷积核大小3,步长1,填充0
self.conv1 = nn.Conv2d(3,6,3,1,0)
# 第1个池化层,窗口大小2*2,步长2,填充0
self.pool1 = nn.MaxPool2d(2,2,0)
# 第2个卷积层. 输入6通道,输出16通道,卷积核大小3*3,步长1,填充0
self.conv2 = nn.Conv2d(6,16,3,1,0)
# 第2个池化层,窗口大小 2*2,步长2,填充0
self.pool2 = nn.MaxPool2d(2,2,0)
# 第1个隐藏层(全连接层);输入576,输出120
self.linear1 = nn.Linear(576,120)
# 第2个隐藏层(全连接层);输入120,输出84
self.linear2 = nn.Linear(120, 84)
# 第3个隐藏层(全连接层);输入84,输出10
self.output = nn.Linear(84, 10)
# 2. 定义前向传播
def forward(self,x):
# 第1层,卷积层(加权求和) + 激励层(激活函数) + 池化层(降维)
x = self.pool1(torch.relu(self.conv1(x)))
# 第2层,卷积层(加权求和) + 激励层(激活函数) + 池化层(降维)
x = self.pool2(torch.relu(self.conv2(x)))
# 细节:全连接层只能处理二维数据,因此要对数据进行拉平(8,16,6,6)——>(8,576)
# 参1:样本数(行数),参2:列数(特征数),-1表示自动计算; 8行576列
x = x.reshape(x.size(0),-1)
# 第3层:全连接层(加权求和) + 激励层(激活函数)
x = torch.relu(self.linear1(x))
# 第4层:全连接层(加权求和) + 激励层(激活函数)
x = torch.relu(self.linear2(x))
# 第5层,全连接层(加权求和)——>输出层
return self.output(x) # 后续用 多分类交叉熵损失函数CrossEntropyLoss = softmax()激活函数 + 损失计算
3. 模型训练
def train(train_dataset,test_dataset):
# 1.创建数据加载器;
# shuffle=True 一句话作用:每个 epoch 开始时,把整个数据集样本顺序彻底打乱
dataloader = DataLoader(train_dataset,batch_size=BATCH_SIZE,shuffle=True)
# 2.创建模型对象
model = ImageModel()
# 3.创建损失函数对象
criterion = nn.CrossEntropyLoss() # 多分类交叉熵损失函数 = softmax()激活函数 + 损失计算
# 4. 创建优化器对象
optimizer = optim.Adam(model.parameters(),lr=0.001)
# 5. 循环遍历epoch,开始每轮的训练动作
# 5.1 定义变量,记录训练的总轮数
epochs = 10 # 训练的总轮数,10轮
# 5.2 遍历,完成每轮的 所有批次的 训练动作
for epoch_idx in range(epochs):
# 5.2.1 定义变量,记录总损失,总样本数据量,预测正确样本个数,训练(开始)时间
total_loss,total_samples,total_correct,start = 0,0,0,time.time()
# 5.2.2 遍历数据加载器,获取到每批次的数据
for x,y in dataloader:
# 切换训练模式
model.train()
# 5.2.4 模型预测
y_pred = model(x)
# 5.2.5 计算损失
loss = criterion(y_pred,y)
# 5.2.6 梯度清零+反向传播+参数更新
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 5.2.7 统计预测正确的样本个数
# print(y_pred) # 批次中,每张图 每个分类的 预测概率
# # argmax() 返回最大值对应的索引,作为该图片的预测分类
# print(torch.argmax(y_pred,dim=-1))
# print((torch.argmax(y_pred,dim=-1) == y).sum()) # 预测正确的样本个数
total_correct += (torch.argmax(y_pred,dim=-1) == y).sum()
# 5.2.8 统计当前批次的总损失.
total_loss += loss.item() * len(y) # [第一批总损失+第二批总损失+...]
# 5.2.9 统计当前批次的总样本个数
total_samples += len(y)
# break 每轮只训练1批,提高训练效率,只有测试会这么写,实际开发绝不要这么做
# 5.2.10 走这里,说明一轮训练完毕,打印该轮的训练信息
print(f'epoch:{epoch_idx+1},loss:{total_loss/total_samples:.5f},acc:{total_correct/total_samples:.5f},time:{time.time()-start:.5f}')
# break 这里写break 意味着只训练一轮
# 6. 保存模型
torch.save(model.state_dict(),'image_model.pth')
4. 模型测试
def evaluate(test_dataset):
# 1. 创建测试集数据加载器
dataloader = DataLoader(test_dataset,batch_size=BATCH_SIZE,shuffle=True)
# 2. 创建模型对象
model = ImageModel()
# 3. 加载模型参数
model.load_state_dict(torch.load('image_model.pth')) # pickle文件
# 4.定义变量,统计预测正确的样本个数与总样本个数
total_correct,total_samples = 0,0
# 5. 遍历数据加载器,获取到每批次的数据
for x,y in dataloader:
# 5.1 切换模型模式
model.eval()
# 5.2 模型预测
y_pred = model(x) # 这一步输出的是一个原始的logic值,而不是0-1的概率
# 5.3 因为训练的时候用了CrossEntropyLoss,所以搭建神经网络的时候没有加softmax()激活函数,这里要用argmax()来模拟;
# argmax()函数功能: 返回最大值对应的索引,充当——>该图片的预测分类.
y_pred = torch.argmax(y_pred,dim=-1) # -1表示行
# 5.4 统计预测正确的样本个数
total_correct += (torch.argmax(y_pred,dim=-1) == y).sum()
# 5.5 统计总样本个数
total_samples += len(y)
# 6. 打印正确率
print(f'ACC:{total_correct/total_samples:.2f}')
5.测试
if __name__ == '__main__':
# # 1. 获取数据集
train_dataset, test_dataset = create_dataset()
# print(f'训练集:{train_dataset.data.shape},测试集:{test_dataset.data.shape}')
# print(f'数据集类别:{train_dataset.class_to_idx}') #
#
# # 图像展示:
# plt.figure(figsize=(2,2))
# plt.imshow(train_dataset.data[1111]) # 索引是11的图像
# plt.title(train_dataset.targets[1111])
# plt.show()
# 2.搭建神经网络
model = ImageModel()
# 查看模型参数
# 参1:模型;参2:输出维度(CHW,通道,高,宽),参3:批次大小
# summary(model,(3,32,32),batch_size=BATCH_SIZE)
# 3. 模型训练
# train(train_dataset,test_dataset)
# 4. 模型评估
evaluate(test_dataset)

浙公网安备 33010602011771号