深度学习前沿应用图像分类Fine-Tuning
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度学习前沿应用图像分类Fine-Tuning相关的知识,希望对你有一定的参考价值。
【深度学习前沿应用】图像分类Fine-Tuning
(文章目录)
前言
1. 什么是预训练-微调模式?
在计算机视觉领域,预训练-微调模式已经沿用了多年,即在大规模图片数据集预训练模型参数,然后将训练好的参数在新的小数据集任务上进行微调,从而产生泛化性能更好的模型。
2. 什么是ResNet?
ResNet为常用的预训练模型之一,其核心操作为卷积与残差连接。卷积层为3×3的滤波器,并遵循两个简单的设计规则:①对于相同的输出特征图尺寸,每层具有相同数量的滤波器;②如果特征图尺寸减半,则滤波器数量加倍,以保持每层的时间复杂度。直接用步长为2的卷积层进行下采样,网络以全局平均池化层和伴随softmax的1000维全连接层结束,其中,卷积层数为34,因此也称为ResNet34(如下图1所示)。
本小节将使用ResNet34预训练-微调框架,实现猫脸12分类。对于给定的猫脸,判断其所属类型。
一、数据加载及预处理
本实验数据集来源于网络开源数据集(https://aistudio.baidu.com/aistudio/datasetdetail/10954),该数据集中包含12类猫图片,总计数据量为2160,部分图片展示如下图1所示。
(一)、数据加载及预处理
首先将该数据集挂载到当前项目中,然后读取数据文件,将数据按照8:2划分为训练集与验证集
- 导入相关包
import os
import time
import os.path as osp
import zipfile
import numpy as np
import paddle
import paddle.nn as nn
import pandas as pd
import paddle.nn.functional as F
from PIL import Image
from paddle.io import Dataset, DataLoader
from paddle.optimizer import Adam
from paddle.vision import Compose, ToTensor, Resize
from paddle.vision.models import resnet34
from paddle.metric import Accuracy
from sklearn.model_selection import StratifiedShuffleSplit
- 将train划分为训练集和验证集
info = pd.read_csv(osp.join(./data, train_list.txt), sep=\\t, header=None)
images, labels = info.iloc[:, 0], info.iloc[:, 1]
split = StratifiedShuffleSplit(test_size=0.2)
train_idx, valid_idx = next(split.split(images, labels))
info_tr = info.iloc[train_idx, :]
info_va = info.iloc[valid_idx, :]
info_tr.to_csv(data/train.csv, header=False, index=False)
info_va.to_csv(data/valid.csv, header=False, index=False)
(二)、数据集封装
class CatDataset(Dataset):
train_file = cat_12_train.zip
test_file = cat_12_test.zip
train_label = train_list.txt
def __init__(self, root, mode, transform=None):
super(CatDataset, self).__init__()
self.root = root
self.mode = mode
self.transform = transform
if not osp.isfile(osp.join(root, self.train_file)) or \\
not osp.isfile(osp.join(root, self.train_label)) or \\
not osp.isfile(osp.join(root, self.test_file)):
raise ValueError(wrong data path)
if not osp.isdir(osp.join(self.root, cat_12_train)):
with zipfile.ZipFile(osp.join(root, self.train_file)) as f:
f.extractall(root)
with zipfile.ZipFile(osp.join(root, self.test_file)) as f:
f.extractall(root)
if mode == train:
info = pd.read_csv(osp.join(root, train_list.txt), sep=\\t, header=None)
self.images = info.iloc[:, 0].to_list()
self.labels = paddle.to_tensor(
info.iloc[:, 1].to_list()
)
elif mode == train_:
info = pd.read_csv(osp.join(root, train.csv), header=None)
self.images = info.iloc[:, 0].to_list()
self.labels = paddle.to_tensor(
info.iloc[:, 1].to_list()
)
pass
elif mode == valid_:
info = pd.read_csv(osp.join(root, valid.csv), header=None)
self.images = info.iloc[:, 0].to_list()
self.labels = paddle.to_tensor(
info.iloc[:, 1].to_list()
)
else:
images = os.listdir(os.path.join(root, cat_12_test))
self.images = [cat_12_test/+image for image in images]
self.labels = None
def __getitem__(self, idx):
image = Image.open(osp.join(self.root, self.images[idx]))
if image.mode != RGB:
image = image.convert(RGB)
if self.transform is not None:
image = self.transform(image)
if self.mode == test:
return image,
else:
label = self.labels[idx]
return image, label
def __len__(self):
return len(self.images)
(三)、样本分类与统计
paddle.set_device(gpu if paddle.is_compiled_with_cuda() else cpu)
transform = Compose([
Resize([224, 224]),
ToTensor()
])
train_ds = CatDataset(./data, train_, transform)
valid_ds = CatDataset(./data, valid_, transform)
train_dl = DataLoader(train_ds, batch_size=64, shuffle=True)
valid_dl = DataLoader(valid_ds, batch_size=64, shuffle=False)
print(训练集样本数:,train_ds.__len__())
print(验证集样本数:,valid_ds.__len__())
二、预训练模型加载
paddle,vision是飞桨在视觉领域的高层API,内部封装了常用的数据集以及常用预测训练模型,如LeNet、VGG系列、ResNet系列及MobileNet系列等。本实验使用resnet34为例,演示如何进行图像分类的微调。
准备好数据集之后,加载预训练模型,调用net=resnet34(pretrained=True),设置参数pretrained为True,便可使用预训练好的参数,否则,需要从头开始训练参数(首次加载预训练参数时需要从相关专业网络中下载):
加载预训练模型,并设置类别数目为12(猫的分类)
net = resnet34(pretrained=True, num_classes=12)
三、模型微调
加载好预训练的模型之后,定义模型的优化器、评价指标等,输入领域数据,执行微调:
(一)、定义优化器
optimizer = Adam(
parameters=net.parameters(),
learning_rate=1e-5
)
(二)、定义损失函数
loss_fn = nn.CrossEntropyLoss()
(三)、定义准确率评价指标
metric_fn = Accuracy()
(四)、微调20轮
for epoch in range(20):
t0 = time.time()
net.train()
for data, label in train_dl:
logit = net(data)
loss = loss_fn(logit, label.astype(int64))
optimizer.clear_grad()
loss.backward()
optimizer.step()
# 验证
net.eval()
loss_tr = 0.
for data, label in train_dl:
logit = net(data)
label = label.astype(int64)
loss_tr += loss_fn(logit, label).cpu().numpy()[0]
loss_tr /= len(train_dl)
loss_va = 0.
for data, label in valid_dl:
label = label.astype(int64)
logit = net(data)
loss_va += loss_fn(logit, label).cpu().numpy()[0]
metric_fn.update(
metric_fn.compute(logit, label)
)
loss_va /= len(valid_dl)
acc_va = metric_fn.accumulate()
metric_fn.reset()
t = time.time() - t0
print([Epoch :3d :.2fs] train loss(:.4f); valid loss(:.4f), acc(:.2f)
.format(epoch, t, loss_tr, loss_va, acc_va))
训练过程部分输出如下图2所示:
四、模型预测
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
def show_image(file_name):
img = mpimg.imread(data/+file_name)
plt.figure(figsize=(10,10))
plt.imshow(img)
plt.show()
test_ds = CatDataset(./data, mode=test, transform=transform)
test_dl = DataLoader(test_ds, batch_size=32, shuffle=False)
test_pred = []
with paddle.no_grad():
for data, in test_dl:
logit = net(data)
pred = paddle.argmax(
F.softmax(logit, axis=-1),
axis=-1
)
test_pred.append(pred.cpu().numpy())
test_pred = np.concatenate(test_pred, axis=0)
for image, pred in zip(test_ds.images, test_pred.astype(np.int)):
img = mpimg.imread(data/+image)
plt.figure(figsize=(10,10))
plt.imshow(img)
plt.show()
print(图片路径:%s, 图片预测类型:%d\\n % (image.split(/)[1], pred))
预测结果部分输出如下图3、4、5、6所示
总结
本系列文章内容为根据清华社出版的《机器学习实践》所作的相关笔记和感悟,其中代码均为基于百度飞桨开发,若有任何侵权和不妥之处,请私信于我,定积极配合处理,看到必回!!!
最后,引用本次活动的一句话,来作为文章的结语~( ̄▽ ̄~)~:
【**学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。**】
以上是关于深度学习前沿应用图像分类Fine-Tuning的主要内容,如果未能解决你的问题,请参考以下文章