基于百度AIStudio飞桨paddleRS-develop版道路模型开发训练
参考地址:https://aistudio.baidu.com/projectdetail/8271882
基于python35+paddle120+env环境
预测可视化结果:
(一)安装环境:
先上传本地下载的源代码PaddleRS-develop.zip
解压PaddleRS-develop.zip到目录PaddleRS
然后分别执行下面安装命令!pip install
!unzip -q /home/aistudio/data/data191076/PaddleRS-develop.zip && mv PaddleRS-develop PaddleRS
!pip install matplotlib==3.4 scikit-image pycocotools -t /home/aistudio/external-libraries
!pip install opencv-contrib-python -t /home/aistudio/external-libraries
!pip install -r PaddleRS/requirements.txt -t /home/aistudio/external-libraries
!pip install -e PaddleRS/ -t /home/aistudio/external-libraries
!pip install paddleslim==2.6.0 -t /home/aistudio/external-libraries
添加环境组件
# 因为`sys.path`可能没有及时更新,这里选择手动更新
import sys
sys.path.append('/home/aistudio/external-libraries')
sys.path.append('/home/aistudio/PaddleRS')
(二)数据预处理tran_dataPre.py
%run tran_dataPre.py
(三)开始模型训练
%run trans.py
(四) tran_dataPre.py内容如下所示:
#先解压数据集
#!unzip -oq -d /home/aistudio/massroad /home/aistudio/data/data56961/mass_road.zip
# 划分训练集/验证集/测试集,并生成文件名列表
import random
import os.path as osp
from os import listdir
import cv2
# 随机数生成器种子
RNG_SEED = 56961
# 调节此参数控制训练集数据的占比
TRAIN_RATIO = 0.9
# 数据集路径
DATA_DIR = '/home/aistudio/massroad'
# 分割类别
CLASSES = (
'background',
'road',
)
def write_rel_paths(phase, names, out_dir, prefix):
"""将文件相对路径存储在txt格式文件中"""
with open(osp.join(out_dir, phase+'.txt'), 'w') as f:
for name in names:
f.write(
' '.join([
osp.join(prefix, 'input', name),
osp.join(prefix, 'output', name)
])
)
f.write('\n')
random.seed(RNG_SEED)
train_prefix = osp.join('road_segmentation_ideal', 'training')
test_prefix = osp.join('road_segmentation_ideal', 'testing')
train_names = listdir(osp.join(DATA_DIR, train_prefix, 'output'))
train_names = list(filter(lambda n: n.endswith('.png'), train_names))
test_names = listdir(osp.join(DATA_DIR, test_prefix, 'output'))
test_names = list(filter(lambda n: n.endswith('.png'), test_names))
# 对文件名进行排序,以确保多次运行结果一致
train_names.sort()
test_names.sort()
random.shuffle(train_names)
len_train = int(len(train_names)*TRAIN_RATIO)
write_rel_paths('train', train_names[:len_train], DATA_DIR, train_prefix)
write_rel_paths('val', train_names[len_train:], DATA_DIR, train_prefix)
write_rel_paths('test', test_names, DATA_DIR, test_prefix)
# 写入类别信息
with open(osp.join(DATA_DIR, 'labels.txt'), 'w') as f:
for cls in CLASSES:
f.write(cls+'\n')
print("数据集划分已完成。")
# 将GT中的255改写为1,便于训练
import os.path as osp
from glob import glob
import cv2
from tqdm import tqdm
# 数据集路径
# DATA_DIR = '/home/aistudio/massroad'
train_prefix = osp.join('road_segmentation_ideal', 'training')
test_prefix = osp.join('road_segmentation_ideal', 'testing')
train_paths = glob(osp.join(DATA_DIR, train_prefix, 'output', '*.png'))
test_paths = glob(osp.join(DATA_DIR, test_prefix, 'output', '*.png'))
for path in tqdm(train_paths+test_paths):
im = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
im[im>0] = 1
# 原地改写
cv2.imwrite(path, im)
(五) trans.py内容如下所示:
# 导入需要用到的库
import random
import os.path as osp
import cv2
import numpy as np
import paddle
import paddlers as pdrs
from paddlers import transforms as T
from matplotlib import pyplot as plt
from PIL import Image
import sys
sys.path.append('/home/aistudio/external-libraries')
sys.path.append('/home/aistudio/PaddleRS')
# 定义全局变量
# 随机种子
SEED = 56961
# 数据集存放目录
DATA_DIR = '/home/aistudio/massroad/'
# 训练集`file_list`文件路径
TRAIN_FILE_LIST_PATH = '/home/aistudio/massroad/train.txt'
# 验证集`file_list`文件路径
VAL_FILE_LIST_PATH = '/home/aistudio/massroad/val.txt'
# 测试集`file_list`文件路径
TEST_FILE_LIST_PATH = '/home/aistudio/massroad/test.txt'
# 数据集类别信息文件路径
LABEL_LIST_PATH = '/home/aistudio/massroad/labels.txt'
# 实验目录,保存输出的模型权重和结果
EXP_DIR = '/home/aistudio/exp/'
# 固定随机种子,尽可能使实验结果可复现
random.seed(SEED)
np.random.seed(SEED)
paddle.seed(SEED)
# 构建数据集
# 定义训练和验证时使用的数据变换(数据增强、预处理等)
train_transforms = T.Compose([
T.DecodeImg(),
# 随机裁剪
T.RandomCrop(crop_size=512),
# 以50%的概率实施随机水平翻转
T.RandomHorizontalFlip(prob=0.5),
# 以50%的概率实施随机垂直翻转
T.RandomVerticalFlip(prob=0.5),
# 将数据归一化到[-1,1]
T.Normalize(
mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
T.ArrangeSegmenter('train')
])
eval_transforms = T.Compose([
T.DecodeImg(),
T.Resize(target_size=1500),
# 验证阶段与训练阶段的数据归一化方式必须相同
T.Normalize(
mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
T.ArrangeSegmenter('eval')
])
# 分别构建训练和验证所用的数据集
train_dataset = pdrs.datasets.SegDataset(
data_dir=DATA_DIR,
file_list=TRAIN_FILE_LIST_PATH,
label_list=LABEL_LIST_PATH,
transforms=train_transforms,
num_workers=4,
shuffle=True
)
val_dataset = pdrs.datasets.SegDataset(
data_dir=DATA_DIR,
file_list=VAL_FILE_LIST_PATH,
label_list=LABEL_LIST_PATH,
transforms=eval_transforms,
num_workers=0,
shuffle=False
)
# 构建DeepLab V3+模型,使用ResNet-50作为backbone
model = pdrs.tasks.seg.DeepLabV3P(
in_channels=3,
num_classes=len(train_dataset.labels),
backbone='ResNet50_vd'
)
model.initialize_net(
pretrain_weights='CITYSCAPES',
save_dir=osp.join(EXP_DIR, 'pretrain'),
resume_checkpoint=None,
is_backbone_weights=False
)
# 构建优化器
optimizer = paddle.optimizer.Adam(
learning_rate=0.001,
parameters=model.net.parameters()
)
# 执行模型训练
model.train(
num_epochs=100,
train_dataset=train_dataset,
train_batch_size=8,
eval_dataset=val_dataset,
optimizer=optimizer,
save_interval_epochs=10,
# 每多少次迭代记录一次日志
log_interval_steps=30,
save_dir=EXP_DIR,
# 是否使用early stopping策略,当精度不再改善时提前终止训练
early_stop=False,
# 是否启用VisualDL日志功能
use_vdl=True,
# 指定从某个检查点继续训练
resume_checkpoint=None
)
(六)训练生成过程信息
Output exceeds the size limit. Open the full output data in a text editor
2024-09-05 14:16:51 [INFO] Loading pretrained model from /home/aistudio/exp/pretrain/model.pdparams
2024-09-05 14:16:53 [WARNING] [SKIP] Shape of parameters head.decoder.conv.weight do not match. (pretrained: [19, 256, 1, 1] vs actual: [2, 256, 1, 1])
2024-09-05 14:16:53 [WARNING] [SKIP] Shape of parameters head.decoder.conv.bias do not match. (pretrained: [19] vs actual: [2])
2024-09-05 14:16:53 [INFO] There are 358/360 variables loaded into DeepLabV3P.
2024-09-05 14:17:46 [INFO] [TRAIN] Epoch=1/100, Step=30/90, loss=0.133503, lr=0.001000, time_each_step=1.77s, eta=4:24:32
2024-09-05 14:18:25 [INFO] [TRAIN] Epoch=1/100, Step=60/90, loss=0.181917, lr=0.001000, time_each_step=1.31s, eta=3:14:53
2024-09-05 14:19:02 [INFO] [TRAIN] Epoch=1/100, Step=90/90, loss=0.112567, lr=0.001000, time_each_step=1.22s, eta=3:2:6
2024-09-05 14:19:03 [INFO] [TRAIN] Epoch 1 finished, loss=0.15933047160506247 .
2024-09-05 14:19:44 [INFO] [TRAIN] Epoch=2/100, Step=30/90, loss=0.141528, lr=0.001000, time_each_step=1.36s, eta=3:22:2
2024-09-05 14:20:20 [INFO] [TRAIN] Epoch=2/100, Step=60/90, loss=0.165187, lr=0.001000, time_each_step=1.22s, eta=3:0:42
2024-09-05 14:20:57 [INFO] [TRAIN] Epoch=2/100, Step=90/90, loss=0.145009, lr=0.001000, time_each_step=1.22s, eta=2:59:1
2024-09-05 14:20:58 [INFO] [TRAIN] Epoch 2 finished, loss=0.1168842613697052 .
2024-09-05 14:21:39 [INFO] [TRAIN] Epoch=3/100, Step=30/90, loss=0.126603, lr=0.001000, time_each_step=1.38s, eta=3:22:13
2024-09-05 14:22:16 [INFO] [TRAIN] Epoch=3/100, Step=60/90, loss=0.117296, lr=0.001000, time_each_step=1.22s, eta=2:58:14
2024-09-05 14:22:53 [INFO] [TRAIN] Epoch=3/100, Step=90/90, loss=0.072859, lr=0.001000, time_each_step=1.23s, eta=2:58:46
2024-09-05 14:22:53 [INFO] [TRAIN] Epoch 3 finished, loss=0.10787189056475957 .
2024-09-05 14:23:34 [INFO] [TRAIN] Epoch=4/100, Step=30/90, loss=0.081685, lr=0.001000, time_each_step=1.37s, eta=3:18:39
2024-09-05 14:24:11 [INFO] [TRAIN] Epoch=4/100, Step=60/90, loss=0.087735, lr=0.001000, time_each_step=1.23s, eta=2:57:28
2024-09-05 14:24:48 [INFO] [TRAIN] Epoch=4/100, Step=90/90, loss=0.084795, lr=0.001000, time_each_step=1.22s, eta=2:55:44
2024-09-05 14:24:49 [INFO] [TRAIN] Epoch 4 finished, loss=0.10476481277081702 .
2024-09-05 14:25:30 [INFO] [TRAIN] Epoch=5/100, Step=30/90, loss=0.098625, lr=0.001000, time_each_step=1.37s, eta=3:16:59
2024-09-05 14:26:07 [INFO] [TRAIN] Epoch=5/100, Step=60/90, loss=0.078188, lr=0.001000, time_each_step=1.24s, eta=2:57:12
2024-09-05 14:26:43 [INFO] [TRAIN] Epoch=5/100, Step=90/90, loss=0.098015, lr=0.001000, time_each_step=1.21s, eta=2:52:11
2024-09-05 14:26:44 [INFO] [TRAIN] Epoch 5 finished, loss=0.10311256903741095 .
2024-09-05 14:27:25 [INFO] [TRAIN] Epoch=6/100, Step=30/90, loss=0.109136, lr=0.001000, time_each_step=1.38s, eta=3:16:8
...
2024-09-05 15:39:38 [INFO] Start to evaluate (total_samples=81, total_steps=81)...
2024-09-05 15:40:14 [INFO] [EVAL] Finished, Epoch=40, miou=0.716638, category_iou=[0.96831487 0.46496069], oacc=0.969164, category_acc=[0.97447995 0.81316509], kappa=0.619485, category_F1-score=[0.98390241 0.63477565] .
2024-09-05 15:40:14 [INFO] Current evaluated best model on eval_dataset is epoch_10, miou=0.7255623401044613
2024-09-05 15:40:18 [INFO] Model saved in /home/aistudio/exp/epoch_40.
(七) 测试集预测结果:
# 构建测试集
test_dataset = pdrs.datasets.SegDataset(
data_dir=DATA_DIR,
file_list=TEST_FILE_LIST_PATH,
label_list=LABEL_LIST_PATH,
transforms=eval_transforms,
num_workers=0,
shuffle=False
)
# 为模型加载历史最佳权重
state_dict = paddle.load(osp.join(EXP_DIR, 'best_model/model.pdparams'))
model.net.set_state_dict(state_dict)
# 执行测试
test_result = model.evaluate(test_dataset)
print(
"测试集上指标:IoU为{:.2f},Acc为{:.2f},Kappa系数为{:.2f}, F1为{:.2f}".format(
test_result['category_iou'][1],
test_result['category_acc'][1],
test_result['kappa'],
test_result['category_F1-score'][1]
)
)
2024-09-05 20:07:40 [INFO] 13 samples in file /home/aistudio/massroad/test.txt
2024-09-05 20:07:41 [INFO] Start to evaluate (total_samples=13, total_steps=13)...
测试集上指标:IoU为0.47,Acc为0.82,Kappa系数为0.62, F1为0.64
(八)预测结果可视化情况:
# 预测结果可视化
# 重复运行本单元可以查看不同结果
def read_image(path):
im = cv2.imread(path)
return im[...,::-1]
def show_images_in_row(ims, fig, title='', quantize=False):
n = len(ims)
fig.suptitle(title)
axs = fig.subplots(nrows=1, ncols=n)
for idx, (im, ax) in enumerate(zip(ims, axs)):
# 去掉刻度线和边框
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.get_xaxis().set_ticks([])
ax.get_yaxis().set_ticks([])
if isinstance(im, str):
im = read_image(im)
if quantize:
im = (im*255).astype('uint8')
if im.ndim == 2:
im = np.tile(im[...,np.newaxis], [1,1,3])
ax.imshow(im)
# 需要展示的样本个数
num_imgs_to_show = 4
# 随机抽取样本
chosen_indices = random.choices(range(len(test_dataset)), k=num_imgs_to_show)
# 参考 https://stackoverflow.com/a/68209152
fig = plt.figure(constrained_layout=True)
fig.suptitle("Test Results")
subfigs = fig.subfigures(nrows=3, ncols=1)
# 读取输入影像并显示
im_paths = [test_dataset.file_list[idx]['image'] for idx in chosen_indices]
show_images_in_row(im_paths, subfigs[0], title='Image')
# 获取模型预测输出
with paddle.no_grad():
model.net.eval()
preds = []
for idx in chosen_indices:
input, mask = test_dataset[idx]
input = paddle.to_tensor(input["image"]).unsqueeze(0)
logits, *_ = model.net(input)
pred = paddle.argmax(logits[0], axis=0)
preds.append(pred.numpy())
show_images_in_row(preds, subfigs[1], title='Pred', quantize=True)
# 读取真值标签并显示
im_paths = [test_dataset.file_list[idx]['mask'] for idx in chosen_indices]
show_images_in_row(im_paths, subfigs[2], title='GT', quantize=True)
# 渲染结果
fig.canvas.draw()
Image.frombytes('RGB', fig.canvas.get_width_height(), fig.canvas.tostring_rgb())
本blog地址:https://blog.csdn.net/hsg77