ADD file via upload
This commit is contained in:
parent
5144866ef5
commit
598b1b1fed
|
@ -0,0 +1,156 @@
|
|||
"""
|
||||
|
||||
Author: Andreas Rössler
|
||||
"""
|
||||
import os
|
||||
import argparse
|
||||
|
||||
|
||||
import torch
|
||||
#import pretrainedmodels
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
from network.xception import xception, xception_concat
|
||||
import math
|
||||
import torchvision
|
||||
|
||||
|
||||
def return_pytorch04_xception(pretrained=False):
|
||||
# Raises warning "src not broadcastable to dst" but thats fine
|
||||
model = xception(pretrained=False)
|
||||
if pretrained:
|
||||
# Load model in torch 0.4+
|
||||
model.fc = model.last_linear
|
||||
del model.last_linear
|
||||
state_dict = torch.load(
|
||||
'/public/liuhonggu/.torch/models/xception-b5690688.pth')
|
||||
for name, weights in state_dict.items():
|
||||
if 'pointwise' in name:
|
||||
state_dict[name] = weights.unsqueeze(-1).unsqueeze(-1)
|
||||
model.load_state_dict(state_dict)
|
||||
model.last_linear = model.fc
|
||||
del model.fc
|
||||
return model
|
||||
|
||||
|
||||
class TransferModel(nn.Module):
|
||||
"""
|
||||
Simple transfer learning model that takes an imagenet pretrained model with
|
||||
a fc layer as base model and retrains a new fc layer for num_out_classes
|
||||
"""
|
||||
def __init__(self, modelchoice, num_out_classes=2, dropout=0.5):
|
||||
super(TransferModel, self).__init__()
|
||||
self.modelchoice = modelchoice
|
||||
if modelchoice == 'xception':
|
||||
self.model = return_pytorch04_xception(pretrained=False)
|
||||
# Replace fc
|
||||
num_ftrs = self.model.last_linear.in_features
|
||||
if not dropout:
|
||||
self.model.last_linear = nn.Linear(num_ftrs, num_out_classes)
|
||||
else:
|
||||
print('Using dropout', dropout)
|
||||
self.model.last_linear = nn.Sequential(
|
||||
nn.Dropout(p=dropout),
|
||||
nn.Linear(num_ftrs, num_out_classes)
|
||||
)
|
||||
elif modelchoice == 'xception_concat':
|
||||
self.model = xception_concat()
|
||||
num_ftrs = self.model.last_linear.in_features
|
||||
if not dropout:
|
||||
self.model.last_linear = nn.Linear(num_ftrs, num_out_classes)
|
||||
else:
|
||||
print('Using dropout', dropout)
|
||||
self.model.last_linear = nn.Sequential(
|
||||
nn.Dropout(p=dropout),
|
||||
nn.Linear(num_ftrs, num_out_classes)
|
||||
)
|
||||
elif modelchoice == 'resnet50' or modelchoice == 'resnet18':
|
||||
if modelchoice == 'resnet50':
|
||||
self.model = torchvision.models.resnet50(pretrained=True)
|
||||
if modelchoice == 'resnet18':
|
||||
self.model = torchvision.models.resnet18(pretrained=True)
|
||||
# Replace fc
|
||||
num_ftrs = self.model.fc.in_features
|
||||
if not dropout:
|
||||
self.model.fc = nn.Linear(num_ftrs, num_out_classes)
|
||||
else:
|
||||
self.model.fc = nn.Sequential(
|
||||
nn.Dropout(p=dropout),
|
||||
nn.Linear(num_ftrs, num_out_classes)
|
||||
)
|
||||
else:
|
||||
raise Exception('Choose valid model, e.g. resnet50')
|
||||
|
||||
def set_trainable_up_to(self, boolean, layername="Conv2d_4a_3x3"):
|
||||
"""
|
||||
Freezes all layers below a specific layer and sets the following layers
|
||||
to true if boolean else only the fully connected final layer
|
||||
:param boolean:
|
||||
:param layername: depends on network, for inception e.g. Conv2d_4a_3x3
|
||||
:return:
|
||||
"""
|
||||
# Stage-1: freeze all the layers
|
||||
if layername is None:
|
||||
for i, param in self.model.named_parameters():
|
||||
param.requires_grad = True
|
||||
return
|
||||
else:
|
||||
for i, param in self.model.named_parameters():
|
||||
param.requires_grad = False
|
||||
if boolean:
|
||||
# Make all layers following the layername layer trainable
|
||||
ct = []
|
||||
found = False
|
||||
for name, child in self.model.named_children():
|
||||
if layername in ct:
|
||||
found = True
|
||||
for params in child.parameters():
|
||||
params.requires_grad = True
|
||||
ct.append(name)
|
||||
if not found:
|
||||
raise Exception('Layer not found, cant finetune!'.format(
|
||||
layername))
|
||||
else:
|
||||
if self.modelchoice == 'xception':
|
||||
# Make fc trainable
|
||||
for param in self.model.last_linear.parameters():
|
||||
param.requires_grad = True
|
||||
|
||||
else:
|
||||
# Make fc trainable
|
||||
for param in self.model.fc.parameters():
|
||||
param.requires_grad = True
|
||||
|
||||
def forward(self, x):
|
||||
x = self.model(x)
|
||||
return x
|
||||
|
||||
|
||||
def model_selection(modelname, num_out_classes,
|
||||
dropout=None):
|
||||
"""
|
||||
:param modelname:
|
||||
:return: model, image size, pretraining<yes/no>, input_list
|
||||
"""
|
||||
if modelname == 'xception':
|
||||
return TransferModel(modelchoice='xception',
|
||||
num_out_classes=num_out_classes)
|
||||
# , 299, \True, ['image'], None
|
||||
elif modelname == 'resnet18':
|
||||
return TransferModel(modelchoice='resnet18', dropout=dropout,
|
||||
num_out_classes=num_out_classes)
|
||||
# , \224, True, ['image'], None
|
||||
elif modelname == 'xception_concat':
|
||||
return TransferModel(modelchoice='xception_concat',
|
||||
num_out_classes=num_out_classes)
|
||||
else:
|
||||
raise NotImplementedError(modelname)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
model, image_size, *_ = model_selection('xception', num_out_classes=2)
|
||||
print(model)
|
||||
model = model.cuda()
|
||||
from torchsummary import summary
|
||||
input_s = (3, image_size, image_size)
|
||||
print(summary(model, input_s))
|
Loading…
Reference in New Issue