|
|
|
|
|
|
|
import torch |
|
import torch.nn as nn |
|
import torch.optim as optim |
|
from torchvision import models |
|
from torchvision.models.vgg import VGG |
|
|
|
from data_train import dataloader |
|
from data_val import dataloader_val |
|
import pdb |
|
import numpy as np |
|
import time |
|
import matplotlib.pyplot as plt |
|
|
|
import os |
|
|
|
|
|
|
|
|
|
class FCN32s(nn.Module): |
|
|
|
def __init__(self, pretrained_net, n_class): |
|
super().__init__() |
|
self.n_class = n_class |
|
self.pretrained_net = pretrained_net |
|
self.relu = nn.ReLU(inplace=True) |
|
self.deconv1 = nn.ConvTranspose2d(512, 512, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn1 = nn.BatchNorm2d(512) |
|
self.deconv2 = nn.ConvTranspose2d(512, 256, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn2 = nn.BatchNorm2d(256) |
|
self.deconv3 = nn.ConvTranspose2d(256, 128, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn3 = nn.BatchNorm2d(128) |
|
self.deconv4 = nn.ConvTranspose2d(128, 64, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn4 = nn.BatchNorm2d(64) |
|
self.deconv5 = nn.ConvTranspose2d(64, 32, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn5 = nn.BatchNorm2d(32) |
|
self.classifier = nn.Conv2d(32, n_class, kernel_size=1) |
|
|
|
def forward(self, x): |
|
output = self.pretrained_net(x) |
|
x5 = output['x5'] |
|
|
|
score = self.bn1(self.relu(self.deconv1(x5))) |
|
score = self.bn2(self.relu(self.deconv2(score))) |
|
score = self.bn3(self.relu(self.deconv3(score))) |
|
score = self.bn4(self.relu(self.deconv4(score))) |
|
score = self.bn5(self.relu(self.deconv5(score))) |
|
score = self.classifier(score) |
|
|
|
return score |
|
|
|
|
|
class FCN16s(nn.Module): |
|
|
|
def __init__(self, pretrained_net, n_class): |
|
super().__init__() |
|
self.n_class = n_class |
|
self.pretrained_net = pretrained_net |
|
self.relu = nn.ReLU(inplace=True) |
|
self.deconv1 = nn.ConvTranspose2d(512, 512, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn1 = nn.BatchNorm2d(512) |
|
self.deconv2 = nn.ConvTranspose2d(512, 256, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn2 = nn.BatchNorm2d(256) |
|
self.deconv3 = nn.ConvTranspose2d(256, 128, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn3 = nn.BatchNorm2d(128) |
|
self.deconv4 = nn.ConvTranspose2d(128, 64, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn4 = nn.BatchNorm2d(64) |
|
self.deconv5 = nn.ConvTranspose2d(64, 32, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn5 = nn.BatchNorm2d(32) |
|
self.classifier = nn.Conv2d(32, n_class, kernel_size=1) |
|
|
|
def forward(self, x): |
|
output = self.pretrained_net(x) |
|
x5 = output['x5'] |
|
x4 = output['x4'] |
|
|
|
score = self.relu(self.deconv1(x5)) |
|
score = self.bn1(score + x4) |
|
score = self.bn2(self.relu(self.deconv2(score))) |
|
score = self.bn3(self.relu(self.deconv3(score))) |
|
score = self.bn4(self.relu(self.deconv4(score))) |
|
score = self.bn5(self.relu(self.deconv5(score))) |
|
score = self.classifier(score) |
|
|
|
return score |
|
|
|
|
|
class FCN8s(nn.Module): |
|
|
|
def __init__(self, pretrained_net, n_class): |
|
super().__init__() |
|
self.n_class = n_class |
|
self.pretrained_net = pretrained_net |
|
self.relu = nn.ReLU(inplace=True) |
|
self.deconv1 = nn.ConvTranspose2d(512, 512, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn1 = nn.BatchNorm2d(512) |
|
self.deconv2 = nn.ConvTranspose2d(512, 256, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn2 = nn.BatchNorm2d(256) |
|
self.deconv3 = nn.ConvTranspose2d(256, 128, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn3 = nn.BatchNorm2d(128) |
|
self.deconv4 = nn.ConvTranspose2d(128, 64, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn4 = nn.BatchNorm2d(64) |
|
self.deconv5 = nn.ConvTranspose2d(64, 32, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn5 = nn.BatchNorm2d(32) |
|
self.classifier = nn.Conv2d(32, n_class, kernel_size=1) |
|
|
|
def forward(self, x): |
|
output = self.pretrained_net(x) |
|
x5 = output['x5'] |
|
x4 = output['x4'] |
|
x3 = output['x3'] |
|
|
|
score = self.relu(self.deconv1(x5)) |
|
score = self.bn1(score + x4) |
|
score = self.relu(self.deconv2(score)) |
|
score = self.bn2(score + x3) |
|
score = self.bn3(self.relu(self.deconv3(score))) |
|
score = self.bn4(self.relu(self.deconv4(score))) |
|
score = self.bn5(self.relu(self.deconv5(score))) |
|
score = self.classifier(score) |
|
|
|
return score |
|
|
|
|
|
class FCNs(nn.Module): |
|
|
|
def __init__(self, pretrained_net, n_class): |
|
super().__init__() |
|
self.n_class = n_class |
|
self.pretrained_net = pretrained_net |
|
self.relu = nn.ReLU(inplace=True) |
|
self.deconv1 = nn.ConvTranspose2d(512, 512, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn1 = nn.BatchNorm2d(512) |
|
self.deconv2 = nn.ConvTranspose2d(512, 256, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn2 = nn.BatchNorm2d(256) |
|
self.deconv3 = nn.ConvTranspose2d(256, 128, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn3 = nn.BatchNorm2d(128) |
|
self.deconv4 = nn.ConvTranspose2d(128, 64, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn4 = nn.BatchNorm2d(64) |
|
self.deconv5 = nn.ConvTranspose2d(64, 32, kernel_size=3, stride=2, padding=1, dilation=1, output_padding=1) |
|
self.bn5 = nn.BatchNorm2d(32) |
|
self.classifier = nn.Conv2d(32, n_class, kernel_size=1) |
|
|
|
def forward(self, x): |
|
output = self.pretrained_net(x) |
|
x5 = output['x5'] |
|
x4 = output['x4'] |
|
x3 = output['x3'] |
|
x2 = output['x2'] |
|
x1 = output['x1'] |
|
|
|
score = self.bn1(self.relu(self.deconv1(x5))) |
|
score = score + x4 |
|
score = self.bn2(self.relu(self.deconv2(score))) |
|
score = score + x3 |
|
score = self.bn3(self.relu(self.deconv3(score))) |
|
score = score + x2 |
|
score = self.bn4(self.relu(self.deconv4(score))) |
|
score = score + x1 |
|
score = self.bn5(self.relu(self.deconv5(score))) |
|
score = self.classifier(score) |
|
|
|
return score |
|
|
|
|
|
class VGGNet(VGG): |
|
def __init__(self, pretrained=True, model='vgg16', requires_grad=True, remove_fc=True, show_params=False): |
|
super().__init__(make_layers(cfg[model])) |
|
self.ranges = ranges[model] |
|
|
|
if pretrained: |
|
exec("self.load_state_dict(models.%s(pretrained=True).state_dict())" % model) |
|
|
|
if not requires_grad: |
|
for param in super().parameters(): |
|
param.requires_grad = False |
|
|
|
if remove_fc: |
|
del self.classifier |
|
|
|
if show_params: |
|
for name, param in self.named_parameters(): |
|
print(name, param.size()) |
|
|
|
def forward(self, x): |
|
output = {} |
|
|
|
for idx in range(len(self.ranges)): |
|
for layer in range(self.ranges[idx][0], self.ranges[idx][1]): |
|
x = self.features[layer](x) |
|
output["x%d"%(idx+1)] = x |
|
|
|
return output |
|
|
|
|
|
ranges = { |
|
'vgg11': ((0, 3), (3, 6), (6, 11), (11, 16), (16, 21)), |
|
'vgg13': ((0, 5), (5, 10), (10, 15), (15, 20), (20, 25)), |
|
'vgg16': ((0, 5), (5, 10), (10, 17), (17, 24), (24, 31)), |
|
'vgg19': ((0, 5), (5, 10), (10, 19), (19, 28), (28, 37)) |
|
} |
|
|
|
|
|
cfg = { |
|
'vgg11': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], |
|
'vgg13': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], |
|
'vgg16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'], |
|
'vgg19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'], |
|
} |
|
|
|
def make_layers(cfg, batch_norm=False): |
|
layers = [] |
|
in_channels = 3 |
|
for v in cfg: |
|
if v == 'M': |
|
layers += [nn.MaxPool2d(kernel_size=2, stride=2)] |
|
else: |
|
conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1) |
|
if batch_norm: |
|
layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)] |
|
else: |
|
layers += [conv2d, nn.ReLU(inplace=True)] |
|
in_channels = v |
|
return nn.Sequential(*layers) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
vgg_model = VGGNet(requires_grad=True) |
|
fcn_model = FCNs(pretrained_net=vgg_model, n_class=2) |
|
fcn_model = fcn_model.cuda() |
|
criterion = nn.BCELoss().cuda() |
|
optimizer = optim.SGD(fcn_model.parameters(), lr=1e-2, momentum=0.7) |
|
|
|
|
|
|
|
print('Train {},Validation {}'.format(len(dataloader)*4,len(dataloader_val)*4)) |
|
epochs=10 |
|
train_loss=[] |
|
valid_loss=[] |
|
for epo in range(epochs): |
|
start = time.time() |
|
|
|
epo_loss = 0 |
|
fcn_model.train() |
|
for item in dataloader: |
|
input = item['A'] |
|
y = item['B'] |
|
input = torch.autograd.Variable(input) |
|
y = torch.autograd.Variable(y) |
|
input = input.cuda() |
|
y = y.cuda() |
|
optimizer.zero_grad() |
|
output = fcn_model(input) |
|
output = nn.functional.sigmoid(output) |
|
loss = criterion(output, y) |
|
loss.backward() |
|
epo_loss += loss.item() |
|
optimizer.step() |
|
|
|
|
|
|
|
|
|
|
|
|
|
val_loss = 0 |
|
fcn_model.eval() |
|
with torch.no_grad(): |
|
for item in dataloader_val: |
|
input = item['A'] |
|
y = item['B'] |
|
input = torch.autograd.Variable(input) |
|
y = torch.autograd.Variable(y) |
|
input = input.cuda() |
|
y = y.cuda() |
|
optimizer.zero_grad() |
|
output = fcn_model(input) |
|
output = nn.functional.sigmoid(output) |
|
loss = criterion(output, y) |
|
|
|
val_loss += loss.item() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end = time.time() |
|
trainingLoss = epo_loss/len(dataloader) |
|
validationLoss = val_loss/len(dataloader_val) |
|
train_loss.append(trainingLoss) |
|
valid_loss.append(validationLoss) |
|
print('epoch loss = %f'%(trainingLoss), |
|
'validation loss = %f'%(validationLoss), |
|
'time cost',end-start,'s') |
|
|
|
|
|
if not os.path.exists('checkpoints'): |
|
os.makedirs('checkpoints') |
|
torch.save(fcn_model, 'checkpoints/fcn_model_{}.pt'.format(epo)) |
|
print('saveing checkpoints/fcn_model_{}.pt \n'.format(epo)) |
|
|
|
np.save('training loss', train_loss) |
|
np.save('validation loss', valid_loss) |
|
|
|
|
|
|
|
y1 = train_loss |
|
y2 = valid_loss |
|
|
|
x = np.array(range(epochs)) |
|
|
|
plt.plot(x,y1, label = 'trainingloss') |
|
plt.plot(x,y2, label = 'validloss') |
|
plt.xlabel('Epoch') |
|
plt.ylabel('Loss') |
|
plt.legend() |
|
plt.savefig('Loss'+'.png') |
|
plt.show() |