-
Notifications
You must be signed in to change notification settings - Fork 302
Conversation
…yuyu2172/chainercv into add-pspnet-infer
… add-pspnet-infer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial comment.
|
||
with self.init_scope(): | ||
self.input_size = input_size | ||
self.trunk = DilatedFCN(n_blocks=n_blocks) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use extractor
instead of trunk
.
This is consistent with links such as FasterRCNN
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I changed it.
mid_stride = chainer.config.mid_stride | ||
super(BottleneckConv, self).__init__() | ||
with self.init_scope(): | ||
self.cbr1 = ConvBNReLU( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to make the attribute name of ConvBN*
consistent across the library.
We have Conv2DBNActiv
, which will be used by ResNet implementations.
Since cbr
is specific to Conv->BN->ReLU
, I want to avoid the name.
How about conv1
, conv2
, ... ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I changed the attribute name to conv1
, conv2
, ...
return F.relu(h + x) | ||
|
||
|
||
class ResBlock(chainer.ChainList): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you merge ResBlock
and DilatedResBlock
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merged.
h = F.max_pooling_2d(h, 3, 2, 1) # 1/4 | ||
h = self.res2(h) | ||
h = self.res3(h) # 1/8 | ||
if chainer.config.train: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not always return h1
and h2
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
h1
is only for calculating auxiliary loss. That is completely useless during inference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
predict
should be called during inference and not __call__
. There is not much inconvenience returning it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, I want to avoid using a global variable to configure behavior if possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I changed this part to return both h1
and h2
always.
if initialW is None: | ||
chainer.config.initialW = chainer.initializers.HeNormal() | ||
else: | ||
chainer.config.initialW = initialW |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer not using global variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I replaced all such part to use a local variable given by the argument to the class.
|
||
# To calculate auxirally loss | ||
if chainer.config.train: | ||
self.cbr_aux = ConvBNReLU(None, 512, 3, 1, 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not like to change the configuration of a model using global variable.
It would not be much problem to instantiate these links. Why not always instantiate them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, let's instantiate them always.
constructor. ``H, W`` is the input image size. | ||
|
||
""" | ||
if chainer.config.train: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not add compute_aux
option instead of changing behavior using chainer.config.train
?
There can be a situation when a user wants to compute aux
with chainer.config.train=False
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. I'll change it.
img -= self.mean[:, None, None] | ||
img = img.astype(np.float32, copy=False) | ||
if self._use_pretrained_model: | ||
# Pre-trained model is trained for BGR images |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you flip the order of in_channels of the weights in conversion code?
By doing so, this if statement can be deleted.
I want to make pspnet.py
to be as simple as possible at the expense of more complex conversion code because people would rarely see the conversion code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I'll try to do it.
} | ||
} | ||
|
||
def __init__(self, n_class=None, input_size=None, n_blocks=None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about making PSPNet50
and PSPNet101
, which inherit from PSPNet
.
In my idea, PSPNet.__init__
would take extractor
as input.
I have the designs of FasterRCNN
and FasterRCNNVGG16
in my mind.
|
||
class ConvBNReLU(chainer.Chain): | ||
|
||
def __init__(self, in_ch, out_ch, ksize, stride=1, pad=1, dilation=1): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you make input variables/variable names similar to Conv2DBNActiv
?
try: | ||
from chainermn.links import MultiNodeBatchNormalization | ||
except Exception: | ||
warnings.warn('To perform batch normalization with multiple GPUs or ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of raising a warning during import, it should be raised when PSPNet is instantiated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please fix this. Please make sure that the error is raised only when comm
is specified.
Also, we should install the latest release.
I ran
|
Can you make sure that |
|
||
if __name__ == '__main__': | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument('--img_fn', '-f', type=str) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use
parser.add_argument('image')
for parsing image path?
This is the style used by other demos.
parser.add_argument('--img_fn', '-f', type=str) | ||
parser.add_argument('--gpu', '-g', type=int, default=-1) | ||
parser.add_argument('--scales', '-s', type=float, nargs='*', default=None) | ||
parser.add_argument('--out_dir', '-o', type=str, default='.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you change the demo to plot.show
instead of plot.savefig
?
As a consequence, could you remove this option?
parser.add_argument('--gpu', '-g', type=int, default=-1) | ||
parser.add_argument('--scales', '-s', type=float, nargs='*', default=None) | ||
parser.add_argument('--out_dir', '-o', type=str, default='.') | ||
parser.add_argument('--model', '-m', type=str, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use model
option when mentioning architectures of networks (e.g., SSD512
and SSD300
).
Could you use pretrained_model
as the name of option?
from chainercv.links import PSPNet | ||
from chainercv.utils import read_image | ||
from chainercv.visualizations import vis_image | ||
from chainercv.visualizations import vis_label |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name of the function has been modified to vis_semantic_segmentation
.
|
||
if args.model == 'voc2012': | ||
model = PSPNet(pretrained_model='voc2012') | ||
labels = voc_semantic_segmentation_label_names |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you change the name to label_names
?
labels
is (B, H, W)
array in this context.
return pred | ||
|
||
|
||
if __name__ == '__main__': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about changing the name of the file to predict_cityscapes
.
@@ -1,3 +1,3 @@ | |||
[pep8] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should merge .pep8
to setup.cfg
because this is how Chainer does it.
@@ -0,0 +1,3 @@ | |||
[flake8] | |||
exclude = .eggs,*.egg,build,caffe_pb2.py,caffe_pb3.py,docs,.git | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please delete empty line.
try: | ||
from chainermn.links import MultiNodeBatchNormalization | ||
except Exception: | ||
warnings.warn('To perform batch normalization with multiple GPUs or ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please fix this. Please make sure that the error is raised only when comm
is specified.
Also, we should install the latest release.
What do you think about reusing ResBlock for https://github.com/chainer/chainercv/blob/master/chainercv/links/model/resnet/resblock.py |
👍 for reusing |
I was actually working on it, but had not yet completed implementations. https://github.com/yuyu2172/chainercv/tree/add-pspnet-infer-major-change |
Reopening PR #610 |
@yuyu2172 Thanks, that's fine. I think it's better to close this PR. Thank you for handing over this. |
Please merge #494 and #392 first.
This PR uses
Conv2DBNActiv
with a ChainerMN communicator andCityscapesSemanticSegmentationDataset
.This PR adds PSPNet model definition and it's inference demo code.
This also includes convert.py to convert the official caffemodel to Chainer model.