Closed 847001315 closed 2 years ago
你好,能提供一下具体的环境信息吗
好的,以下是我的环境信息: cuda:10.2 pytorch:1.10 mmcv-full:1.4.4 mmsegmentation:0.20.2 mmdet:2.22.0 数据集说明:为自定义的医学数据集,其中包含一类目标类,其余被背景,图像尺寸为【112112,三通道】,mask图像为【112112,单通道,同时处理过,将背景的像素点的像素值设为0,目标类的像素点的像素值设为1】 其中数据集的自定义类文件为:
from mmseg.datasets.builder import DATASETS
from mmseg.datasets.custom import CustomDataset
@DATASETS.register_module()
class EchonetDataset(CustomDataset):
## 数据集标注的各类名称,即 0, 1, 2, 3... 各个类别的对应名称
CLASSES = (
'background','heart',
)
# # 各类类别的 BGR 三通道值,用于可视化预测结果
PALETTE = [ [0, 0, 0],[255, 255, 255]]
def __init__(self, **kwargs):
super(EchonetDataset, self).__init__(
img_suffix='.jpg',
seg_map_suffix='.png',
reduce_zero_label=False, ## 此时 label 里的 0(上面 CLASSES 里第一个 “label_a”)在计算损失函数和指标时不会被忽略。
**kwargs
)
最终生成的配置文件的config为如下:
num_things_classes = 2
num_stuff_classes = 0
num_classes = 2
norm_cfg = dict(type='SyncBN', requires_grad=True)
model = dict(
type='EncoderDecoderMask2Former',
pretrained=None,
backbone=dict(
type='BEiTAdapter',
patch_size=16,
embed_dim=1024,
depth=24,
num_heads=16,
mlp_ratio=4,
qkv_bias=True,
use_abs_pos_emb=False,
use_rel_pos_bias=True,
img_size=224,
init_values=1e-06,
drop_path_rate=0.3,
conv_inplane=64,
n_points=4,
deform_num_heads=16,
cffn_ratio=0.25,
deform_ratio=0.5,
interaction_indexes=[[0, 5], [6, 11], [12, 17], [18, 23]]),
decode_head=dict(
type='Mask2FormerHead',
in_channels=[1024, 1024, 1024, 1024],
feat_channels=1024,
out_channels=1024,
in_index=[0, 1, 2, 3],
num_things_classes=2,
num_stuff_classes=0,
num_queries=100,
num_transformer_feat_level=3,
pixel_decoder=dict(
type='MSDeformAttnPixelDecoder',
num_outs=3,
norm_cfg=dict(type='GN', num_groups=32),
act_cfg=dict(type='ReLU'),
encoder=dict(
type='DetrTransformerEncoder',
num_layers=6,
transformerlayers=dict(
type='BaseTransformerLayer',
attn_cfgs=dict(
type='MultiScaleDeformableAttention',
embed_dims=1024,
num_heads=32,
num_levels=3,
num_points=4,
im2col_step=64,
dropout=0.0,
batch_first=False,
norm_cfg=None,
init_cfg=None),
ffn_cfgs=dict(
type='FFN',
embed_dims=1024,
feedforward_channels=4096,
num_fcs=2,
ffn_drop=0.0,
act_cfg=dict(type='ReLU', inplace=True)),
operation_order=('self_attn', 'norm', 'ffn', 'norm')),
init_cfg=None),
positional_encoding=dict(
type='SinePositionalEncoding', num_feats=512, normalize=True),
init_cfg=None),
enforce_decoder_input_project=False,
positional_encoding=dict(
type='SinePositionalEncoding', num_feats=512, normalize=True),
transformer_decoder=dict(
type='DetrTransformerDecoder',
return_intermediate=True,
num_layers=9,
transformerlayers=dict(
type='DetrTransformerDecoderLayer',
attn_cfgs=dict(
type='MultiheadAttention',
embed_dims=1024,
num_heads=32,
attn_drop=0.0,
proj_drop=0.0,
dropout_layer=None,
batch_first=False),
ffn_cfgs=dict(
embed_dims=1024,
feedforward_channels=4096,
num_fcs=2,
act_cfg=dict(type='ReLU', inplace=True),
ffn_drop=0.0,
dropout_layer=None,
add_identity=True),
feedforward_channels=4096,
operation_order=('cross_attn', 'norm', 'self_attn', 'norm',
'ffn', 'norm')),
init_cfg=None),
loss_cls=dict(
type='CrossEntropyLoss',
use_sigmoid=False,
loss_weight=2.0,
reduction='mean',
class_weight=[1.0, 1.0, 0.1]),
loss_mask=dict(
type='CrossEntropyLoss',
use_sigmoid=True,
reduction='mean',
loss_weight=5.0),
loss_dice=dict(
type='DiceLoss',
use_sigmoid=True,
activate=True,
reduction='mean',
naive_dice=True,
eps=1.0,
loss_weight=5.0)),
train_cfg=dict(
num_points=12544,
oversample_ratio=3.0,
importance_sample_ratio=0.75,
assigner=dict(
type='MaskHungarianAssigner',
cls_cost=dict(type='ClassificationCost', weight=2.0),
mask_cost=dict(
type='CrossEntropyLossCost', weight=5.0, use_sigmoid=True),
dice_cost=dict(
type='DiceCost', weight=5.0, pred_act=True, eps=1.0)),
sampler=dict(type='MaskPseudoSampler')),
test_cfg=dict(
panoptic_on=True,
semantic_on=False,
instance_on=True,
max_per_image=100,
iou_thr=0.8,
filter_low_score=True,
mode='slide',
crop_size=(224, 224),
stride=(426, 426)),
init_cfg=None)
find_unused_parameters = True
dataset_type = 'EchonetDataset'
data_root = '/data/cgh/project/ViT-Adapter-main/segmentation/data/echonet_dataset'
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
crop_size = (224, 224)
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', reduce_zero_label=True),
dict(type='RandomFlip', prob=0.5),
dict(type='PhotoMetricDistortion'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size=(224, 224), pad_val=0, seg_pad_val=255),
dict(type='ToMask'),
dict(type='DefaultFormatBundle'),
dict(
type='Collect',
keys=['img', 'gt_semantic_seg', 'gt_masks', 'gt_labels'])
]
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(224, 224),
flip=True,
transforms=[
dict(
type='SETR_Resize',
keep_ratio=True,
crop_size=(224, 224),
setr_multi_scale=True),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
])
]
data = dict(
samples_per_gpu=1,
workers_per_gpu=4,
train=dict(
type='EchonetDataset',
data_root=
'/data/cgh/project/ViT-Adapter-main/segmentation/data/echonet_dataset',
img_dir='images/train',
ann_dir='ann/train',
pipeline=[
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', reduce_zero_label=True),
dict(type='RandomFlip', prob=0.5),
dict(type='PhotoMetricDistortion'),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='Pad', size=(224, 224), pad_val=0, seg_pad_val=255),
dict(type='ToMask'),
dict(type='DefaultFormatBundle'),
dict(
type='Collect',
keys=['img', 'gt_semantic_seg', 'gt_masks', 'gt_labels'])
]),
val=dict(
type='EchonetDataset',
data_root=
'/data/cgh/project/ViT-Adapter-main/segmentation/data/echonet_dataset',
img_dir='images/val',
ann_dir='ann/val',
pipeline=[
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(224, 224),
flip=True,
transforms=[
dict(
type='SETR_Resize',
keep_ratio=True,
crop_size=(224, 224),
setr_multi_scale=True),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
])
]),
test=dict(
type='EchonetDataset',
data_root=
'/data/cgh/project/ViT-Adapter-main/segmentation/data/echonet_dataset',
img_dir='images/test',
ann_dir='ann/test',
pipeline=[
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(224, 224),
flip=True,
transforms=[
dict(
type='SETR_Resize',
keep_ratio=True,
crop_size=(224, 224),
setr_multi_scale=True),
dict(
type='Normalize',
mean=[123.675, 116.28, 103.53],
std=[58.395, 57.12, 57.375],
to_rgb=True),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img'])
])
]))
log_config = dict(
interval=50, hooks=[dict(type='TextLoggerHook', by_epoch=False)])
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = None
resume_from = None
workflow = [('train', 1)]
cudnn_benchmark = True
optimizer = dict(
type='AdamW',
lr=2e-05,
betas=(0.9, 0.999),
weight_decay=0.05,
constructor='LayerDecayOptimizerConstructor',
paramwise_cfg=dict(num_layers=24, layer_decay_rate=0.9))
optimizer_config = dict()
lr_config = dict(
policy='poly',
warmup='linear',
warmup_iters=1500,
warmup_ratio=1e-06,
power=1.0,
min_lr=0.0,
by_epoch=False)
runner = dict(type='IterBasedRunner', max_iters=160000)
checkpoint_config = dict(by_epoch=False, interval=1000, max_keep_ckpts=1)
evaluation = dict(
interval=1600, metric='mIoU', pre_eval=True, save_best='mIoU')
t_size = 224
work_dir = './work_dirs/mask2former_beit_adapter_echonet'
gpu_ids = range(0, 1)
auto_resume = False
如果有需要,我可以把dataset和module的config继续贴上来,其中module就直接引用的本仓库的mask2former_beit.py。
在我没有修改除了config以外的情况下,代码无法跑通,会在我准备进行验证时出错,会在mmseg_custom/models/segmentors/EncoderDecoderMask2Former.py的第192行左右,即
assert (count_mat == 0).sum() == 0
处跳出异常。
具体代码如下:【除了注释了一句,其它并无修改】
# Copyright (c) OpenMMLab. All rights reserved.
import torch
import torch.nn as nn
import torch.nn.functional as F
from mmseg.core import add_prefix
from mmseg.models import builder
from mmseg.models.builder import SEGMENTORS
from mmseg.models.segmentors.base import BaseSegmentor
from mmseg.ops import resize
@SEGMENTORS.register_module()
class EncoderDecoderMask2Former(BaseSegmentor):
"""Encoder Decoder segmentors.
EncoderDecoder typically consists of backbone, decode_head, auxiliary_head.
Note that auxiliary_head is only used for deep supervision during training,
which could be dumped during inference.
"""
def __init__(self,
backbone,
decode_head,
neck=None,
auxiliary_head=None,
train_cfg=None,
test_cfg=None,
pretrained=None,
init_cfg=None):
super(EncoderDecoderMask2Former, self).__init__(init_cfg)
if pretrained is not None:
assert backbone.get('pretrained') is None, \
'both backbone and segmentor set pretrained weight'
backbone.pretrained = pretrained
self.backbone = builder.build_backbone(backbone)
if neck is not None:
self.neck = builder.build_neck(neck)
decode_head.update(train_cfg=train_cfg)
decode_head.update(test_cfg=test_cfg)
self._init_decode_head(decode_head)
self._init_auxiliary_head(auxiliary_head)
self.train_cfg = train_cfg
self.test_cfg = test_cfg
assert self.with_decode_head
def _init_decode_head(self, decode_head):
"""Initialize ``decode_head``"""
self.decode_head = builder.build_head(decode_head)
self.align_corners = self.decode_head.align_corners
self.num_classes = self.decode_head.num_classes
def _init_auxiliary_head(self, auxiliary_head):
"""Initialize ``auxiliary_head``"""
if auxiliary_head is not None:
if isinstance(auxiliary_head, list):
self.auxiliary_head = nn.ModuleList()
for head_cfg in auxiliary_head:
self.auxiliary_head.append(builder.build_head(head_cfg))
else:
self.auxiliary_head = builder.build_head(auxiliary_head)
def extract_feat(self, img):
"""Extract features from images."""
x = self.backbone(img)
if self.with_neck:
x = self.neck(x)
return x
def encode_decode(self, img, img_metas):
"""Encode images with backbone and decode into a semantic segmentation
map of the same size as input."""
x = self.extract_feat(img)
out = self._decode_head_forward_test(x, img_metas)
out = resize(
input=out,
size=img.shape[2:],
mode='bilinear',
align_corners=self.align_corners)
return out
def _decode_head_forward_train(self, x, img_metas, gt_semantic_seg,
**kwargs):
"""Run forward function and calculate loss for decode head in
training."""
losses = dict()
loss_decode = self.decode_head.forward_train(x, img_metas,
gt_semantic_seg, **kwargs)
losses.update(add_prefix(loss_decode, 'decode'))
return losses
def _decode_head_forward_test(self, x, img_metas):
"""Run forward function and calculate loss for decode head in
inference."""
seg_logits = self.decode_head.forward_test(x, img_metas, self.test_cfg)
return seg_logits
def _auxiliary_head_forward_train(self, x, img_metas, gt_semantic_seg):
"""Run forward function and calculate loss for auxiliary head in
training."""
losses = dict()
if isinstance(self.auxiliary_head, nn.ModuleList):
for idx, aux_head in enumerate(self.auxiliary_head):
loss_aux = aux_head.forward_train(x, img_metas,
gt_semantic_seg,
self.train_cfg)
losses.update(add_prefix(loss_aux, f'aux_{idx}'))
else:
loss_aux = self.auxiliary_head.forward_train(
x, img_metas, gt_semantic_seg, self.train_cfg)
losses.update(add_prefix(loss_aux, 'aux'))
return losses
def forward_dummy(self, img):
"""Dummy forward function."""
seg_logit = self.encode_decode(img, None)
return seg_logit
def forward_train(self, img, img_metas, gt_semantic_seg, **kwargs):
"""Forward function for training.
Args:
img (Tensor): Input images.
img_metas (list[dict]): List of image info dict where each dict
has: 'img_shape', 'scale_factor', 'flip', and may also contain
'filename', 'ori_shape', 'pad_shape', and 'img_norm_cfg'.
For details on the values of these keys see
`mmseg/datasets/pipelines/formatting.py:Collect`.
gt_semantic_seg (Tensor): Semantic segmentation masks
used if the architecture supports semantic segmentation task.
Returns:
dict[str, Tensor]: a dictionary of loss components
"""
x = self.extract_feat(img)
losses = dict()
loss_decode = self._decode_head_forward_train(x, img_metas,
gt_semantic_seg,
**kwargs)
losses.update(loss_decode)
if self.with_auxiliary_head:
loss_aux = self._auxiliary_head_forward_train(
x, img_metas, gt_semantic_seg)
losses.update(loss_aux)
return losses
# TODO refactor
def slide_inference(self, img, img_meta, rescale):
"""Inference by sliding-window with overlap.
If h_crop > h_img or w_crop > w_img, the small patch will be used to
decode without padding.
"""
# print("img.shape",img.shape)
# print("img",img)
h_stride, w_stride = self.test_cfg.stride
h_crop, w_crop = self.test_cfg.crop_size
batch_size, _, h_img, w_img = img.size()
num_classes = self.num_classes
# print("num_class",num_classes)
h_grids = max(h_img - h_crop + h_stride - 1, 0) // h_stride + 1
w_grids = max(w_img - w_crop + w_stride - 1, 0) // w_stride + 1
preds = img.new_zeros((batch_size, num_classes, h_img, w_img))
# print("preds",preds)
count_mat = img.new_zeros((batch_size, 1, h_img, w_img))
# print("count_mat",count_mat)
for h_idx in range(h_grids):
for w_idx in range(w_grids):
y1 = h_idx * h_stride
x1 = w_idx * w_stride
y2 = min(y1 + h_crop, h_img)
x2 = min(x1 + w_crop, w_img)
y1 = max(y2 - h_crop, 0)
x1 = max(x2 - w_crop, 0)
crop_img = img[:, :, y1:y2, x1:x2]
crop_seg_logit = self.encode_decode(crop_img, img_meta)
preds += F.pad(crop_seg_logit,
(int(x1), int(preds.shape[3] - x2), int(y1),
int(preds.shape[2] - y2)))
count_mat[:, :, y1:y2, x1:x2] += 1
# print(count_mat[:, :, y1:y2, x1:x2])
# assert (count_mat == 0).sum() == 0
if torch.onnx.is_in_onnx_export():
# cast count_mat to constant while exporting to ONNX
count_mat = torch.from_numpy(
count_mat.cpu().detach().numpy()).to(device=img.device)
preds = preds / count_mat
# preds = preds
if rescale:
preds = resize(
preds,
size=img_meta[0]['ori_shape'][:2],
mode='bilinear',
align_corners=self.align_corners,
warning=False)
return preds
def whole_inference(self, img, img_meta, rescale):
"""Inference with full image."""
seg_logit = self.encode_decode(img, img_meta)
if rescale:
# support dynamic shape for onnx
if torch.onnx.is_in_onnx_export():
size = img.shape[2:]
else:
size = img_meta[0]['ori_shape'][:2]
seg_logit = resize(
seg_logit,
size=size,
mode='bilinear',
align_corners=self.align_corners,
warning=False)
return seg_logit
def inference(self, img, img_meta, rescale):
"""Inference with slide/whole style.
Args:
img (Tensor): The input image of shape (N, 3, H, W).
img_meta (dict): Image info dict where each dict has: 'img_shape',
'scale_factor', 'flip', and may also contain
'filename', 'ori_shape', 'pad_shape', and 'img_norm_cfg'.
For details on the values of these keys see
`mmseg/datasets/pipelines/formatting.py:Collect`.
rescale (bool): Whether rescale back to original shape.
Returns:
Tensor: The output segmentation map.
"""
assert self.test_cfg.mode in ['slide', 'whole']
ori_shape = img_meta[0]['ori_shape']
assert all(_['ori_shape'] == ori_shape for _ in img_meta)
if self.test_cfg.mode == 'slide':
seg_logit = self.slide_inference(img, img_meta, rescale)
else:
seg_logit = self.whole_inference(img, img_meta, rescale)
output = F.softmax(seg_logit, dim=1)
flip = img_meta[0]['flip']
if flip:
flip_direction = img_meta[0]['flip_direction']
assert flip_direction in ['horizontal', 'vertical']
if flip_direction == 'horizontal':
output = output.flip(dims=(3,))
elif flip_direction == 'vertical':
output = output.flip(dims=(2,))
return output
def simple_test(self, img, img_meta, rescale=True):
"""Simple test with single image."""
seg_logit = self.inference(img, img_meta, rescale)
seg_pred = seg_logit.argmax(dim=1)
if torch.onnx.is_in_onnx_export():
# our inference backend only support 4D output
seg_pred = seg_pred.unsqueeze(0)
return seg_pred
seg_pred = seg_pred.cpu().numpy()
# unravel batch dim
seg_pred = list(seg_pred)
return seg_pred
def aug_test(self, imgs, img_metas, rescale=True):
"""Test with augmentations.
Only rescale=True is supported.
"""
# aug_test rescale all imgs back to ori_shape for now
assert rescale
# to save memory, we get augmented seg logit inplace
seg_logit = self.inference(imgs[0], img_metas[0], rescale)
for i in range(1, len(imgs)):
cur_seg_logit = self.inference(imgs[i], img_metas[i], rescale)
seg_logit += cur_seg_logit
seg_logit /= len(imgs)
seg_pred = seg_logit.argmax(dim=1)
seg_pred = seg_pred.cpu().numpy()
# unravel batch dim
seg_pred = list(seg_pred)
return seg_pred
我将count_mat输出出来,可以看到里面并非都是0,对这句话不理解,于是试着直接将其注释,发现代码可以运行。
目前代码可以运行,但得出来的结果非常奇怪,只能得到
目前不清楚到底是我注释了这个代码的缘故,还是我config哪里的配置没有写好。
问题:跑出来只有一个类的结果,另外一个类始终是0 情况1?:可能是由于我注释了assert (count_mat == 0).sum() == 0这句话,不理解这句话的意义,想询问一下count_mat是什么意思,是否会影响最终结果 情况2?:会不会因为我的config文件哪里写错了? 情况3?:会不会是我数据集的图像尺寸过小?【已经确定数据集有被载入】
我目前自己可以想到的情况就是以上三种~ 非常谢谢您~,这两天一直打扰您了
@duanduanduanyuchen 看一看config
@duanduanduanyuchen 看一看config
您是叫他来看我的config吗?还是我去看他某个仓库的config?
我发现了一个可能的地方,如果背景类(0)也要参与计算的话,reduce_zero_label=True得改成False。 我看到你的Dataset类里设成False了,不过config里还是True
@duanduanduanyuchen 看一看config
您是叫他来看我的config吗?还是我去看他某个仓库的config?
是的,他会帮你看
还有一个地方,我看到你说图像是112x112的,你这里是直接pad到224x224吗,而不是resize到224x224. 可以把
test_cfg=dict(mode='slide', crop_size=(224, 224), stride=(426, 426))
改成
test_cfg=dict(mode='slide', crop_size=(224, 224), stride=(224, 224))
或者
test_cfg=dict(mode='whole')
试一试
现在训练和测试的pipeline应该没有对齐,训练时是112pad到224,测试时是112resize224,这可能会造成一些精度下降
assert (count_mat == 0).sum() == 0
这段代码的含义是保证count_mat
矩阵所有元素非0,count_mat
矩阵是在测试的slide过程中的计数矩阵,目的在于对原图像进行切割、滑窗后进行测试的过程中,整张图片被滑窗完全覆盖。
根据你的config,在你的model
变量中你设置的crop_size
为(224,224)
,在test_pipeline
变量中设置的img_scale
也为(224,224)
,建议你检查在该段报错代码中的img
的形状大小是否为(224,224)
。
现在训练和测试的pipeline应该没有对齐,训练时是112pad到224,测试时是112resize224,这可能会造成一些精度下降
非常感谢您替我解答~我去按照您的说法去更改一下,谢谢谢谢~~~
assert (count_mat == 0).sum() == 0
这段代码的含义是保证count_mat
矩阵所有元素非0,count_mat
矩阵是在测试的slide过程中的计数矩阵,目的在于对原图像进行切割、滑窗后进行测试的过程中,整张图片被滑窗完全覆盖。 根据你的config,在你的model
变量中你设置的crop_size
为(224,224)
,在test_pipeline
变量中设置的img_scale
也为(224,224)
,建议你检查在该段报错代码中的img
的形状大小是否为(224,224)
。
明白了~,也谢谢您替我解答~我再去补充一下相关知识,修改一下你们说的配置问题,再看看~,谢谢谢谢大家百忙之中抽空给我解答
assert (count_mat == 0).sum() == 0
这段代码的含义是保证count_mat
矩阵所有元素非0,count_mat
矩阵是在测试的slide过程中的计数矩阵,目的在于对原图像进行切割、滑窗后进行测试的过程中,整张图片被滑窗完全覆盖。 根据你的config,在你的model
变量中你设置的crop_size
为(224,224)
,在test_pipeline
变量中设置的img_scale
也为(224,224)
,建议你检查在该段报错代码中的img
的形状大小是否为(224,224)
。明白了~,也谢谢您替我解答~我再去补充一下相关知识,修改一下你们说的配置问题,再看看~,谢谢谢谢大家百忙之中抽空给我解答
我试了一下MMSeg自带的医学数据集CHASE_DB1,config如下,可以参考一下:
# Copyright (c) Shanghai AI Lab. All rights reserved.
_base_ = [
'../_base_/models/upernet_beit.py',
'../_base_/datasets/chase_db1.py',
'../_base_/default_runtime.py',
'../_base_/schedules/schedule_40k.py'
]
img_scale = (960, 999)
crop_size = (128, 128)
# pretrained = 'https://conversationhub.blob.core.windows.net/beit-share-public/beit/beit_large_patch16_224_pt22k_ft22k.pth'
pretrained = 'pretrained/beit_large_patch16_224_pt22k_ft22k.pth'
model = dict(
pretrained=pretrained,
backbone=dict(
type='BEiTAdapter',
img_size=128,
patch_size=16,
embed_dim=1024,
depth=24,
num_heads=16,
mlp_ratio=4,
qkv_bias=True,
use_abs_pos_emb=False,
use_rel_pos_bias=True,
init_values=1e-6,
drop_path_rate=0.3,
conv_inplane=64,
n_points=4,
deform_num_heads=16,
cffn_ratio=0.25,
deform_ratio=0.5,
interaction_indexes=[[0, 5], [6, 11], [12, 17], [18, 23]],
),
decode_head=dict(
in_channels=[1024, 1024, 1024, 1024],
num_classes=2,
channels=1024,
),
auxiliary_head=dict(
in_channels=1024,
num_classes=2
),
test_cfg = dict(mode='slide', crop_size=crop_size, stride=(85, 85))
)
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations'),
dict(type='Resize', img_scale=img_scale, ratio_range=(0.5, 2.0)),
dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75),
dict(type='RandomFlip', prob=0.5),
dict(type='PhotoMetricDistortion'),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img', 'gt_semantic_seg'])
]
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=img_scale,
# img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75],
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='ResizeToMultiple', size_divisor=32),
dict(type='RandomFlip'),
dict(type='Normalize', **img_norm_cfg),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img']),
])
]
optimizer = dict(_delete_=True, type='AdamW', lr=2e-5, betas=(0.9, 0.999), weight_decay=0.05,
constructor='LayerDecayOptimizerConstructor',
paramwise_cfg=dict(num_layers=24, layer_decay_rate=0.90))
lr_config = dict(_delete_=True, policy='poly',
warmup='linear',
warmup_iters=1500,
warmup_ratio=1e-6,
power=1.0, min_lr=0.0, by_epoch=False)
data=dict(train=dict(pipeline=train_pipeline),
val=dict(pipeline=test_pipeline),
test=dict(pipeline=test_pipeline))
runner = dict(type='IterBasedRunner')
checkpoint_config = dict(by_epoch=False, interval=1000, max_keep_ckpts=1)
evaluation = dict(interval=4000, metric='mDice', save_best='mDice')
assert (count_mat == 0).sum() == 0
这段代码的含义是保证count_mat
矩阵所有元素非0,count_mat
矩阵是在测试的slide过程中的计数矩阵,目的在于对原图像进行切割、滑窗后进行测试的过程中,整张图片被滑窗完全覆盖。 根据你的config,在你的model
变量中你设置的crop_size
为(224,224)
,在test_pipeline
变量中设置的img_scale
也为(224,224)
,建议你检查在该段报错代码中的img
的形状大小是否为(224,224)
。明白了~,也谢谢您替我解答~我再去补充一下相关知识,修改一下你们说的配置问题,再看看~,谢谢谢谢大家百忙之中抽空给我解答
我试了一下MMSeg自带的医学数据集CHASE_DB1,config如下,可以参考一下:
# Copyright (c) Shanghai AI Lab. All rights reserved. _base_ = [ '../_base_/models/upernet_beit.py', '../_base_/datasets/chase_db1.py', '../_base_/default_runtime.py', '../_base_/schedules/schedule_40k.py' ] img_scale = (960, 999) crop_size = (128, 128) # pretrained = 'https://conversationhub.blob.core.windows.net/beit-share-public/beit/beit_large_patch16_224_pt22k_ft22k.pth' pretrained = 'pretrained/beit_large_patch16_224_pt22k_ft22k.pth' model = dict( pretrained=pretrained, backbone=dict( type='BEiTAdapter', img_size=128, patch_size=16, embed_dim=1024, depth=24, num_heads=16, mlp_ratio=4, qkv_bias=True, use_abs_pos_emb=False, use_rel_pos_bias=True, init_values=1e-6, drop_path_rate=0.3, conv_inplane=64, n_points=4, deform_num_heads=16, cffn_ratio=0.25, deform_ratio=0.5, interaction_indexes=[[0, 5], [6, 11], [12, 17], [18, 23]], ), decode_head=dict( in_channels=[1024, 1024, 1024, 1024], num_classes=2, channels=1024, ), auxiliary_head=dict( in_channels=1024, num_classes=2 ), test_cfg = dict(mode='slide', crop_size=crop_size, stride=(85, 85)) ) img_norm_cfg = dict( mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True) train_pipeline = [ dict(type='LoadImageFromFile'), dict(type='LoadAnnotations'), dict(type='Resize', img_scale=img_scale, ratio_range=(0.5, 2.0)), dict(type='RandomCrop', crop_size=crop_size, cat_max_ratio=0.75), dict(type='RandomFlip', prob=0.5), dict(type='PhotoMetricDistortion'), dict(type='Normalize', **img_norm_cfg), dict(type='Pad', size=crop_size, pad_val=0, seg_pad_val=255), dict(type='DefaultFormatBundle'), dict(type='Collect', keys=['img', 'gt_semantic_seg']) ] test_pipeline = [ dict(type='LoadImageFromFile'), dict( type='MultiScaleFlipAug', img_scale=img_scale, # img_ratios=[0.5, 0.75, 1.0, 1.25, 1.5, 1.75], flip=False, transforms=[ dict(type='Resize', keep_ratio=True), dict(type='ResizeToMultiple', size_divisor=32), dict(type='RandomFlip'), dict(type='Normalize', **img_norm_cfg), dict(type='ImageToTensor', keys=['img']), dict(type='Collect', keys=['img']), ]) ] optimizer = dict(_delete_=True, type='AdamW', lr=2e-5, betas=(0.9, 0.999), weight_decay=0.05, constructor='LayerDecayOptimizerConstructor', paramwise_cfg=dict(num_layers=24, layer_decay_rate=0.90)) lr_config = dict(_delete_=True, policy='poly', warmup='linear', warmup_iters=1500, warmup_ratio=1e-6, power=1.0, min_lr=0.0, by_epoch=False) data=dict(train=dict(pipeline=train_pipeline), val=dict(pipeline=test_pipeline), test=dict(pipeline=test_pipeline)) runner = dict(type='IterBasedRunner') checkpoint_config = dict(by_epoch=False, interval=1000, max_keep_ckpts=1) evaluation = dict(interval=4000, metric='mDice', save_best='mDice')
非常感谢您还抽空写了一下config!!我昨天吸收你们的建议后,去更改了一下,代码已经可以成功运行,并且iou并不会为0了。不过我遇到了问题,目前跑出来的结果,iou仅为60(deeplabv3跑该数据集可以iou=90),loss一直无法下降,目前仅仅调整学习率暂时无法解决,我会去再排查一下是否是我的config或者数据增强出现问题,也会参考您现在发的config,再一次感谢您回复我,十分感谢!!
昨天的config里好像没有加载预训练权重pretrained=None
,不知道你后来有没有加上?
在CHASE_DB1上的结果看着还可以(unet+deeplabv3 40k训完是89.5左右的mDice, link)
目前16k/40k(还没训完)的log是这样:
2022-06-20 16:02:21,580 - mmseg - INFO -
+------------+-------+-------+
| Class | Dice | Acc |
+------------+-------+-------+
| background | 98.65 | 98.55 |
| vessel | 80.19 | 81.37 |
+------------+-------+-------+
2022-06-20 16:02:21,580 - mmseg - INFO - Summary:
2022-06-20 16:02:21,580 - mmseg - INFO -
+-------+-------+-------+
| aAcc | mDice | mAcc |
+-------+-------+-------+
| 97.47 | 89.42 | 89.96 |
+-------+-------+-------+
昨天的config里好像没有加载预训练权重
pretrained=None
,不知道你后来有没有加上?
后面依旧没有加上,有一个疑惑,例如您刚刚给我发的config中的model的backbone的image_size为128,但预训练权重是224的,是否可以载入?我一开始感觉我的图像尺寸和model的backbone尺寸不同就没有加,后续可以去加一下。
昨天的config里好像没有加载预训练权重
pretrained=None
,不知道你后来有没有加上?后面依旧没有加上,有一个疑惑,例如您刚刚给我发的config中的model的backbone的image_size为128,但预训练权重是224的,是否可以载入?我一开始感觉我的图像尺寸和model的backbone尺寸不同就没有加,后续可以去加一下。
可以载入的,finetune的分辨率可以和预训练不一致 这个模型比较大,医疗数据一般都比较少,如果不用预训练效果可能会比较差
昨天的config里好像没有加载预训练权重
pretrained=None
,不知道你后来有没有加上?后面依旧没有加上,有一个疑惑,例如您刚刚给我发的config中的model的backbone的image_size为128,但预训练权重是224的,是否可以载入?我一开始感觉我的图像尺寸和model的backbone尺寸不同就没有加,后续可以去加一下。
可以载入的,finetune的分辨率可以和预训练不一致 这个模型比较大,医疗数据一般都比较少,如果不用预训练效果可能会比较差
好的!我后续去试验一下,刚刚开始接触mmseg框架,很多基础不清晰,非常打扰!!再一次感谢您!!想问一个问题,我的图片大小为112*112,test的mode选择whole和slide是否有影响?哪个模式更适合小图?whole吗?
昨天的config里好像没有加载预训练权重
pretrained=None
,不知道你后来有没有加上?后面依旧没有加上,有一个疑惑,例如您刚刚给我发的config中的model的backbone的image_size为128,但预训练权重是224的,是否可以载入?我一开始感觉我的图像尺寸和model的backbone尺寸不同就没有加,后续可以去加一下。
可以载入的,finetune的分辨率可以和预训练不一致 这个模型比较大,医疗数据一般都比较少,如果不用预训练效果可能会比较差
好的!我后续去试验一下,刚刚开始接触mmseg框架,很多基础不清晰,非常打扰!!再一次感谢您!!想问一个问题,我的图片大小为112*112,test的mode选择whole和slide是否有影响?哪个模式更适合小图?whole吗?
如果大小全部都是固定的112x112,用whole就好了
昨天的config里好像没有加载预训练权重
pretrained=None
,不知道你后来有没有加上?后面依旧没有加上,有一个疑惑,例如您刚刚给我发的config中的model的backbone的image_size为128,但预训练权重是224的,是否可以载入?我一开始感觉我的图像尺寸和model的backbone尺寸不同就没有加,后续可以去加一下。
可以载入的,finetune的分辨率可以和预训练不一致 这个模型比较大,医疗数据一般都比较少,如果不用预训练效果可能会比较差
好的!我后续去试验一下,刚刚开始接触mmseg框架,很多基础不清晰,非常打扰!!再一次感谢您!!想问一个问题,我的图片大小为112*112,test的mode选择whole和slide是否有影响?哪个模式更适合小图?whole吗?
如果大小全部都是固定的112x112,用whole就好了
好的!了解了!!!vitadaper好像接受不了图尺寸为112X112的,我之前单独抽取把vitadapter抽取出来,放入之前自己的模型中,会出现有一个层的特征图为3x3,另外一个本来应该和它同尺度的特征图为4x4(说的很不清晰,后面我把它全部向上取整后,就可以跑了)。是否我可以认为,最低尺寸应该应该为128x128?
昨天的config里好像没有加载预训练权重
pretrained=None
,不知道你后来有没有加上?后面依旧没有加上,有一个疑惑,例如您刚刚给我发的config中的model的backbone的image_size为128,但预训练权重是224的,是否可以载入?我一开始感觉我的图像尺寸和model的backbone尺寸不同就没有加,后续可以去加一下。
可以载入的,finetune的分辨率可以和预训练不一致 这个模型比较大,医疗数据一般都比较少,如果不用预训练效果可能会比较差
好的!我后续去试验一下,刚刚开始接触mmseg框架,很多基础不清晰,非常打扰!!再一次感谢您!!想问一个问题,我的图片大小为112*112,test的mode选择whole和slide是否有影响?哪个模式更适合小图?whole吗?
如果大小全部都是固定的112x112,用whole就好了
好的!了解了!!!vitadaper好像接受不了图尺寸为112X112的,我之前单独抽取把vitadapter抽取出来,放入之前自己的模型中,会出现有一个层的特征图为3x3,另外一个本来应该和它同尺度的特征图为4x4(说的很不清晰,后面我把它全部向上取整后,就可以跑了)。是否我可以认为,最低尺寸应该应该为128x128?
确实。要求输入图像的分辨率能被32整除(因为最小的特征图是stride 32的),倒不一定是128x128
昨天的config里好像没有加载预训练权重
pretrained=None
,不知道你后来有没有加上?后面依旧没有加上,有一个疑惑,例如您刚刚给我发的config中的model的backbone的image_size为128,但预训练权重是224的,是否可以载入?我一开始感觉我的图像尺寸和model的backbone尺寸不同就没有加,后续可以去加一下。
可以载入的,finetune的分辨率可以和预训练不一致 这个模型比较大,医疗数据一般都比较少,如果不用预训练效果可能会比较差
好的!我后续去试验一下,刚刚开始接触mmseg框架,很多基础不清晰,非常打扰!!再一次感谢您!!想问一个问题,我的图片大小为112*112,test的mode选择whole和slide是否有影响?哪个模式更适合小图?whole吗?
如果大小全部都是固定的112x112,用whole就好了
好的!了解了!!!vitadaper好像接受不了图尺寸为112X112的,我之前单独抽取把vitadapter抽取出来,放入之前自己的模型中,会出现有一个层的特征图为3x3,另外一个本来应该和它同尺度的特征图为4x4(说的很不清晰,后面我把它全部向上取整后,就可以跑了)。是否我可以认为,最低尺寸应该应该为128x128?
确实。要求输入图像的分辨率能被32整除(因为最小的特征图是stride 32的),倒不一定是128x128
好的!!!非常感谢╰(´︶`)╯!!如果我对mmseg和vit-adapter更熟悉了之后,是否可以写一个博客用来介绍如何在本项目中自定义数据集?
昨天的config里好像没有加载预训练权重
pretrained=None
,不知道你后来有没有加上?后面依旧没有加上,有一个疑惑,例如您刚刚给我发的config中的model的backbone的image_size为128,但预训练权重是224的,是否可以载入?我一开始感觉我的图像尺寸和model的backbone尺寸不同就没有加,后续可以去加一下。
可以载入的,finetune的分辨率可以和预训练不一致 这个模型比较大,医疗数据一般都比较少,如果不用预训练效果可能会比较差
好的!我后续去试验一下,刚刚开始接触mmseg框架,很多基础不清晰,非常打扰!!再一次感谢您!!想问一个问题,我的图片大小为112*112,test的mode选择whole和slide是否有影响?哪个模式更适合小图?whole吗?
如果大小全部都是固定的112x112,用whole就好了
好的!了解了!!!vitadaper好像接受不了图尺寸为112X112的,我之前单独抽取把vitadapter抽取出来,放入之前自己的模型中,会出现有一个层的特征图为3x3,另外一个本来应该和它同尺度的特征图为4x4(说的很不清晰,后面我把它全部向上取整后,就可以跑了)。是否我可以认为,最低尺寸应该应该为128x128?
确实。要求输入图像的分辨率能被32整除(因为最小的特征图是stride 32的),倒不一定是128x128
好的!!!非常感谢╰(´︶`)╯!!如果我对mmseg和vit-adapter更熟悉了之后,是否可以写一个博客用来介绍如何在本项目中自定义数据集?
当然可以😊
您好~ 我这两天去把您之前说的发的config进行修改一些路径,已经可以跑了,并且得到了比deeplabv3_resnet50更好的效果。但是我在跑另外一个3类别数据集【如果加上背景是4类,但我并不打算计算背景】的时候,验证集的对于这三个类还能达到姣好的效果,但测试集得出来的结果仅有0和2两个像素值,没有1像素值,也没有其它像素值,目前我打算去将背景也加为一类,但是我有点困惑,如果说背景不加入其中的话,那确实分割出来只会有三个可能的像素值【但城市景观好像就没有背景类?】。所以想问:
我接下来会将背景类加入~ 非常感谢您!!
您好~ 我这两天去把您之前说的发的config进行修改一些路径,已经可以跑了,并且得到了比deeplabv3_resnet50更好的效果。但是我在跑另外一个3类别数据集【如果加上背景是4类,但我并不打算计算背景】的时候,验证集的对于这三个类还能达到姣好的效果,但测试集得出来的结果仅有0和2两个像素值,没有1像素值,也没有其它像素值,目前我打算去将背景也加为一类,但是我有点困惑,如果说背景不加入其中的话,那确实分割出来只会有三个可能的像素值【但城市景观好像就没有背景类?】。所以想问:
- 如果我没将背景(像素值255)也算作一类,是否会影响分类结果?
- 测试集仅得出了0和2的像素值,并没有1的像素值,这可能存在什么原因? 以下是验证集得到的结果:
我接下来会将背景类加入~ 非常感谢您!!
您好~ 我这两天去把您之前说的发的config进行修改一些路径,已经可以跑了,并且得到了比deeplabv3_resnet50更好的效果。但是我在跑另外一个3类别数据集【如果加上背景是4类,但我并不打算计算背景】的时候,验证集的对于这三个类还能达到姣好的效果,但测试集得出来的结果仅有0和2两个像素值,没有1像素值,也没有其它像素值,目前我打算去将背景也加为一类,但是我有点困惑,如果说背景不加入其中的话,那确实分割出来只会有三个可能的像素值【但城市景观好像就没有背景类?】。所以想问:
- 如果我没将背景(像素值255)也算作一类,是否会影响分类结果?
- 测试集仅得出了0和2的像素值,并没有1的像素值,这可能存在什么原因? 以下是验证集得到的结果:
我接下来会将背景类加入~ 非常感谢您!!
- 背景不参与是可以的,不过通常像素值0是背景,而255是要忽略的像素
- 请问你的reduce_zero_label是设的什么
- 我有一个办法应该可以解决,就是重新映射一下标签,背景为0,其他的为1、2、3,reduce_zero_label=True
好的,谢谢您! 我之前设置的reduce_zero_label=false,然后0 1 2 为具体的三个目标类,我手动将mask的背景设为255。请问mmseg默认255是不计算的吗? 对于第三点,我马上去尝试
昨天的config里好像没有加载预训练权重
pretrained=None
,不知道你后来有没有加上?后面依旧没有加上,有一个疑惑,例如您刚刚给我发的config中的model的backbone的image_size为128,但预训练权重是224的,是否可以载入?我一开始感觉我的图像尺寸和model的backbone尺寸不同就没有加,后续可以去加一下。
可以载入的,finetune的分辨率可以和预训练不一致 这个模型比较大,医疗数据一般都比较少,如果不用预训练效果可能会比较差
好的!我后续去试验一下,刚刚开始接触mmseg框架,很多基础不清晰,非常打扰!!再一次感谢您!!想问一个问题,我的图片大小为112*112,test的mode选择whole和slide是否有影响?哪个模式更适合小图?whole吗?
如果大小全部都是固定的112x112,用whole就好了
好的!了解了!!!vitadaper好像接受不了图尺寸为112X112的,我之前单独抽取把vitadapter抽取出来,放入之前自己的模型中,会出现有一个层的特征图为3x3,另外一个本来应该和它同尺度的特征图为4x4(说的很不清晰,后面我把它全部向上取整后,就可以跑了)。是否我可以认为,最低尺寸应该应该为128x128?
确实。要求输入图像的分辨率能被32整除(因为最小的特征图是stride 32的),倒不一定是128x128
好的!!!非常感谢╰(´︶`)╯!!如果我对mmseg和vit-adapter更熟悉了之后,是否可以写一个博客用来介绍如何在本项目中自定义数据集?
哥们,博客写好了吗😁
ViT-Adapter-main/segmentation/mmseg_custom/models/segmentors/encoder_decoder_mask2former.py的195行,存在句子”assert (count_mat == 0).sum() == 0“,每次运行都会因为这个异常而跳出来。我将其注释掉,程序可以正常运行,但每次得出来的结果都是一样的,不知道和这里是否有关?想请问,count_mat代表什么意思?
下面是那一段代码: def slide_inference(self, img, img_meta, rescale): """Inference by sliding-window with overlap.
打扰了~~~