当前位置: 首页
AI
基于 PaddlePaddle 框架的 SegNet 论文复现

基于 PaddlePaddle 框架的 SegNet 论文复现

热心网友 时间:2025-07-18
转载
本文复现了SegNet语义分割模型,其为编码器-解码器结构,编码器对应VGG-16前13层,解码器共13层,损失函数采用带median frequency weight的加权交叉熵。在Ai Studio环境配置后,基于PaddleSeg,经模型搭建、损失函数设计及调参,在camvid数据集上复现,结果超原论文60.1%的mIoU精度。

基于 paddlepaddle 框架的 segnet 论文复现 - 游乐网

论文简介

论文名称:SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation
论文地址:https://arxiv.org/pdf/1511.00561.pdf

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

1. 网络结构

基于 PaddlePaddle 框架的 SegNet 论文复现 - 游乐网
总体结构是一个“编码器——解码器”最后加上Softmax层的结构
编码器与VGG-16的前13层,相对应的,解码器也是13层

2. Loss

使用的是交叉熵函数
原论文使用的是“median frequency weight”的加权交叉熵进行计算,每一类的 weight=median(weights)/weights
实验时我们同时使用了不加权重的交叉熵和加权重的交叉熵进行计算,发现加权重的交叉熵效果的确更好

3. Experiments

3.1 Ai Studio 环境配置

由于 Ai Studio 的部分兼容问题,目前使用加权交叉熵需要修改 PaddlePaddle 内置的交叉熵函数,可以在终端中执行如下命令进行暂时的修复:
1.使用 vim 编辑文件:
vim /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/paddle/nn/functional/loss.py
2.注释掉问题语句:
:1414,1420s/^/#/g

之后就可以使用 Ai Studio 环境进行复现

3.2 训练、验证参数设置

在 config.yml 中可以对训练、验证参数进行设置

batch_size: 12  #设定batch_size的值即为迭代一次送入网络的图片数量,一般显卡显存越大,batch_size的值可以越大iters: 1000    #模型迭代的次数train_dataset: #训练数据设置  type: Dataset #选择数据集格式  dataset_root: data/PaddleSeg/camvid #选择数据集路径  train_path: data/PaddleSeg/camvid/train_list.txt #选择数据集list  num_classes: 12 #指定目标的类别个数(背景也算为一类)  transforms: #数据预处理/增强的方式    - type: Resize #送入网络之前需要进行resize      target_size: [512, 512] #将原图resize成512*512在送入网络    - type: RandomHorizontalFlip #采用水平反转的方式进行数据增强    - type: Normalize #图像进行归一化  mode: trainval_dataset: #验证数据设置  type: Dataset #选择数据集格式  dataset_root: data/PaddleSeg/camvid #选择数据集路径  val_path: data/PaddleSeg/camvid/val_list.txt #选择数据集list  num_classes: 12 #指定目标的类别个数(背景也算为一类)  transforms: #数据预处理/增强的方式    - type: Resize  #将原图resize成512*512在送入网络      target_size: [512, 512]  #将原图resize成512*512在送入网络    - type: Normalize #图像进行归一化  mode: valoptimizer: #设定优化器的类型  type: sgd #采用SGD(Stochastic Gradient Descent)随机梯度下降方法为优化器  momentum: 0.9 #动量  weight_decay: 4.0e-5 #权值衰减,使用的目的是防止过拟合learning_rate: #设定学习率  value: 0.1  #初始学习率  decay:    type: poly  #采用poly作为学习率衰减方式。    power: 0.9  #衰减率    end_lr: 0   #最终学习率loss: #设定损失函数的类型  types:    - type: CrossEntropyLoss #损失函数类型  coef: [1]model: #模型说明  type: SegNet  #设定模型类别  num_classes: 12
登录后复制

       

3.3 开始训练

快速开始命令介绍:

