系列文章目录(共五章33节已完结)
第一章deeplabv3+源码之慢慢解析 根目录(1)main.py–get_argparser函数
第一章deeplabv3+源码之慢慢解析 根目录(2)main.py–get_dataset函数
第一章deeplabv3+源码之慢慢解析 根目录(3)main.py–validate函数
第一章deeplabv3+源码之慢慢解析 根目录(4)main.py–main函数
第一章deeplabv3+源码之慢慢解析 根目录(5)predict.py–get_argparser函数和main函数
第二章deeplabv3+源码之慢慢解析 datasets文件夹(1)voc.py–voc_cmap函数和download_extract函数
第二章deeplabv3+源码之慢慢解析 datasets文件夹(2)voc.py–VOCSegmentation类
第二章deeplabv3+源码之慢慢解析 datasets文件夹(3)cityscapes.py–Cityscapes类
第二章deeplabv3+源码之慢慢解析 datasets文件夹(4)utils.py–6个小函数
第三章deeplabv3+源码之慢慢解析 metrics文件夹stream_metrics.py–StreamSegMetrics类和AverageMeter类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(a1)hrnetv2.py–4个函数和可执行代码
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(a2)hrnetv2.py–Bottleneck类和BasicBlock类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(a3)hrnetv2.py–StageModule类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(a4)hrnetv2.py–HRNet类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(b1)mobilenetv2.py–2个类和2个函数
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(b2)mobilenetv2.py–MobileNetV2类和mobilenet_v2函数
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(c1)resnet.py–2个基础函数,BasicBlock类和Bottleneck类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(c2)resnet.py–ResNet类和10个不同结构的调用函数
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(d1)xception.py–SeparableConv2d类和Block类
第四章deeplabv3+源码之慢慢解析 network文件夹(1)backbone文件夹(d2)xception.py–Xception类和xception函数
第四章deeplabv3+源码之慢慢解析 network文件夹(2)_deeplab.py–ASPP相关的4个类和1个函数
第四章deeplabv3+源码之慢慢解析 network文件夹(3)_deeplab.py–DeepLabV3类,DeepLabHeadV3Plus类和DeepLabHead类
第四章deeplabv3+源码之慢慢解析 network文件夹(4)modeling.py–5个私有函数(4个骨干网,1个模型载入)
第四章deeplabv3+源码之慢慢解析 network文件夹(5)modeling.py–12个调用函数
第四章deeplabv3+源码之慢慢解析 network文件夹(6)utils.py–_SimpleSegmentationModel类和IntermediateLayerGetter类
第五章deeplabv3+源码之慢慢解析 utils文件夹(1)ext_transforms.py.py–2个翻转类和ExtCompose类
第五章deeplabv3+源码之慢慢解析 utils文件夹(2)ext_transforms.py.py–2个裁剪类和2个缩放类
第五章deeplabv3+源码之慢慢解析 utils文件夹(3)ext_transforms.py.py–旋转类,填充类,张量转化类和标准化类
第五章deeplabv3+源码之慢慢解析 utils文件夹(4)ext_transforms.py.py–ExtResize类,ExtColorJitter类,Lambda类和Compose类
第五章deeplabv3+源码之慢慢解析 utils文件夹(5)loss.py–FocalLoss类
第五章deeplabv3+源码之慢慢解析 utils文件夹(6)scheduler.py–PolyLR类
第五章deeplabv3+源码之慢慢解析 utils文件夹(7)utils.py–去标准化,momentum设定,标准化层锁定和路径创建
第五章deeplabv3+源码之慢慢解析 utils文件夹(8)visualizer.py–Visualizer类(完结)
文章目录
前期准备和说明
提示:源码众多,此次选这个版本pytorch版
- 已经理解了前2章的代码。
- metrics度量,指标的意思,本文件夹的代码顾名思义。需要理解基本的度量指标理论知识。
总体目录
提示:metrics文件夹的总体结构如下,只有stream_metrics.py需要详解。
__init__.py
#一句话,简单明了。
from .stream_metrics import StreamSegMetrics, AverageMeter
stream_metrics.py导入
import numpy as np
from sklearn.metrics import confusion_matrix #导入了混淆矩阵confusion_matrix,各种度量必用。
_StreamMetrics类
提示:此内部类偏重设计,所有功能需要子类重写实现。详见下面StreamMetrics类。
class _StreamMetrics(object):
def __init__(self):
""" Overridden by subclasses """
raise NotImplementedError() #raise抛出异常,此内部类各个函数需要子类重写。
def update(self, gt, pred):
""" Overridden by subclasses """
raise NotImplementedError()
def get_results(self):
""" Overridden by subclasses """
raise NotImplementedError()
def to_str(self, metrics):
""" Overridden by subclasses """
raise NotImplementedError()
def reset(self):
""" Overridden by subclasses """
raise NotImplementedError()
StreamMetrics类
提示:这个类是_StreamMetrics类的子类,实现具体功能。
class StreamSegMetrics(_StreamMetrics):
"""
Stream Metrics for Semantic Segmentation Task
"""
def __init__(self, n_classes):
self.n_classes = n_classes #n_classes参数传入分类数目。
self.confusion_matrix = np.zeros((n_classes, n_classes)) #构造初始化混淆矩阵。
def update(self, label_trues, label_preds):
for lt, lp in zip(label_trues, label_preds): #zip()函数,将对应的标签和预测值打包成对(元组)。
self.confusion_matrix += self._fast_hist( lt.flatten(), lp.flatten() ) #详见下文_fast_hist函数。
@staticmethod #静态方法,和类方法不同,面向对象要学好!!!(注java中静态方法和类方法是同一个东西,python中不是一个东西,有区别,建议新手好好学习一些基本概念。后补小链接。)
def to_str(results): #将结果转为字符串(以便显示)。
string = "\n"
for k, v in results.items(): #从结果中取值。
if k!="Class IoU":
string += "%s: %f\n"%(k, v) #以字符串形式显示结果中非IoU的k,v值。
#string+='Class IoU:\n'
#for k, v in results['Class IoU'].items():
# string += "\tclass %d: %f\n"%(k, v)
return string
def _fast_hist(self, label_true, label_pred): #此函数详细例子后补链接。
mask = (label_true >= 0) & (label_true < self.n_classes) #即label_true在训练分类的数目之内,则mask=True。不在训练分类id里(未标注数据)的常被设置成-1或255,详见datasets第二章的讲解。
hist = np.bincount( #np.bincount是统计从0到array数组中最大数字出现的个数的函数,并同样以array数组输出显示。后补链接。
self.n_classes * label_true[mask].astype(int) + label_pred[mask], #n_classes*n_classes的矩阵,获得label_true[mask]行,label_pred[mask]列的完整矩阵值。对角线上的都是真值==预测值的数量,其他位置不为0的,就是不相等的。如第i项为ai*n+bi,若ai==bi,则结果是n的整数倍,即统计时在对角线上。
minlength=self.n_classes ** 2, #结果大小最小为n_classes*n_classes,不能小于原矩阵,不足的补零。结果是个长向量。
).reshape(self.n_classes, self.n_classes) #将结果转为矩阵n_classes*n_classes。
return hist #返回统计图。
def get_results(self): #后补详细公式对应代码链接。
"""Returns accuracy score evaluation result. #计算以下四项。
- overall accuracy
- mean accuracy
- mean IU
- fwavacc
"""
hist = self.confusion_matrix
acc = np.diag(hist).sum() / hist.sum() #ACC准确率(PA像素准确率)=对角线之和(正确的)/全部的和(总)
acc_cls = np.diag(hist) / hist.sum(axis=1) #MPA平均像素准确率(step1)计算每个类内被正确分类像素数的比例。
acc_cls = np.nanmean(acc_cls) #MPA(step2)再求所有类的平均。
iu = np.diag(hist) / (hist.sum(axis=1) + hist.sum(axis=0) - np.diag(hist)) #IoU真实集和预测集交并比,交集就是对角线,并集就是(行和 + 列和 - 对角线)。
mean_iu = np.nanmean(iu) #MIoU平均交并比。
freq = hist.sum(axis=1) / hist.sum() #FWIoU频权交并比,以每类出现频率为权重,与IoU进行加权计算。
fwavacc = (freq[freq > 0] * iu[freq > 0]).sum()
cls_iu = dict(zip(range(self.n_classes), iu)) #每个类对应的交并比。
return {
"Overall Acc": acc,
"Mean Acc": acc_cls,
"FreqW Acc": fwavacc,
"Mean IoU": mean_iu,
"Class IoU": cls_iu,
}
def reset(self): #重置混淆矩阵,即初始化为0.
self.confusion_matrix = np.zeros((self.n_classes, self.n_classes))
AverageMeter类
提示:计算均值。
class AverageMeter(object):
"""Computes average values"""
def __init__(self):
self.book = dict() #初始化字典
def reset_all(self):
self.book.clear() #清空。
def reset(self, id):
item = self.book.get(id, None) #按id重置对应的条目为(0,0)。
if item is not None:
item[0] = 0
item[1] = 0
def update(self, id, val):
record = self.book.get(id, None) #按id赋值条目为(val,1)
if record is None:
self.book[id] = [val, 1]
else:
record[0]+=val
record[1]+=1
def get_results(self, id):
record = self.book.get(id, None) #按id计算条目record[0] / record[1]
assert record is not None
return record[0] / record[1]
Tips
-
补充Python3中静态方法和类方法,实例方法,这个比较短小,方便快速理解,详细理解建议系统学习Python。
-
下一章进入network文件夹,主要是网络模型的代码。