As I said earlier, you can’t do like this if you want to use cnn_learner
. If you want to do it this way, I’d recommend using Learner
instead.
Main advantage of using cnn_learner is as follows:
- fastai custom head (also, automatically inferring no. of classes from DataLoaders)
Sequential(
(0): AdaptiveConcatPool2d(
(ap): AdaptiveAvgPool2d(output_size=1)
(mp): AdaptiveMaxPool2d(output_size=1)
)
(1): Flatten(full=False)
(2): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(3): Dropout(p=0.25, inplace=False)
(4): Linear(in_features=512, out_features=512, bias=False)
(5): ReLU(inplace=True)
(6): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(7): Dropout(p=0.5, inplace=False)
(8): Linear(in_features=512, out_features=20, bias=False)
)
- Add normalize transform if you haven’t already
- Initialize these new layers using Kaiming Normal initializer
Rest of the functionality is managed by Leaner
class, so you’ll get that anyways. Now, coming to your task. You can simply pass your model_hybrid
object to Learner and it will work. But, as I mentioned, weights of your new Module won’t be initialized by fastai anymore. Also, you won’t be able to take advantage of Discriminative Learning rates. To do both, try doing:
model_hybrid = torchvision.models.resnet18(pretrained=True)
cust_head = Quantumnet()
apply_init(cust_head)
model_hybrid.fc = cust_head
def hybrid_splitter(m): return L(m.features,m.fc).map(params)
learn = Learner(data,model_hybrid,splitter=hybrid_splitter,...)
This will freeze the layers in m.features
and will only train your custom head
by default, when you call learn.freeze()
, only last param group is kept trainable and rest of the model is freezed