Thanks for your reply. But it seems that the internals are expecting 3-channel inputs for the base models? E.g., when I run the following (the goal is a U-Net with 1 input channel images and 2 output channel images):
def custom_resnet18(*args, **kwargs):
model = resnet18(*args, **kwargs)
model.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)
return model
learn = unet_learner(dls = dls,
arch = custom_resnet18,
pretrained = True,
n_in=1,
n_out=2)
I get the following error:
/opt/conda/lib/python3.7/site-packages/fastai/vision/learner.py in unet_learner(dls, arch, normalize, n_out, pretrained, config, loss_func, opt_func, lr, splitter, cbs, metrics, path, model_dir, wd, wd_bn_bias, train_bn, moms, **kwargs)
219 img_size = dls.one_batch()[0].shape[-2:]
220 assert img_size, "image size could not be inferred from data"
--> 221 model = create_unet_model(arch, n_out, img_size, pretrained=pretrained, **kwargs)
222
223 splitter=ifnone(splitter, meta['split'])
/opt/conda/lib/python3.7/site-packages/fastai/vision/learner.py in create_unet_model(arch, n_out, img_size, pretrained, cut, n_in, **kwargs)
194 "Create custom unet architecture"
195 meta = model_meta.get(arch, _default_meta)
--> 196 body = create_body(arch, n_in, pretrained, ifnone(cut, meta['cut']))
197 model = models.unet.DynamicUnet(body, n_out, img_size, **kwargs)
198 return model
/opt/conda/lib/python3.7/site-packages/fastai/vision/learner.py in create_body(arch, n_in, pretrained, cut)
64 "Cut off the body of a typically pretrained `arch` as determined by `cut`"
65 model = arch(pretrained=pretrained)
---> 66 _update_first_layer(model, n_in, pretrained)
67 #cut = ifnone(cut, cnn_config(arch)['cut'])
68 if cut is None:
/opt/conda/lib/python3.7/site-packages/fastai/vision/learner.py in _update_first_layer(model, n_in, pretrained)
51 first_layer, parent, name = _get_first_layer(model)
52 assert isinstance(first_layer, nn.Conv2d), f'Change of input channels only supported with Conv2d, found {first_layer.__class__.__name__}'
---> 53 assert getattr(first_layer, 'in_channels') == 3, f'Unexpected number of input channels, found {getattr(first_layer, "in_channels")} while expecting 3'
54 params = {attr:getattr(first_layer, attr) for attr in 'out_channels kernel_size stride padding dilation groups padding_mode'.split()}
55 params['bias'] = getattr(first_layer, 'bias') is not None
AssertionError: Unexpected number of input channels, found 1 while expecting 3
Which appears to be an assertion in the _update_first_layer code that expects that the first convolutional layer has a 3-channel input. So by pre-changing the first convolutional layer to expect 1 channel input, that assertion fails.
This actually seems to imply that the fastai v2 U-Net is designed to allow you to use the functionality with an arbitrary number of channels, and so now I need to investigate whether my original error is actually totally unrelated to this functionality.