前言
本次分享将带领大家从0到1完成一个语义分割任务,覆盖数据准备、模型训练评估和推理部署的全流程,项目将采用以PaddleSeg为核心的飞浆深度学习框架进行开发,并总结开发过程中踩过的一些坑,希望能为有类似项目需求的同学提供一点帮助。
项目背景和目标
背景:
- 语义分割是计算机视觉的一个基础任务。本次选用的案例来自现实生活场景,通过人像分割,实现背景替换。项目最后,将实现一个AI证件照的应用,并将应用部署到 AI Studio 平台,由于场景对实时性有更高要求,本次采用百度自研的 PP-LiteSeg 进行模型训练和部署。
目标:
- 基于paddlepaddle深度学习框架完成一个语义分割任务;
- 完成模型的训练、评估、预测和部署等深度学习任务全过程。
百度AI Studio平台
本次实验将采用AI Studio实训平台中的免费GPU资源,在平台注册账号后,点击创建项目-选择NoteBook任务,然后添加数据集,如下图所示,完成项目创建。启动环境可以自行选择CPU资源 or GPU资源,创建任务每天有8点免费算力,推荐大家使用GPU资源进行模型训练,这样会大幅减少模型训练时长。
飞浆深度学习开发框架介绍
PaddlePaddle百度提供的开源深度学习框架,其中文名是“飞桨”,致力于为开发者和企业提供最好的深度学习研发体验,国产框架中绝对的榜一大哥!其核心优势是生态完善,目前集成了各种开发套件,覆盖了数据处理、模型训练、模型验证、模型部署等各个阶段的工具。下面简要介绍一下本项目用到的几个核心组件:
- PaddleSeg:一个语义分割任务的工具集,集成了丰富的主流分割算法和百度自研的最新模型,提供覆盖分割任务全流程的API。
- PaddleServing:将模型部署成一个在线预测服务的库,支持服务端和客户端之间的高并发和高效通信。
- PaddleLite:将模型转换成可以端侧推理的库,比如将模型部署到手机端进行推理。
- Fastdeploy:一款全场景、易用灵活、极致高效的AI推理部署工具,支持云边端等各种部署方式。
从零开始实战
1 PaddleSeg完成模型训练
1.1 安装PaddleSeg
在项目中打开终端,然后运行如下命令:
# (可选)conda安装虚拟环境,环境会持久保存在项目中
conda create -p envs/py38 python=3.8
source activate envs/py38
# 安装paddlepaddle,根据云端环境选择cpu版本和gpu版本
pip install --upgrade paddlepaddle -i https://mirror.baidu.com/pypi/simple
pip install --upgrade paddlepaddle-gpu -i https://mirror.baidu.com/pypi/simple
# 下载PaddleSeg代码 注意要安装2.9版本,gitee上是2.8
# 如果国内下载太慢,加上镜像https://mirror.ghproxy.com/
git clone https://github.com/PaddlePaddle/PaddleSeg.git
# 安装
cd PaddleSeg
pip install -r requirements.txt
pip install -v -e .
# 测试是否安装成功
sh tests/install/check_predict.sh
1.2 数据准备
数据集介绍
本次实验使用的数据集来自开源的人像语义分割数据集,数据集总共有 7082 张图片,手动划分为训练集、验证集和测试集,其中训练集 5666 张,验证集 1416 张。只包含两种标签类型:背景和人物。大家也可以选择其他开源的人像语义分割数据集。
我们需要制作符合PaddleSeg框架要求的数据集格式:参考准备自定义数据集。
step1: 解压数据集
# 打开终端
cd ~/data/
# -d 指定解压缩的路径,会在data0文件夹下生成koto数据集,持久保存在云端环境种
unzip data59640/koto.zip -d ../data0
step2: 制作标签文件
python generate_dataset.py
# 其中generate_dataset.py中的代码如下:
'''
import os
import cv2
import numpy as np
from tqdm import tqdm
# modify the data txt file
dataset_dir = '/home/aistudio/data0/koto'
for txt in ['train_list.txt', 'valid_list.txt']:
output = []
with open(dataset_dir + '/' + txt, 'r') as f:
lines = f.readlines()
for line in lines:
image, label = line.strip().split(' ')
image = image.replace('/mnt/d/data/koto/', '')
label = label.replace('/mnt/d/data/koto/', '')
output.append(image + ' ' + label)
with open(dataset_dir + '/new_' + txt, 'w') as f:
f.writelines(f'{line}'+'\n' for line in output)
# 将Label图像转换为标签,0:背景,1:人像
anno_dir = '/home/aistudio/data0/koto/annos'
annos = os.listdir(anno_dir)
for anno in tqdm(annos):
anno_file = os.path.join(anno_dir, anno)
label = cv2.imread(anno_file, 0)
new_label = np.zeros(label.shape, dtype=np.uint8)
if label[0, 0] < 10: # 背景黑色,人像白色
new_label[label > 128] = 1
else:
new_label[label <= 128] = 1
cv2.imwrite(anno_file, new_label)
'''
# 如果希望将灰度标注图转换为伪彩色标注图,可以执行以下命令。
cd PaddleSeg
python tools/data/gray2pseudo_color.py /home/aistudio/data0/koto/annos /home/aistudio/data0/koto/annos_color
如上,我们便完成了数据的准备工作,接下来将完成模型在该数据集上的训练。
1.3 模型训练:
这里我们以选用PaddleSeg自带的pp_liteseg为例,有关该模型的介绍可参考官方文档。
- 准备训练配置文件-以pp_liteseg为例:
cp configs/quick_start/pp_liteseg_optic_disc_512x512_1k.yml configs/quick_start/pp_liteseg_person_seg.yml
# 修改其中对应的数据集信息
'''
train_dataset:
type: Dataset
dataset_root: /home/aistudio/data0/koto/
train_path: /home/aistudio/data0/koto/new_train_list.txt
val_dataset:
type: Dataset
dataset_root: /home/aistudio/data0/koto/
val_path: /home/aistudio/data0/koto/new_valid_list.txt
'''
- 开启训练
python tools/train.py --config configs/quick_start/pp_liteseg_person_seg.yml --do_eval --use_vdl --save_interval 500 --save_dir output/liteseg
- 如果选用 UNet 模型
# 重新准备训练配置文件
cp configs/unet/unet_chasedb1_128x128_40k.yml configs/unet/unet_person_seg.yml
# 修改其中对应的数据集信息,如下
'''
batch_size: 16
iters: 10000
train_dataset:
type: Dataset
dataset_root: /home/aistudio/data0/koto/
train_path: /home/aistudio/data0/koto/new_train_list.txt
num_classes: 2
mode: train
transforms:
- type: ResizeStepScaling
min_scale_factor: 0.5
max_scale_factor: 2.0
scale_step_size: 0.25
- type: RandomPaddingCrop
crop_size: [512, 512]
- type: RandomHorizontalFlip
- type: RandomDistort
brightness_range: 0.5
contrast_range: 0.5
saturation_range: 0.5
- type: Normalize
val_dataset:
type: Dataset