I want to create a CNN learner that is a resnet architecture plus an extra layer at the end that normalizes the output of the resnet for problem specific reasons. What is the canonical way of doing this?
I have defined by custom output layer as:
class CustomOutput(nn.Module):
def __init__(self):
super().__init__()
def forward(self, xb):
return answer_probability(xb)
The following runs, but it seems a bit hacky:
learner = cnn_learner(data, models.resnet50, metrics=rmse)
learner.model = nn.Sequential(learner.model, CustomOutput())
(I’m also unsure if the frozen layers part of the Learner
operates correctly after this).
I have also tried this:
class CustomCNN(nn.Module):
def __init__(self, arch=models.resnet34):
super().__init__()
self.body = create_body(arch)
self.cnn = nn.Sequential(self.body, CustomOutput())
def forward(self, xb):
return self.cnn(xb)
learner = cnn_learner(data, CustomCNN, metrics=rmse)
But this fails with error:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-46-a5adf3bbf097> in <module>
----> 1 learner = cnn_learner(data, model, metrics=rmse)
/opt/conda/envs/fastai/lib/python3.6/site-packages/fastai/vision/learner.py in cnn_learner(data, base_arch, cut, pretrained, lin_ftrs, ps, custom_head, split_on, bn_final, init, concat_pool, **kwargs)
95 meta = cnn_config(base_arch)
96 model = create_cnn_model(base_arch, data.c, cut, pretrained, lin_ftrs, ps=ps, custom_head=custom_head,
---> 97 split_on=split_on, bn_final=bn_final, concat_pool=concat_pool)
98 learn = Learner(data, model, **kwargs)
99 learn.split(split_on or meta['split'])
/opt/conda/envs/fastai/lib/python3.6/site-packages/fastai/vision/learner.py in create_cnn_model(base_arch, nc, cut, pretrained, lin_ftrs, ps, custom_head, split_on, bn_final, concat_pool)
81 split_on:Optional[SplitFuncOrIdxList]=None, bn_final:bool=False, concat_pool:bool=True):
82 "Create custom convnet architecture"
---> 83 body = create_body(base_arch, pretrained, cut)
84 if custom_head is None:
85 nf = num_features_model(nn.Sequential(*body.children())) * (2 if concat_pool else 1)
/opt/conda/envs/fastai/lib/python3.6/site-packages/fastai/vision/learner.py in create_body(arch, pretrained, cut)
53 def create_body(arch:Callable, pretrained:bool=True, cut:Optional[Union[int, Callable]]=None):
54 "Cut off the body of a typically pretrained `model` at `cut` (int) or cut the model as specified by `cut(model)` (function)."
---> 55 model = arch(pretrained)
56 cut = ifnone(cut, cnn_config(arch)['cut'])
57 if cut is None:
<ipython-input-44-c2079208eac2> in __init__(self, arch)
2 def __init__(self, arch=models.resnet34):
3 super().__init__()
----> 4 self.body = create_body(arch)
5 self.cnn = nn.Sequential(self.body, GalaxyOutput())
6
/opt/conda/envs/fastai/lib/python3.6/site-packages/fastai/vision/learner.py in create_body(arch, pretrained, cut)
53 def create_body(arch:Callable, pretrained:bool=True, cut:Optional[Union[int, Callable]]=None):
54 "Cut off the body of a typically pretrained `model` at `cut` (int) or cut the model as specified by `cut(model)` (function)."
---> 55 model = arch(pretrained)
56 cut = ifnone(cut, cnn_config(arch)['cut'])
57 if cut is None:
TypeError: 'bool' object is not callable