cd PaddleSegpython train.py \ # 使用 PaddleSeg 进行训练       --config config.yml \ # 配置文件路径       --do_eval \ # 在保存模型时验证       --use_vdl \ # 使用 visualdl 保存日志       --save_interval 500 \ # 保存模型的频率       --save_dir output # 模型及日志保存路径
登录后复制

       

3.4 训练过程展示

训练日志可以在 github 项目下载:https://github.com/stuartchen1949/segnet_paddle/tree/main/log_upload
下面截取部分信息展示:基于 PaddlePaddle 框架的 SegNet 论文复现 - 游乐网        

基于 PaddlePaddle 框架的 SegNet 论文复现 - 游乐网        

3.5 调参技巧说明

最好是按照原论文的超参数进行复现,这样工作量低
在本论文中,bs=12,lr=0.1,使用 SGD 方法,动量为0.9 但是也可以另辟蹊径,比如:分阶段训练,每个阶段设置学习率不同

3.6 其他说明

截至2024年8月18日,在解码器的 unpool 过程中,Paddle 并无对应的 API,所以在本次复现使用的是 Paddle 的 interpolate 函数,插值方式设置的是“双三次插值”

项目介绍

项目背景

本项目为“飞桨论文复现挑战赛(第四期)”参赛作品,比赛链接:https://aistudio.baidu.com/aistudio/competition/detail/106
目的是复现论文“SegNet: A Deep Convolutional Encoder-Decoder Architecture for Image Segmentation”

项目结果

基于 PaddlePaddle 框架的 SegNet 论文复现 - 游乐网        

结果说明

原论文使用“camvid 11类”数据集达到 miou 精度 60.1% ,我们的结果为 0.5553/11*12=0.605 >60.1% (因为最后一类是void,原论文并未计算,需要消除这个影响)

项目实现思路

大方向

1.模型搭建

2.损失函数设计

3.调参

模型搭建

由于属于 语义分割 问题,故使用 Paddle 的 PaddleSeg 模块进行快速开发
PaddleSeg 快速指南:https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.2/docs/quick_start.md
为了实现复现任务,我们只需要:
1.定义模型并添加至 PaddleSeg 的模型库中
2.计算出交叉熵的权值并修改 PaddleSeg 的 交叉熵函数.py
3.创建 config.py 文件设置超参数

损失函数设计

原论文使用的是“median frequency weight”的加权交叉熵进行计算,每一类的 weight=median(weights)/weights

调参

按照原论文的数据进行设置即可

我们使用的 config.yml 文件内容如下

batch_size: 12iters: 10000train_dataset:  type: Dataset  dataset_root: PaddleSeg/camvid  train_path: PaddleSeg/camvid/train_list.txt  num_classes: 12  transforms:    # - type: Resize    #   target_size: [512, 512]    # - type: RandomHorizontalFlip    - type: Normalize  mode: trainval_dataset:  type: Dataset  dataset_root: PaddleSeg/camvid  val_path: PaddleSeg/camvid/val_list.txt  num_classes: 12  transforms:    # - type: Resize    #   target_size: [512, 512]    - type: Normalize  mode: valoptimizer:  type: sgd  momentum: 0.9  weight_decay: 4.0e-5lr_scheduler:  type: PolynomialDecay  learning_rate: 0.1  end_lr: 0  power: 0.9loss:  types:    - type: CrossEntropyLoss  coef: [1]model:  type: SegNet  num_classes: 12
登录后复制    

我们需要修改 PaddleSeg 中的损失函数 cross_entropy_loss.py ,修改后如下

