You can get the idea from this post https://discuss.pytorch.org/t/how-to-perform-finetuning-in-pytorch/419
model = torchvision.models.vgg19(pretrained=True) for param in model.parameters(): param.requires_grad = False # Replace the last fully-connected layer # Parameters of newly constructed modules have requires_grad=True by default model.fc = nn.Linear(512, 8) # assuming that the fc7 layer has 512 neurons, otherwise change it model.cuda()
Thank you, I’ll try it!
Don’t forget to retrain the last layer though. At the moment the weights of it have just random numbers, so you must retrain it. You can do the retraining the same way as normal, the only change is that now the weights of the other layers won’t change because I set the requires_grad to False. If you have enough data to do a full training, then simply remove the line which does that, but it will surely take much longer to train.
My torch==0.1.9 while torchvision==0.1.7, but the APIs of torchvision.models.vgg19() seems is different from the docs. Here is the error.It’s the version problem?
I followed the solution from Pre-trained VGG16, but it also has problem.
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-9-cbf958b7f4be> in <module>() 3 import torch.nn as nn 4 import torch.nn.functional as F ----> 5 model = torchvision.models.vgg19(pretrained=True) 6 for param in model.parameters(): 7 param.requires_grad = False TypeError: vgg19() takes no arguments (1 given)
I ran into the same problem. I cloned the latest code repos of
pytorchvision and built both manually.
Or you can refer to this issue
Hmm, I didn’t try the code yesterday and just changed the line from a residual network.
Now I tried it, and got the same error as you. It seems that you can get just the model, but not the weights of it. Which actually contradicts the documentation when it is written that you can give the pretrained argument.
As @Crazyai said, you can refer to that issue and download the model from github. However, bear in mind that they are not planning to release the version with batch normalization. Alternately, use a residual network and finetune it, probably getting even better results than with VGG.
Pretrained VGG models are a new thing. Updating torchvision to the newest version should fix it.
I uninstalled the current torchvision, and rebulid the newest version, and it worked. Thank you very much!
My network initialized as below:
#VGG19 import torchvision import torch.nn as nn import torch.nn.functional as F vgg19 = torchvision.models.vgg19(pretrained=True) for param in vgg19.parameters(): param.requires_grad = False requires_grad=True by default vgg19.fc = nn.Linear(1000, 8) neurons, otherwise change it vgg19.cuda() import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(vgg19.fc.parameters(), lr=0.001, momentum=0.9)#lr 0.001
But when I train with code as below, there is a error in loss.backward():
inputs, labels = Variable(inputs.cuda()), Variable(labels.cuda()) # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = vgg19(inputs) #print(type(outputs),type(inputs)) loss = criterion(outputs, labels) #loss = F.nll_loss(outputs, labels) loss.backward() optimizer.step() step += 1 # print statistics running_loss += loss.data
RuntimeError: there are no graph nodes that require computing gradients
That’s because vgg19 doesn’t have a
fc member variable. Instead, it has a
(classifier): Sequential ( (0): Dropout (p = 0.5) (1): Linear (25088 -> 4096) (2): ReLU (inplace) (3): Dropout (p = 0.5) (4): Linear (4096 -> 4096) (5): ReLU (inplace) (6): Linear (4096 -> 100) )
To replace the last linear layer, a temporary solution would be
vgg19.classifier._modules['6'] = nn.Linear(4096, 8)
Thank you, then how should I change the last layer to param.requires_grad = True
Newly constructed layer has
requires_grad=True by default. You don’t need to do it manually.
thank you. what should I change if I want to add dropout in ‘fc’? the last classifier layer has been changed in terms of the number of classes and I want to add dropout before it.
There’s already a dropout layer before the final FC layer, the code is
self.classifier = nn.Sequential( nn.Linear(512 * 7 * 7, 4096), nn.ReLU(True), nn.Dropout(), nn.Linear(4096, 4096), nn.ReLU(True), nn.Dropout(), nn.Linear(4096, num_classes), )
you only need to replace the last 4096, num_classes to your own fc layer.
i am trying to convert the classification network to regression netowork by replacing the last layer with number of outputs as one can you please suggest any solution ay help would be greatly appreciated i am new to pytorch
You can just do exactly this by setting the last layer as:
In your training procedure you probably want to use
nn.MSELoss as your criterion.
Thank you for your response. However, i tried that here is my code but the model returns nothing
class FineTuneModel(nn.Module): def __init__(self, original_model, num_classes): super(FineTuneModel, self).__init__() # Everything except the last linear layer self.features = nn.Sequential(*list(original_model.children())[:-1]) self.classifier = nn.Sequential( nn.Linear(512, 1) ) self.modelName = 'LightCNN-29' # Freeze those weights for p in self.features.parameters(): p.requires_grad = False def forward(self, x): f = self.features(x) f = f.view(f.size(0), -1) y = self.classifier(f) return y model = FineTuneModel(original_model, args.num_classes) print(model)
FineTuneModel( (features): Sequential() (classifier): Sequential( (0): Linear(in_features=512, out_features=1, bias=True) ) )
original model is pretrained resnet model
class FineTuneModel(nn.Module): def __init__(self, original_model, num_classes): super(FineTuneModel, self).__init__() # Everything except the last linear layer self.features = nn.Sequential(*list(original_model.children())[:-1]) self.classifier = nn.Sequential( nn.Linear(512, 1) ) self.modelName = 'LightCNN-29' # Freeze those weights for p in self.features.parameters(): p.requires_grad = False def forward(self, x): f = self.features(x) f = f.view(f.size(0), -1) y = self.classifier(f) return y
self.features seems to be empty.
Could you check, that
oroginal_model is a valid model?
PS: You can add code with three backticks `. I’ve formatted your code for better readability.