目录
5.5 实践:基于ResNet18网络完成图像分类任务
5.5.1 数据处理
5.5.1.1数据集介绍
5.5.1.3 构造Dataset类
5.5.2 模型构建
5.5.3 模型训练
5.5.4 模型评价
5.5.5 模型预测
思考题
总结
图像分类(Image Classification)是计算机视觉中的一个基础任务,将图像的语义将不同图像划分到不同类别。很多任务可以转换为图像分类任务。比如人脸检测就是判断一个区域内是否有人脸,可以看作一个二分类的图像分类任务。
数据集:CIFAR-10数据集
网络:ResNet18模型
损失函数:交叉熵损失
优化器:Adam优化器,Adam优化器的介绍参考NNDL第7.2.4.3节。
评价指标:准确率。
CIFAR-10数据集包含了10种不同的类别、共60,000张图像,其中每个类别的图像都是6000张,图像大小均为32×3232×32像素。
5.5.1.2 数据读取
在本实验中,将原始训练集拆分成了train_set、dev_set两个部分,分别包括40 000条和10 000条样本。将data_batch_1到data_batch_4作为训练集,data_batch_5作为验证集,test_batch作为测试集。
最终的数据集构成为:
读取一个batch数据,查看数据的维度并可视化观察其中的一张样本图像和对应的标签:
import os
import pickle
import numpy as np
def load_cifar10_batch(folder_path, batch_id=1, mode='train'):
if mode == 'test':
file_path = os.path.join(folder_path, 'test_batch')
else:
file_path = os.path.join(folder_path, 'data_batch_' + str(batch_id))
# 加载数据集文件
with open(file_path, 'rb') as batch_file:
batch = pickle.load(batch_file, encoding='latin1')
imgs = batch['data'].reshape((len(batch['data']), 3, 32, 32)) / 255.
labels = batch['labels']
return np.array(imgs, dtype='float32'), np.array(labels)
imgs_batch, labels_batch = load_cifar10_batch(folder_path='D:\\QQFiles\\1831277247\\FileRecv\\cifar-10-python\\cifar-10-batches-py',
batch_id=1, mode='train')
# 打印一下每个batch中X和y的维度
print("batch of imgs shape: ", imgs_batch.shape, "batch of labels shape: ", labels_batch.shape)
import matplotlib.pyplot as plt
image, label = imgs_batch[1], labels_batch[1]
print("The label in the picture is {}".format(label))
plt.figure(figsize=(2, 2))
plt.imshow(image.transpose(1,2,0))
plt.savefig('cnn-car.pdf')
构造一个CIFAR10Dataset类
import torch
from torch.utils.data import Dataset, DataLoader
import torchvision.transforms as transforms
import PIL.Image as Image
class CIFAR10Dataset(Dataset):
def __init__(self, folder_path='D:\\QQFiles\\1831277247\\FileRecv\\cifar-10-python\\cifar-10-batches-py', mode='train'):
if mode == 'train':
# 加载batch1-batch4作为训练集
self.imgs, self.labels = load_cifar10_batch(folder_path=folder_path, batch_id=1, mode='train')
for i in range(2, 5):
imgs_batch, labels_batch = load_cifar10_batch(folder_path=folder_path, batch_id=i, mode='train')
self.imgs, self.labels = np.concatenate([self.imgs, imgs_batch]), np.concatenate(
[self.labels, labels_batch])
elif mode == 'dev':
# 加载batch5作为验证集
self.imgs, self.labels = load_cifar10_batch(folder_path=folder_path, batch_id=5, mode='dev')
elif mode == 'test':
# 加载测试集
self.imgs, self.labels = load_cifar10_batch(folder_path=folder_path, mode='test')
self.transform = transforms.Compose([
transforms.Resize((224, 224)), transforms.RandomHorizontalFlip(p=0.5), transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])
def __getitem__(self, idx):
img, label = self.imgs[idx], self.labels[idx]
img = img.transpose(1, 2, 0)
img = Image.fromarray(np.uint8(img))
img = self.transform(img)
return img, label
def __len__(self):
return len(self.imgs)
train_dataset = CIFAR10Dataset(folder_path='D:\\QQFiles\\1831277247\\FileRecv\\cifar-10-python\\cifar-10-batches-py', mode='train')
dev_dataset = CIFAR10Dataset(folder_path='D:\\QQFiles\\1831277247\\FileRecv\\cifar-10-python\\cifar-10-batches-py', mode='dev')
test_dataset = CIFAR10Dataset(folder_path='D:\\QQFiles\\1831277247\\FileRecv\\cifar-10-python\\cifar-10-batches-py', mode='test')
from torchvision.models import resnet18
resnet18_model = resnet18()
什么是“预训练模型”?什么是“迁移学习”?
预训练模型就是预先训练一个模型,然后根据任务所需对预先训练出的模型进行调整,使之更符合自己的目标任务,从而提高效率与精度。迁移学习是一种机器学习技术,就是指将知识从一个领域迁移到另一个领域的能力。神经网络需要用数据来训练,它从数据中获得信息,进而把它们转换成相应的权重。这些权重能够被提取出来,迁移到其他的神经网络中。
比较“使用预训练模型”和“不使用预训练模型”的效果。
resnet = models.resnet18(pretrained=True)
resnet = models.resnet18(pretrained=False)
未进行预训练
可以看出进行预训练后准确率更高
【深度学习】使用预训练模型_DrCrypto的博客-CSDN博客_深度学习预训练模型操作
pytorch学习笔记之加载预训练模型_AI算法札记的博客-CSDN博客_pytorch加载预训练模型
import torch.nn.functional as F
import torch.optim as opt
# 指定运行设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)
# 学习率大小
lr = 0.01
# 批次大小
batch_size = 64
# 加载数据
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
dev_loader = DataLoader(dev_dataset, batch_size=batch_size)
test_loader = DataLoader(test_dataset, batch_size=batch_size)
# 定义网络
model = resnet18_model
model.to(device)
# 定义优化器,这里使用Adam优化器以及l2正则化策略,相关内容在7.3.3.2和7.6.2中会进行详细介绍
optimizer = opt.SGD(model.parameters(),lr=lr, momentum=0.9)
# 定义损失函数
loss_fn = F.cross_entropy
# 定义评价指标
metric = Accuracy()
# 实例化RunnerV3
runner = RunnerV3(model, optimizer, loss_fn, metric)
# 启动训练
log_steps = 3000
eval_steps = 3000
runner.train(train_loader, dev_loader, num_epochs=30, log_steps=log_steps,
eval_steps=eval_steps, save_path="best_model.pdparams")
使用测试数据对在训练过程中保存的最佳模型进行评价,观察模型在测试集上的准确率以及损失情况
# 加载最优模型
runner.load_model('best_model.pdparams')
# 模型评价
score, loss = runner.evaluate(test_loader)
print("[Test] accuracy/loss: {:.4f}/{:.4f}".format(score, loss))
[Test] accuracy/loss: 0.8140/0.5936
同样地,也可以使用保存好的模型,对测试集中的数据进行模型预测,观察模型效果
# 获取测试集中的一个batch的数据
X, label = next(test_loader())
logits = runner.predict(X)
# 多分类,使用softmax计算预测概率
pred = F.softmax(logits)
# 获取概率最大的类别
pred_class = paddle.argmax(pred[2]).numpy()
label = label[2][0].numpy()
# 输出真实类别与预测类别
print("The true category is {} and the predicted category is {}".format(label[0], pred_class[0]))
# 可视化图片
X=np.array(X)
plt.imshow(X.transpose(1, 2, 0))
plt.show()
The true category is 8 and the predicted category is 8
1.阅读《Deep Residual Learning for Image Recognition》,了解5种深度的ResNet(18,34,50,101和152),并简单谈谈自己的看法
图中是5种深度的ResNet,分别是18,34,50,101和152,每个网络都有5部分——conv1,conv2_x,conv3_x,conv4_x,conv5_x。看一下ResNet18,有一个7x7x64的卷积,下面是(2+2+2+2)*2=16层,还有一个fc层,总共18层
2.用自己的话简单评价:LeNet、AlexNet、VGG、GoogLeNet、ResNet
LeNet-5的输入一般都是尺寸较小,并且灰度的图像。如果想处理更高分辨率图像的话,就需要叠加更多的卷积层,增加模型的容量。
AlextNet跟LeNet网络结构相似,只是因为叠加了更多的卷积层使得网络更深了。此外,在卷积层也使用了更多的过滤器。它含有8层网络,整体的结构是:5个卷积层(每个卷积都接了池化层),2个全连接层,以及softmax层。其中,每个卷积层和全连接层都使用了ReLU激活函数。
它有13个卷积层,2个全连接层,以及softmax层。其中,在所有的卷积层中,都使用3*3的过滤器。作者实验了不同网络层数的VGGNet,从11->13->16层,效果一直都有明显的改进。但是从16->19层后,效果有微降的趋势。这可能是网络加深到一定层数后,梯度消失/爆炸的问题开始突显。
为了避免网络过深导致的巨大参数量,GoogLeNet使用了1*1的卷积操作,并且在网络最后使用了全局的平均池化来代替全连接层。网络的参数量大约是AlexNet的1/10。
ResNet
主要解决深层网络梯度消失问题。
使用思维导图全面总结CNN
参考
经典深度学习CNN总结 - LeNet、AlexNet、GoogLeNet、VGG、ResNet
经典的卷积神经网络:LeNet,AlexNet,GoogLeNet,VGG,ResNet
NNDL 实验5(下)
Deep Residual Learning for Image Recognition