import paddlefrom paddle import nnimport paddle.nn.functional as Ffrom paddleseg.cvlibs import manager@manager.LOSSES.add_componentclass CrossEntropyLoss(nn.Layer):    """    Implements the cross entropy loss function.    Args:        weight (tuple|list|ndarray|Tensor, optional): A manual rescaling weight            given to each class. Its length must be equal to the number of classes.            Default ``None``.        ignore_index (int64, optional): Specifies a target value that is ignored            and does not contribute to the input gradient. Default ``255``.        top_k_percent_pixels (float, optional): the value lies in [0.0, 1.0]. When its value < 1.0, only compute the loss for            the top k percent pixels (e.g., the top 20% pixels). This is useful for hard pixel mining. Default ``1.0``.        data_format (str, optional): The tensor format to use, 'NCHW' or 'NHWC'. Default ``'NCHW'``.    """    def __init__(self,                 weight=                #  None,                #  [0.49470329175952255,                #  0.35828960644888747,                #  8.478075684728779,                #  0.2632281509876036,                #  1.8575191953843206,                #  0.8569813461262166,                #  7.10457223748049,                #  7.395517740818225,                #  1.4206921357883606,                #  13.036496170307238,                #  28.57158303913671,                # #  2.1105473453421433                #  0],                 [0.5183676152953121,                 0.3754285285214713,                 8.883627718253265,                 0.2758197715255286,                 1.946374345422177,                 0.8979753806852697,                 7.444422201714914,                 7.749285195873823,                 1.4886514942686155,                 13.660102013013443,                 29.938315778195324,                 0],                 ignore_index=11,                 top_k_percent_pixels=1.0,                 data_format='NCHW'):        super(CrossEntropyLoss, self).__init__()        # if weight is not None:        #     weight = paddle.to_tensor(weight, dtype='float32')        if weight is not None:            self.weight = paddle.to_tensor(weight, dtype='float32')            long_weight = weight + [0] * (256 - len(weight))            self.long_weight = paddle.to_tensor(long_weight, dtype='float32')        else:            self.weight = None            self.long_weight = None        # self.weight = weight        self.ignore_index = 11        self.top_k_percent_pixels = top_k_percent_pixels        self.EPS = 1e-8        self.data_format = data_format    def forward(self, logit, label, semantic_weights=None):        """        Forward computation.        Args:            logit (Tensor): Logit tensor, the data type is float32, float64. Shape is                (N, C), where C is number of classes, and if shape is more than 2D, this                is (N, C, D1, D2,..., Dk), k >= 1.            label (Tensor): Label tensor, the data type is int64. Shape is (N), where each                value is 0 <= label[i] <= C-1, and if shape is more than 2D, this is                (N, D1, D2,..., Dk), k >= 1.            semantic_weights (Tensor, optional): Weights about loss for each pixels, shape is the same as label. Default: None.        """        channel_axis = 1 if self.data_format == 'NCHW' else -1        if self.weight is not None and logit.shape[channel_axis] != len(                self.weight):            raise ValueError(                'The number of weights = {} must be the same as the number of classes = {}.'                .format(len(self.weight), logit.shape[1]))        logit = paddle.transpose(logit, [0, 2, 3, 1])        # logit = paddle.transpose(logit, [0, 2, 1])        loss = F.cross_entropy(            logit,            label,            ignore_index=self.ignore_index,            reduction='none',            # weight=self.weight            weight=self.long_weight)        mask = label != self.ignore_index        mask = paddle.cast(mask, 'float32')        loss = loss * mask        if semantic_weights is not None:            loss = loss * semantic_weights        if self.weight is not None:            _one_hot = F.one_hot(label, logit.shape[-1])            coef = paddle.sum(_one_hot * self.weight, axis=-1)        else:            coef = paddle.ones_like(label)        label.stop_gradient = True        mask.stop_gradient = True        if self.top_k_percent_pixels == 1.0:            avg_loss = paddle.mean(loss) / (paddle.mean(mask * coef) + self.EPS)            return avg_loss        loss = loss.reshape((-1, ))        top_k_pixels = int(self.top_k_percent_pixels * loss.numel())        loss, indices = paddle.topk(loss, top_k_pixels)        coef = coef.reshape((-1, ))        coef = paddle.gather(coef, indices)        coef.stop_gradient = True        return loss.mean() / (paddle.mean(coef) + self.EPS)
登录后复制    

添加我们的模型

1. 将 my_model.py 拷贝至 PaddleSeg/paddleseg/model

2. 修改 __init__.py

项目使用

本项目基于 PaddleSeg 开发,所以使用过程简单,下面进行逐步介绍

0. 解压数据集并进行预处理

1. 下载 PaddleSeg

2. 将相应配置文件修改(本项目采用 cp 命令直接对原文件进行覆盖)

3. 运行训练即可

4. 运行验证即可

0. 解压数据集并进行预处理

In [ ]
# 解压数据!unzip -oq /home/aistudio/data/data79232/camvid.zip
登录后复制    In [ ]
# 创建listimport osdir = "camvid"%cd camvid!touch train_list.txt!touch val_list.txt%cdnames = os.listdir(os.path.join(dir, "train"))l = len(names)print("总共%d个数据" %l)n = 0for name in names:    with open("camvid/train_list.txt","r+") as f:        f.read()        # t = "camvid/train/" + name + " camvid/trainannot/" + name + "\n"        t = "train/" + name + " trainannot/" + name + "\n"        f.write(t)    n+=1    # with open("train_list.txt","r+") as f:    #     f.read()    #     t = "camvid/train/" + name + " camvid/trainannot/" + name + "\n"    #     f.write(t)    # n+=1    print("已写入%d路径" %n)dir = "camvid"names = os.listdir(os.path.join(dir, "val"))l = len(names)print("总共%d个数据" %l)n = 0for name in names:    with open("camvid/val_list.txt","r+") as f:        f.read()        # t = "camvid/val/" + name + " camvid/valannot/" + name + "\n"        t = "val/" + name + " valannot/" + name + "\n"        f.write(t)    n+=1    # with open("val_list.txt","r+") as f:    #     f.read()    #     t = "camvid/val/" + name + " camvid/valannot/" + name + "\n"    #     f.write(t)    # n+=1    print("已写入%d路径" %n)dir = "camvid"# %cd camvid!touch train_list.txt# !touch val_list.txt# %cdnames = os.listdir(os.path.join(dir, "train"))l = len(names)print("总共%d个数据" %l)n = 0for name in names:    with open("train_list.txt","r+") as f:        f.read()        t = "camvid/train/" + name + " camvid/trainannot/" + name + "\n"        f.write(t)    n+=1    print("已写入%d路径" %n)
登录后复制    In [ ]
# 平衡数据集 lossimport cv2 as cvimport numpy as nppaths = open("train_list.txt", "r")CLASS_NUM = 11SUM = [[] for i in range(CLASS_NUM)]SUM_ = 0for line in paths:    line.rstrip("\n")    line.lstrip("\n")    path = line.split()    img = cv.imread(path[1], 0)    img_np = np.array(img)    for i in range(CLASS_NUM):        SUM[i].append(np.sum((img_np == i)))for index, iter in enumerate(SUM):    print("类别{}的数量:".format(index), sum(iter))for iter in SUM:    SUM_ += sum(iter)median = 1/CLASS_NUMfor index, iter in enumerate(SUM):    print("weight_{}:".format(index), median/(sum(iter)/SUM_))
登录后复制    

1. 下载 PaddleSeg

In [ ]
# 安装 paddleseg!git clone https://gitee.com/paddlepaddle/PaddleSeg.git!pip install PaddleSeg
登录后复制    

2. 将相应配置文件修改(本项目采用 cp 命令直接对原文件进行覆盖)

In [ ]
# 覆写损失函数!cp cross_entropy_loss.py PaddleSeg/paddleseg/models/losses/# 添加自定义 model!cp my_model.py PaddleSeg/paddleseg/models!cp __init__.py PaddleSeg/paddleseg/models
登录后复制    

3. 运行训练即可

In [ ]
# 训练一 3000 iter ,模型保存至output!python PaddleSeg/train.py \       --config config.yml \       --do_eval \       --use_vdl \       --save_interval 100 \       --log_iters 1 \       --save_dir output \       --iters 3000 \       --keep_checkpoint_max 10 \       --batch_size 12
登录后复制    In [ ]
# 训练二 36000 iter (只训练到了12111),从output读取模型,保存至output1!python PaddleSeg/train.py \       --config config.yml \       --do_eval \       --use_vdl \       --save_interval 1 \       --log_iters 1 \       --save_dir output_1 \       --iters 36000 \       --keep_checkpoint_max 10 \       --resume_model output/iter_3000 \       --batch_size 12
登录后复制    

4. 运行验证即可

In [ ]
# 计算miou,选取output1最好模型!python PaddleSeg/val.py \       --config config.yml \       --model_path output_1/best_model/model.pdparams    #    --model_path model.pdparams # 复制到/home/aistudio文件夹了
登录后复制    
来源:https://www.php.cn/faq/1413697.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
说一下WorkBuddy 的 Plan 模式

说一下WorkBuddy 的 Plan 模式

如何切换到 Plan 模式 想体验这种更可控的方式?操作很简单。在 WorkBuddy 主界面的右下角,你会看到一个“安全模式切换”的下拉菜单,从中选择“Plan”选项即可完成切换。 核心使用流程 光说概念可能有点抽象,咱们直接看个例子。假设你手头有个任务:“把桌面上‘项目报告’文件夹里所有Exce

时间:2026-04-06 22:52
滴滴出行开放打车 Skill,“龙虾”叫车全程不需要切换 App

滴滴出行开放打车 Skill,“龙虾”叫车全程不需要切换 App

滴滴出行全网首发语音打车Skill,一句话智能叫车全攻略 近日,滴滴出行正式上线了一项创新的语音交互功能:全面开放打车Skill。这意味着,用户只需通过语音指令,即可完成从叫车到行程追踪的全流程,真正实现“动口不动手”的便捷出行体验。 整个操作过程,包括目的地搜索、车型比价、下单确认、查看订单状态等

时间:2026-04-06 22:14
阿里千问 AI 眼镜接入蚂蚁 GPASS:语音解锁共享单车、停车缴费

阿里千问 AI 眼镜接入蚂蚁 GPASS:语音解锁共享单车、停车缴费

当AI眼镜学会“跑腿”:语音解锁单车,无感支付停车费 近来,智能穿戴领域的一个新动向值得关注:阿里旗下的千问AI眼镜,正式接入了蚂蚁集团的GPASS平台。这可不是一次简单的功能叠加,它意味着,诸如共享单车骑行、停车缴费这一系列高频的“AI办事”功能,开始从手机屏幕转移到了你的眼前。 简单说,借助GP

时间:2026-04-06 21:13
Workbuddy注册额外积分

Workbuddy注册额外积分

角色定位与核心任务目标 明确了基本定位后,我们直接切入核心:作为一名专业的文章优化师,我的核心职责在于,将那些带有明显AI生成特征的文本,深度重塑为拥有个人特色与行业洞见的优质内容。 换句话说,这项任务的关键在于实施一次“精准的换血手术”。你必须严格保证原文所有的事实依据、核心观点、逻辑框架,以及每

时间:2026-04-06 20:24
我把 Anthropic 的 Harness 工程思想做成了一个 Skill

我把 Anthropic 的 Harness 工程思想做成了一个 Skill

用AI写代码,难在哪儿? 用AI生成代码本身并不难,真正的挑战在于让它稳定地交付一个真正可用的东西。这篇文章,我们就来聊聊Anthropic工程团队是如何破解这个难题的,以及我如何将这套方法论落地成了一个可以复用的实战工具。 用 AI 写代码有多难?不是写不出来难,是让它稳定交付可用的东西很难。这篇

时间:2026-04-06 16:53
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜
热门教程
更多
  • 游戏攻略
  • 安卓教程
  • 苹果教程
  • 电脑教程