软件杯-地物分类功能
转自AI Studio,原文链接:【官方】第十一届 “中国软件杯”百度遥感赛项:地物分类功能 - 飞桨AI Studio
第十一届 “中国软件杯”百度遥感赛项:地物分类功能
1 比赛介绍
“中国软件杯”大学生软件设计大赛是一项面向中国在校学生的公益性赛事,是2021年全国普通高校大学生竞赛榜单内竞赛。大赛由国家工业和信息化部、教育部、江苏省人民政府共同主办,致力于正确引导我国在校学生积极参加软件科研活动,切实增强自我创新能力和实际动手能力,为我国软件和信息技术服务业培养出更多高端、优秀的人才。2022年,百度飞桨承办了A组和B组两个赛道,本赛题为A组。
比赛官网链接
2 数据集介绍
本项目使用飞桨常规赛:遥感影像地块分割数据集。该赛题由2020 CCF BDCI 遥感影像地块分割赛题优化而来,旨在对遥感影像进行像素级内容解析,对遥感影像中感兴趣的类别进行提取和分类。比赛所用的数据集亦是对BDCI数据集的简化。
数据集链接。
3 数据预处理
In [ ]
# 解压数据集
!unzip -oq -d /home/aistudio/data/data77571/dataset/ /home/aistudio/data/data77571/train_and_label.zip
In [ ]
# 划分训练集/验证集/测试集,并生成文件名列表
# 注意,作为演示,本项目仅使用原数据集的训练集,即用来测试的数据也来自原数据集的训练集import random
import os.path as osp
from os import listdirimport cv2# 随机数生成器种子
RNG_SEED = 77571
# 调节此参数控制训练集数据的占比
TRAIN_RATIO = 0.9
# 调节此参数控制验证集数据的占比
VAL_RATIO = 0.05
# 使用的样本个数(选取排序靠前的样本)
NUM_SAMPLES_TO_USE = 10000
# 数据集路径
DATA_DIR = '/home/aistudio/data/data77571/dataset/'# 分割类别
CLASSES = ('cls0','cls1','cls2','cls3','bg'
)def reset_pixels(name):path = osp.join(DATA_DIR, 'lab_train', name)im = cv2.imread(path, cv2.IMREAD_GRAYSCALE)im[im==255] = CLASSES.index('bg')cv2.imwrite(path, im)def write_rel_paths(phase, names, out_dir):"""将文件相对路径存储在txt格式文件中"""with open(osp.join(out_dir, phase+'.txt'), 'w') as f:for name in names:f.write(' '.join([osp.join('img_train', name.replace('.png', '.jpg')),osp.join('lab_train', name)]))f.write('\n')random.seed(RNG_SEED)names = listdir(osp.join(DATA_DIR, 'lab_train'))
# 将值为255的无效像素重设为背景类
for name in names:reset_pixels(name)
# 对文件名进行排序,以确保多次运行结果一致
names.sort()
if NUM_SAMPLES_TO_USE is not None:names = names[:NUM_SAMPLES_TO_USE]
random.shuffle(names)
len_train = int(len(names)*TRAIN_RATIO)
len_val = int(len(names)*VAL_RATIO)
write_rel_paths('train', names[:len_train], DATA_DIR)
write_rel_paths('val', names[len_train:len_train+len_val], DATA_DIR)
write_rel_paths('test', names[len_train+len_val:], DATA_DIR)# 写入类别信息
with open(osp.join(DATA_DIR, 'labels.txt'), 'w') as f:for cls in CLASSES:f.write(cls+'\n')print("数据集划分已完成。")
4 模型训练与测试
4.1 依赖安装
In [ ]
# 安装matplotlib
!pip install matplotlib==3.4 > /dev/null# 安装PaddleRS(AI Studio上缓存的版本)
!unzip -o -d /home/aistudio/ /home/aistudio/data/data135375/PaddleRS-develop.zip > /dev/null
!mv /home/aistudio/PaddleRS-develop /home/aistudio/PaddleRS
!pip install -e /home/aistudio/PaddleRS > /dev/null
# 因为`sys.path`可能没有及时更新,这里选择手动更新
import sys
sys.path.append('/home/aistudio/PaddleRS')
4.2 模型训练
In [ ]
# 导入需要用到的库import random
import os.path as ospimport 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
In [ ]
# 定义全局变量# 随机种子
SEED = 77571
# 数据集存放目录
DATA_DIR = '/home/aistudio/data/data77571/dataset/'
# 训练集`file_list`文件路径
TRAIN_FILE_LIST_PATH = '/home/aistudio/data/data77571/dataset/train.txt'
# 验证集`file_list`文件路径
VAL_FILE_LIST_PATH = '/home/aistudio/data/data77571/dataset/val.txt'
# 测试集`file_list`文件路径
TEST_FILE_LIST_PATH = '/home/aistudio/data/data77571/dataset/test.txt'
# 数据集类别信息文件路径
LABEL_LIST_PATH = '/home/aistudio/data/data77571/dataset/labels.txt'
# 实验目录,保存输出的模型权重和结果
EXP_DIR = '/home/aistudio/exp/'
In [ ]
# 固定随机种子,尽可能使实验结果可复现random.seed(SEED)
np.random.seed(SEED)
paddle.seed(SEED)
In [ ]
# 构建数据集# 定义训练和验证时使用的数据变换(数据增强、预处理等)
train_transforms = T.Compose([# 将影像缩放到256x256大小T.Resize(target_size=256),# 以50%的概率实施随机水平翻转T.RandomHorizontalFlip(prob=0.5),# 将数据归一化到[-1,1]T.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
])eval_transforms = T.Compose([T.Resize(target_size=256),# 验证阶段与训练阶段的数据归一化方式必须相同T.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
])# 分别构建训练和验证所用的数据集
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
)
In [ ]
# 构建DeepLab V3+模型,使用ResNet-50作为backbone
model = pdrs.tasks.DeepLabV3P(input_channel=3,num_classes=len(train_dataset.labels),backbone='ResNet50_vd'
)
model.net_initialize(pretrain_weights='CITYSCAPES',save_dir=osp.join(EXP_DIR, 'pretrain'),resume_checkpoint=None,is_backbone_weights=False
)# 使用focal loss作为损失函数
model.losses = dict(types=[pdrs.models.ppseg.models.FocalLoss()],coef=[1.0]
)# 制定定步长学习率衰减策略
lr_scheduler = paddle.optimizer.lr.StepDecay(0.001,step_size=8000,gamma=0.5
)
# 构造Adam优化器
optimizer = paddle.optimizer.Adam(learning_rate=lr_scheduler,parameters=model.net.parameters()
)
In [ ]
# 执行模型训练
model.train(num_epochs=30,train_dataset=train_dataset,train_batch_size=16,eval_dataset=val_dataset,optimizer=optimizer,save_interval_epochs=3,# 每多少次迭代记录一次日志log_interval_steps=100,save_dir=EXP_DIR,# 是否使用early stopping策略,当精度不再改善时提前终止训练early_stop=False,# 是否启用VisualDL日志功能use_vdl=True,# 指定从某个检查点继续训练resume_checkpoint=None
)
4.3 模型测试
In [ ]
# 构建测试集
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("测试集上指标:mIoU为{:.2f},OAcc为{:.2f},Kappa系数为{:.2f}".format(test_result['miou'], test_result['oacc'],test_result['kappa'],)
)
print("各类IoU分别为:"+', '.join('{:.2f}'.format(iou) for iou in test_result['category_iou']))
print("各类Acc分别为:"+', '.join('{:.2f}'.format(acc) for acc in test_result['category_acc']))
print("各类F1分别为:"+', '.join('{:.2f}'.format(f1) for f1 in test_result['category_F1-score']))
4.4 预测结果可视化
In [16]
# 预测结果可视化
# 重复运行本单元可以查看不同结果def show_images_in_row(ims, fig, title='', lut=None):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 = cv2.imread(im, cv2.IMREAD_COLOR)if lut is not None:if im.ndim == 3:im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)im = lut[im]else:im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)ax.imshow(im)def get_lut():lut = np.zeros((256,3), dtype=np.uint8)lut[0] = [255, 0, 0]lut[1] = [30, 255, 142]lut[2] = [60, 0, 255]lut[3] = [255, 222, 0]lut[4] = [0, 0, 0]return lut# 需要展示的样本个数
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, _ = test_dataset[idx]input = paddle.to_tensor(input).unsqueeze(0)logits, *_ = model.net(input)pred = paddle.argmax(logits[0], axis=0)pred = pred.numpy().astype(np.uint8)preds.append(pred)
show_images_in_row(preds, subfigs[1], title='Pred', lut=get_lut())# 读取真值标签并显示
im_paths = [test_dataset.file_list[idx]['mask'] for idx in chosen_indices]
show_images_in_row(im_paths, subfigs[2], title='GT', lut=get_lut())# 渲染结果
fig.canvas.draw()
Image.frombytes('RGB', fig.canvas.get_width_height(), fig.canvas.tostring_rgb())
<PIL.Image.Image image mode=RGB size=640x480 at 0x7F3A583A4B10>
5 算法调优建议
由于被标记为“感兴趣地物类别”的像素仅仅占全体样本中非常小的部分,因此原始数据集存在严重的类别分布不均衡问题。如果在模型训练过程中直接忽略未标记的像素(即原始标签中值为255的像素),令这部分像素不参与loss计算与反向传播,则训练得到的模型将无法有效识别背景类。这导致在推理真实影像时,模型给影像中的每个像素分配感兴趣地物类别中的一种,而实际上输入影像中很可能根本不包含这些地物。为了解决这一问题,本项目将原始标签中值为255的像素重新设置为一种新的类别,即背景类,并强制模型学习如何区分前景与背景类。然而,这一做法导致任务变得复杂(因为背景类样本的类内差异极大,且占比极高),使模型性能下降。
综合以上分析,在算法调优过程中。可以尝试的策略包括但不限于:实施数据重采样、使用针对类别不均衡问题设计的损失函数等等。
软件杯-地物分类功能相关推荐
- python遥感影像地物分类_基于轻量化语义分割网络的遥感图像地物分类方法与流程...
本发明属于图像处理 技术领域: ,特别涉及一种地物分类方法,可用于土地利用分析.环境保护以及城市规划. 背景技术: :遥感图像地物分类,旨在取代繁琐的人工作业,利用地物分类方法,得到输入遥感图像的地物 ...
- 【十一届软件杯】遥感解译赛道:变化检测任务——预赛第四名方案分享
十一届软件杯遥感解译赛道--预赛第四名方案分享 本Notebook为基于软件杯官方Baseline更改的项目,结合个人理解,进行了一些优化和更改,分数会比Baseline要高一点,并且将可以继续优化的 ...
- 企业网上下单订货管理软件源码搭建功能介绍|移讯云订货通订单管理系统
网上下单订货管理软件源码搭建功能介绍|移讯云订货通订单管理系统 一:系统概述和用途 系统基于网络,实现厂家和代理商批发商通过网络下单订货功能. 什么是移讯云订货通.什么是企业订货管理系统. 是一款针对 ...
- 「滑板+EdgeBoard 竟能搭出AI质检流水线?」“软件杯”全国一等奖团队参赛心得...
"中国软件杯"大学生软件设计大赛由工信部.教育部及江苏省人民政府主办,为全国普通高校学科竞赛榜单中的重要赛事之一,旨在探索具有中国特色的软件人才产教融合培养路径,培养满足产业发展需 ...
- 苹果手机功能大全介绍_抖音手机软件剪辑推荐及功能介绍
剪辑软件推荐: 1.巧影(免费),功能介绍 为剪辑中的 视频.图像.贴图.文本.手写提供多图层操作功能. 逐帧修剪.拼接和切片:实时预览:色调.亮度和饱和度控制:视频剪辑速度控制 声音渐弱渐强(整体) ...
- 数字IC所用软件及IP分类
数字IC所用软件及IP分类 Synopsys--新思科技 VCS-Verilog Compile Simulater Verdi ICC/ICC2--布局布线工具 Starrc--寄生参数提取工具 D ...
- 对于一款软件而言,完备的功能固然重要,但交互体验也不该被忽视
一般情况下,软件开发的前期设计以及开发的过程中,满足其功能性的优先级要高于交互界面的美观性.以至于业界中众多软件平台的UI设计,与其完备的功能形成落差.对于对美感稍有追求和欣赏能力的用户来说,使用时所 ...
- ArcGIS地物分类专题图制作
文章目录 地物分类专题图制作 1. 准备工作 1.1. 软件安装 1.2. 数据准备 2. 制图 2.1. 添加数据 2.2. 添加颜色 2.3. 页面调整 2.4. 插入图信息 3. 保存信息及导出 ...
- 游戏陪玩app软件开发,这些功能你需要,一定要知道
纵观市场上的各种游戏陪玩软件,同样是游戏陪玩app软件开发,有些是主打游戏辅助社交,有些是社交游戏各占一半,还有一些打着游戏社交的幌子,实际上做的是社交交友软件,只是增加了游戏陪玩的模块而已,在游戏社 ...
最新文章
- OpenCV Mat数据类型及位数总结
- ECMAScript 2021(ES12)新特性简介
- 华为鸿蒙智慧屏评价,华为智慧屏 S真实感受曝光评测,不看后悔死了!
- Beatiful Soup获取淘宝商品详情
- 一个JAVA WEB伪全栈的VUE入坑随笔,从零点零五学起
- JavaScript alert延迟弹出
- Mysql 5.7 Gtid内部学习(八) Gtid带来的运维改变
- 【Android系统源码修改】去掉开机时显示的正在优化应用对话框
- 用Geek Uninstaller在win10下卸载office2010
- xftp6成功安装教程(踩坑系列)
- 一篇文章让你详细了解新手第一次如何使用物联网卡,满满的干货!
- 华为云 云学院 白嫖
- linux查看云锁密码命令,Linux安装云锁
- SCUT01在线协作白板技术解决方案
- C语言-字符0、数字0和‘\0’的区别
- android 主流机型排行,安卓手机性能排行:华为Mate40 Pro仅排第四,第一名无可撼动...
- nagios的安装及nrpe的配置
- 用两条命令看出你买的H3C光模块是否是正品
- 小白都能看懂的实战教程 手把手教你Python Web全栈开发(DAY 3)
- Java计算一个时间段与当前时间的进度百分比