01 FCN(2015)

目录

一、 理论知识

1.  网络架构

2. 损失计算

二、 代码实现

1. train.py

1.1 warmup(参数调优)

1.2 日志工具MetricLogger类

2. 网络搭建

3. 分割任务mask调色板及使用


一、 理论知识

1.  网络架构

各种结构中num_class===类别数+1

FCN-32S:

指的是下采样32倍,然后还原到原图尺寸。

  • 全卷积指的就是将两条绿色线中间的部分(分类网络中的全连接)换为卷积网络;
  • 之后通过上采样得到 ------------------(类别数+1)*H*W

相当于一个类别一个通道

FCN-16S:

 FCN-8S:

 毫无疑问,FCN-8S效果最好。

2. 损失计算

如下图:

假设2个类别+背景,左下角像素标签为1。

预测图中通道数==类别数+1,将每个通道的左下角元素做softmax回归;概率最大的通道数就是该像素的预测类别索引,相当于求每个像素的分类问题类别损失,然后求平均

二、 代码实现

1. train.py

该文件下一些笔记如下:

1.1 warmup(参数调优)

流程:

刚开始模型对数据完全不了解,此时需要使用小学习率

对数据了解了一段时间之后,可以使用大学习率

快接近目标时,使用小学习率进行探索

常见的warmup:

Constant Warmup:学习率从非常小的数值线性增加到预设值之后保持不变

Linner Warmup:学习率从非常小的数值线性增加到预设值之后,然后再线性减小

Cosine Warmup:学习率先从很小的数值线性增加到预设学习率,然后按照cos函数值衰减

代码示例:

####### 0
def create_lr_scheduler(optimizer,
                        num_step: int,
                        epochs: int,
                        warmup=True,
                        warmup_epochs=1,
                        warmup_factor=1e-3):
    assert num_step > 0 and epochs > 0
    if warmup is False:
        warmup_epochs = 0
    def f(x):
        """
        根据step数返回一个学习率倍率因子,
        注意在训练开始之前,pytorch会提前调用一次lr_scheduler.step()方法
        """
        if warmup is True and x <= (warmup_epochs * num_step):
            alpha = float(x) / (warmup_epochs * num_step)
            # warmup过程中lr倍率因子从warmup_factor -> 1
            return warmup_factor * (1 - alpha) + alpha
        else:
            # warmup后lr倍率因子从1 -> 0
            # 参考deeplab_v2: Learning rate policy
            return (1 - (x - warmup_epochs * num_step) / ((epochs - warmup_epochs) * num_step)) ** 0.9

    return torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=f)

####### 1
optimizer = torch.optim.SGD(
    params_to_optimize,
    lr=args.lr, momentum=args.momentum, weight_decay=args.weight_decay
    )
lr_scheduler = create_lr_scheduler(optimizer, len(train_loader), args.epochs, warmup=True)

####### 2
for image, target in metric_logger.log_every(data_loader, print_freq, header):
    ...
    loss = ...
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    lr_scheduler.step()

1.2 日志工具MetricLogger类

预先准备:

自行创建两个类—— class MetricLogger(object) 和 class SmoothedValue(object)

FCN项目下distributed_utils.py文件下的类和函数

使用示例:

MetricLoggerhttps://blog.csdn.net/weixin_44751294/article/details/124364645?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168437823116800217218797%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=168437823116800217218797&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~hot_rank-1-124364645-null-null.142%5Ev87%5Econtrol,239%5Ev2%5Einsert_chatgpt&utm_term=utils.MetricLogger&spm=1018.2226.3001.4187

2. 网络搭建

加载预训练权重时:

missing_keys, unexpected_keys = model.load_state_dict(weights_dict, strict=False)

strict=False

  • True 时,代表有什么要什么,每一个键都有。
  • False 时,有什么我要什么,没有的不勉强。

missing_keys, unexpected_keys  返回值:缺失的键,不期望的键。

3. 分割任务mask调色板及使用

常见的图片格式一般为rgb彩色三通道图或者单通道灰度图,但作为语义分割的label图(以voc数据集为例),其png图片实际格式是单通道的彩色图,这里叫伪彩图(或者也叫索引图)。由于将图片分割后是把像素点分类,不同类的分割结果用不同颜色表示(一个类别就是一个索引),需要定义一个类似于有序字典的东西来表示颜色

伪彩图:

先定义颜色结构,通过颜色的索引代表颜色。
举例:需要三种颜色,那就定义三种颜色[[255, 0, 0], [0, 255, 0],[0, 0, 255]]的结构储存起来,此时我们的伪彩色图片(只会出现上面三类颜色)当像素点的颜色为[255, 0, 0]时,只需要用0表示即可,这里的0就是颜色结构里的第一个颜色。同样地,1,2就分别表示另外两个颜色。

target都是单通道图;像素值是类别索引,通过调色板得到伪彩色图

网络训练时,不会用到;预测时会用到

  • 首先得到调色板(也就是索引图):

存为json文件

import json
import numpy as np
from PIL import Image

# 读取mask标签(训练集中的任意一张target)
target = Image.open("F:/data/voc_data/VOCdevkit/VOC2012/SegmentationClass/2007_000032.png")
# 获取调色板
palette = target.getpalette()
palette = np.reshape(palette, (-1, 3)).tolist()
# 转换成字典子形式
pd = dict((i, color) for i, color in enumerate(palette))
# 写入json文件
json_str = json.dumps(pd)
with open("palette.json", "w") as f:
    f.write(json_str)
  • 预测时使用
############ 01 读取调色板.json文件
palette_path = "./palette.json"
with open(palette_path, "rb") as f:
    pallette_dict = json.load(f)
    pallette = []
    for v in pallette_dict.values():
        pallette += v
############ 02 网络预测
img_path = "/2007_000549.jpg"      #一张图片
original_img = Image.open(img_path)
data_transform = ...
img = data_transform(original_img)  # C,H,W
img = torch.unsqueeze(img, dim=0)   # 扩维 B,C,H,W----1,C,H,W
model = ...
model.eval()
with torch.no_grad():
    output = model(img.to(device))                    # C=类别数+1  代表每个像素属于哪一类的概率
    prediction = output['out'].argmax(1).squeeze(0)   # 在C维度进行softmax取最大值,压缩为(H,W)
    prediction = prediction.to("cpu").numpy().astype(np.uint8)
    ############ 03 调用调色板,转化单通道(H,W)为伪彩色图(H,W)
    mask = Image.fromarray(prediction)
    mask.putpalette(pallette)
    mask.save("test_result.png")  # 预测结果保存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值