ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

paddlepaddle 7 面向语义分割的迁移学习

2022-01-26 21:02:55  阅读:282  来源: 互联网

标签:acc loss vd paddlepaddle 语义 backbones 迁移 data model


正常的迁移学习(迁移自建网络)使用方法如paddlepaddle 6 使用迁移学习对图像进行分类_a486259的博客-CSDN博客,但需要使用Deeplab、HRNet、UNET,FCN等知名的开源语义分割模型得要有相应的模型结构文件和模型权重文件,才可以进行迁移学习。幸好paddleseg中内置了这些模型,因此面向语义分割的迁移学习基于paddleseg实现(仅使用paddleseg实现模型加载与构建),训练部分使用paddle实现。

1、构建数据加载器

面向语义分割的数据加载器,直接参考paddlepaddle 1 数据加载器的使用_a486259的博客-CSDN博客

2、加载预训练模型

在这里首先要明白一个前置知识,不少语义分割模型是预设backbones的,用于提取特征。

 2.1 初始化模型的简单案例

#迁移学习的教程 https://aistudio.baidu.com/aistudio/projectdetail/1339458?channelType=0&channel=0

#支持的模型列表 https://github.com/PaddlePaddle/PaddleSeg/blob/release/2.4/README_CN.md
from paddleseg.models import backbones

#backbone的初始化方法 https://github.com/PaddlePaddle/PaddleSeg/blob/develop/docs/apis/backbones/backbones_cn.md
backbone=backbones.ResNet101_vd(pretrained = None)
backbone.feat_channels
from paddleseg import models
num_classes=4
deeplabv3=models.DeepLabV3P(
        num_classes, 
        backbones.ResNet101_vd(pretrained = None), 
    backbone_indices = (2, 3),
)
print(deeplabv3)

 加载的后模型可以看到是paddle.nn.Layer对象,跟我们自己搭建的模型是一模一样的。

2.2 初始化backbones

paddleseg中实现的backbones共有ResNet_vd、HRNet、MobileNetV3、XceptionDeeplab四个系列。

示例用法

class paddleseg.models.backbones.Resnet_vd(
            layers = 50, 
            output_stride = None, 
            multi_grid = (1, 1, 1), 
            lr_mult_list = (0.1, 0.1, 0.2, 0.2), 
            pretrained = None
)

参数

  • layers (int, optional): ResNet_vd的层数。 支持的层数有[18, 34, 50, 101, 152, 200]。 默认: 50
  • output_stride (int, optional): 与输入图像相比,输出特征的缩放步长,该参数将影响下采样倍数。该参数应为 8 或 16。 默认: 8
  • multi_grid (tuple|list, optional): stage 4的grid设置,用以扩大卷积的感受野。 默认: (1, 1, 1)
  • pretrained (str, optional): 预训练模型的路径。
paddleseg.models.backbones.ResNet18_vd(**args)
返回 ResNet_vd 类的一个对象,其层数为 18 。

paddleseg.models.backbones.ResNet34_vd(**args)
返回 ResNet_vd 类的一个对象,其层数为 34 。

paddleseg.models.backbones.ResNet50_vd(**args)
返回 ResNet_vd 类的一个对象,其层数为 50 。

paddleseg.models.backbones.ResNet101_vd(**args)
返回 ResNet_vd 类的一个对象,其层数为 101 。

paddleseg.models.backbones.ResNet152_vd(**args)
返回 ResNet_vd 类的一个对象,其层数为 152 。

padddelseg.models.backbones.ResNet200_vd(**args)
返回 ResNet_vd 类的一个对象,其层数为 200 。

更多用法可以参考

PaddleSeg/backbones_cn.md at develop · PaddlePaddle/PaddleSeg · GitHub

 2.3 初始化model

paddleseg中预训练的模型有DeepLabV3+、DeepLabV3、FCN、OCRNet、PSPNet、ANN、BiSeNetV2、DANet、FastSCNN、GCNet、GSCNN、HarDNet、UNet、U2Net、U2Net+、AttentionUNet、UNet++、DecoupledSegNet、ISANet、EMANet、DNLNet。有的模型的初始化需要先预设backbone,有的不需要。

DeepLabV3+

class paddleseg.models.DeepLabV3P(
        num_classes, 
        backbone, 
        backbone_indices = (0, 3), 
        aspp_ratios = (1, 6, 12, 18), 
        aspp_out_channels = 256, 
        align_corners = False, 
        pretrained = None
)

基于 PaddlePaddle 实现的 DeepLabV3Plus。

原文请参考: Liang-Chieh Chen, et, al. "Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation"

