转自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的像素重新设置为一种新的类别,即背景类,并强制模型学习如何区分前景与背景类。然而,这一做法导致任务变得复杂(因为背景类样本的类内差异极大,且占比极高),使模型性能下降。

综合以上分析,在算法调优过程中。可以尝试的策略包括但不限于:实施数据重采样、使用针对类别不均衡问题设计的损失函数等等。

软件杯-地物分类功能相关推荐

  1. python遥感影像地物分类_基于轻量化语义分割网络的遥感图像地物分类方法与流程...

    本发明属于图像处理 技术领域: ,特别涉及一种地物分类方法,可用于土地利用分析.环境保护以及城市规划. 背景技术: :遥感图像地物分类,旨在取代繁琐的人工作业,利用地物分类方法,得到输入遥感图像的地物 ...

  2. 【十一届软件杯】遥感解译赛道:变化检测任务——预赛第四名方案分享

    十一届软件杯遥感解译赛道--预赛第四名方案分享 本Notebook为基于软件杯官方Baseline更改的项目,结合个人理解,进行了一些优化和更改,分数会比Baseline要高一点,并且将可以继续优化的 ...

  3. 企业网上下单订货管理软件源码搭建功能介绍|移讯云订货通订单管理系统

    网上下单订货管理软件源码搭建功能介绍|移讯云订货通订单管理系统 一:系统概述和用途 系统基于网络,实现厂家和代理商批发商通过网络下单订货功能. 什么是移讯云订货通.什么是企业订货管理系统. 是一款针对 ...

  4. 「滑板+EdgeBoard 竟能搭出AI质检流水线?」“软件杯”全国一等奖团队参赛心得...

    "中国软件杯"大学生软件设计大赛由工信部.教育部及江苏省人民政府主办,为全国普通高校学科竞赛榜单中的重要赛事之一,旨在探索具有中国特色的软件人才产教融合培养路径,培养满足产业发展需 ...

  5. 苹果手机功能大全介绍_抖音手机软件剪辑推荐及功能介绍

    剪辑软件推荐: 1.巧影(免费),功能介绍 为剪辑中的 视频.图像.贴图.文本.手写提供多图层操作功能. 逐帧修剪.拼接和切片:实时预览:色调.亮度和饱和度控制:视频剪辑速度控制 声音渐弱渐强(整体) ...

  6. 数字IC所用软件及IP分类

    数字IC所用软件及IP分类 Synopsys--新思科技 VCS-Verilog Compile Simulater Verdi ICC/ICC2--布局布线工具 Starrc--寄生参数提取工具 D ...

  7. 对于一款软件而言,完备的功能固然重要,但交互体验也不该被忽视

    一般情况下,软件开发的前期设计以及开发的过程中,满足其功能性的优先级要高于交互界面的美观性.以至于业界中众多软件平台的UI设计,与其完备的功能形成落差.对于对美感稍有追求和欣赏能力的用户来说,使用时所 ...

  8. ArcGIS地物分类专题图制作

    文章目录 地物分类专题图制作 1. 准备工作 1.1. 软件安装 1.2. 数据准备 2. 制图 2.1. 添加数据 2.2. 添加颜色 2.3. 页面调整 2.4. 插入图信息 3. 保存信息及导出 ...

  9. 游戏陪玩app软件开发,这些功能你需要,一定要知道

    纵观市场上的各种游戏陪玩软件,同样是游戏陪玩app软件开发,有些是主打游戏辅助社交,有些是社交游戏各占一半,还有一些打着游戏社交的幌子,实际上做的是社交交友软件,只是增加了游戏陪玩的模块而已,在游戏社 ...

最新文章

  1. OpenCV Mat数据类型及位数总结
  2. ECMAScript 2021(ES12)新特性简介
  3. 华为鸿蒙智慧屏评价,华为智慧屏 S真实感受曝光评测,不看后悔死了!
  4. Beatiful Soup获取淘宝商品详情
  5. 一个JAVA WEB伪全栈的VUE入坑随笔,从零点零五学起
  6. JavaScript alert延迟弹出
  7. Mysql 5.7 Gtid内部学习(八) Gtid带来的运维改变
  8. 【Android系统源码修改】去掉开机时显示的正在优化应用对话框
  9. 用Geek Uninstaller在win10下卸载office2010
  10. xftp6成功安装教程(踩坑系列)
  11. 一篇文章让你详细了解新手第一次如何使用物联网卡,满满的干货!
  12. 华为云 云学院 白嫖
  13. linux查看云锁密码命令,Linux安装云锁
  14. SCUT01在线协作白板技术解决方案
  15. C语言-字符0、数字0和‘\0’的区别
  16. android 主流机型排行,安卓手机性能排行:华为Mate40 Pro仅排第四,第一名无可撼动...
  17. nagios的安装及nrpe的配置
  18. 用两条命令看出你买的H3C光模块是否是正品
  19. 小白都能看懂的实战教程 手把手教你Python Web全栈开发(DAY 3)
  20. Java计算一个时间段与当前时间的进度百分比

热门文章

  1. Google代投技巧
  2. Down by the Salley Gardens 走进莎莉花园
  3. 前端命名规范(经常查阅)
  4. 小红书热门话题!美妆赛道爆文案例
  5. 银行信贷管理学试题库【1】
  6. 2017年9月25日日志
  7. 英文期刊催稿信模板_英文杂志的催稿信
  8. Java实现的小玩具
  9. 替换法(代入法)求解递归式
  10. 这次畅捷通新品发布确定新打法 重新定义小微企业场景服务