参数

  • num_classes (int): 相互独立的目标类别的数量。
  • backbone (paddle.nn.Layer): 骨干网络,目前支持 Resnet50_vd/Resnet101_vd/Xception65。
  • backbone_indices (tuple, optional): 元组中的两个值指示了骨干网络输出的索引。默认: (0, 3)
  • aspp_ratios (tuple, optional): ASSP module模块中使用的扩张率。 如果 output_stride = 16, aspp_ratios 应该设定为 (1, 6, 12, 18)。 如果 output_stride = 8, aspp_ratios 应该设定为 (1, 12, 24, 36)。 默认:(1, 6, 12, 18)
  • aspp_out_channels (int, optional): ASPP模块的输出通道数。默认:256
  • align_corners (bool, optional): F.interpolate 的一个参数。当特征大小为偶数时应设置为 False,例如 1024x512; 否则为 True, 例如 769x769。默认:False
  • pretrained (str, optional): 预训练模型的url或path。 默认:None

 更多模型的用法可以参考PaddleSeg/models_cn.md at develop · PaddlePaddle/PaddleSeg · GitHub

 3、训练模型

语义分割与分类的训练代码本质上是一样的,并无其他的。因此,直接复制前面章节的代码。

from tqdm import tqdm
def train_model(train_loader,model,loss_fn,optim):
    model.train()
    total_loss=0
    total_acc=0
    with tqdm(total=len(train_loader), desc=f'Epoch {epoch + 1}/{Epochs}', postfix=dict, mininterval=0.3) as pbar:
        for iteration, data in enumerate(train_loader()):
            x_data = data[0]            # 训练数据
            y_data = data[1]            # 训练数据标签
            predicts = model(x_data)    # 预测结果
            # 计算损失 等价于 prepare 中loss的设置
            loss = loss_fn(predicts, y_data)
            # 计算准确率 等价于 prepare 中metrics的设置
            acc = paddle.metric.accuracy(predicts, y_data)
            # 反向传播
            loss.backward()
            # 更新参数
            optim.step()
            # 梯度清零
            optim.clear_grad()
            #更新进度条
            total_loss+=loss.item()
            total_acc+=acc.item()
            pbar.set_postfix(**{'total_loss': "%.4f"%(total_loss / (iteration + 1)),'acc':"%.4f"%(total_acc/ (iteration + 1))})
            pbar.update(1)
            
def eval_model(test_loader,model,loss_fn):
    model.eval()
    total_loss=0
    total_acc=0
    for iteration, data in enumerate(test_loader()):
        x_data = data[0]            # 测试数据
        y_data = data[1]            # 测试数据标签
        predicts = model(x_data)    # 预测结果
        # 计算损失与精度
        loss = loss_fn(predicts, y_data)
        acc = paddle.metric.accuracy(predicts, y_data)
        total_loss+=loss.item()
        total_acc+=acc.item()
    loss,acc=total_loss / (iteration + 1), total_acc/ (iteration + 1)
    print("Test result, loss is: {:.4f}, acc is: {:.4f}".format(loss,acc))
    return loss,acc

#===================加载数据集==========================
train_line="ImagesSeg train.txt"
with open(train_line,"r") as f:
    train_lines = f.readlines()
    
test_line="ImagesSeg test.txt"
with open(test_line,"r") as f:
    test_lines = f.readlines()
    
# 测试定义的数据集
train_dataset = ImageSegDataset(train_lines,input_shape=(256,256))
test_dataset = ImageSegDataset(test_lines,input_shape=(256,256))
BATCH_SIZE=64
train_loader = paddle.io.DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)
test_loader = paddle.io.DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=True)
 
#===================构造模型和相关训练参数==========================
model = MyModel()
paddle.summary(model, (BATCH_SIZE, 3, 256, 256))
 
# 设置迭代次数
Epochs = 20
# 设置优化器
optim = paddle.optimizer.Adam(parameters=model.parameters())
# 设置损失函数  其中内置了softmax和onehot
loss_fn = paddle.nn.CrossEntropyLoss()    
 
#===================训练模型==========================
for epoch in range(Epochs):
    train_model(train_loader,model,loss_fn,optim)
    loss,acc=eval_model(test_loader,model,loss_fn)
    #paddle.save(model.state_dict(), "ep{}_acc{:4f}_loss{:.4f}model.pdparams".format(epoch,loss,acc), protocol=4)
    paddle.save(model, "minist/ep{}_acc{:4f}_loss{:.4f}model".format(epoch,loss,acc), input_spec=[paddle.rand((1, 3, 256, 256))])

标签:acc,loss,vd,paddlepaddle,语义,backbones,迁移,data,model
来源: https://blog.csdn.net/a486259/article/details/122708149

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有