- Resnet 50
# -*- coding: utf-8 -*-
import torch.nn as nn
import math
import torch.utils.model_zoo as model_zoo
class residual_block(nn.Module):
expansion = 4
def __init__(self, inplanes, planes, stride=1, downsample = None):
super(residual_block, self).__init__()
self.conv1 = nn.Conv2d(inplanes, planes, bias=False, kernel_size=1)
self.bn1 = nn.BatchNorm2d(planes)
self.conv2 = nn.Conv2d(planes, planes, stride = stride, kernel_size=3 , padding=1, bias = False)
self.bn2 = nn.BatchNorm2d(planes)
self.conv3 = nn.Conv2d(planes, planes*4, kernel_size=1,bias=False)
self.bn3 = nn.BatchNorm2d(planes * 4)
self.relu = nn.ReLU(inplace=True)
self.downsample = downsample
self.stride = stride
def forward(self, x):
residual = x
conv1 = self.conv1(x)
bn1 = self.bn1(conv1)
relu1 = self.relu(bn1)
conv2 = self.conv2(relu1)
bn2 = self.bn2(conv2)
relu2 = self.relu(bn2)
conv3 = self.conv3(relu2)
bn3 = self.bn3(conv3)
if self.downsample is not None:
residual = self.downsample(x)
bn3 += residual
out = self.relu(bn3)
return out
class Resnet(nn.Module):
def __init__(self, layers, numclass):
self.inplanes = 64
super(Resnet, self).__init__() ## super函数是用于调用父类(超类)的一个方法
self.conv1 = nn.Conv2d(in_channels=3, out_channels=64, kernel_size=7, stride=2,
padding=3, bias=False)
self.bn1 = nn.BatchNorm2d(num_features=64)
self.relu = nn.ReLU(inplace=True) ##inplace为True,将会改变输入的数据 ,否则不会改变原输入,只会产生新的输出
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = self._make_layer(residual_block, 64, blocks = layers[0], stride=1)
self.layer2 = self._make_layer(residual_block, 128, blocks = layers[1], stride=2)
self.layer3 = self._make_layer(residual_block, 256, blocks = layers[2], stride=2)
self.layer4 = self._make_layer(residual_block, 512, blocks = layers[3], stride=2)
self.avgpool = nn.AvgPool2d(kernel_size=7, stride=1)
self.fc = nn.Linear(512* residual_block.expansion, numclass)
for m in self.modules():
if isinstance(m, nn.Conv2d):
n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
m.weight.data.normal_(0, math.sqrt(2. / n))
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
def _make_layer(self, block, planes, blocks, stride=1):
downsample = None
if stride !=1 or self.inplanes != block.expansion * planes :
print (planes, blocks)
## torch.nn.Sequential是一个Sequential容器,模块将按照构造函数中传递的顺序添加到模块中。
downsample = nn.Sequential(
nn.Conv2d(self.inplanes, planes*block.expansion, kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(planes*block.expansion)
)
layers = []
layers.append(block(self.inplanes, planes, stride, downsample)) ###该部分是将每个blocks的第一个residual结构保存在layers列表中,这个地方是用来进行下采样的
self.inplanes = planes * block.expansion
for i in range(1, blocks):
layers.append(block(self.inplanes, planes))##该部分是将每个blocks的剩下residual 结构保存在layers列表中,这样就完成了一个blocks的构造。
return nn.Sequential(*layers)
def forward(self, x):
x = self.conv1(x)
bn1 = self.bn1(x)
relu = self.relu(bn1)
maxpool = self.maxpool(relu)
layer1 = self.layer1(maxpool)
layer2 = self.layer2(layer1)
layer3 = self.layer3(layer2)
layer4 = self.layer4(layer3)
avgpool = self.avgpool(layer4)
x = avgpool.view(avgpool.size(0),-1)
x = self.fc(x)
return x
- 利用Resnet50, 在场景数据集MIT67上进行Finetune,并进行训练
-
# -*- coding: utf-8 -*- """ Auther : Haitao Zeng date : 2018.12.18 Function: finetune the pre-trained model on MIT67 $sun397 """ from __future__ import print_function, division, absolute_import from PIL import Image import torch import torchvision import torch.nn as nn from torch.autograd import Variable import torch.optim as optim from torch.optim import lr_scheduler import numpy as np from torchvision import datasets, models, transforms import os import time import copy import torch.utils.data as data from Rsenet50 import Resnet import torch.utils.model_zoo as model_zoo def pil_loader(path): with open(path, 'rb') as f: with Image.open(f) as img: return img.convert('RGB') def accimage_loader(path): import accimage try: return accimage.Image(path) except IOError: # Potentially a decoding problem, fall back to PIL.Image return pil_loader(path) def default_loader(path): from torchvision import get_image_backend if get_image_backend() == 'accimage': return accimage_loader(path) else: return pil_loader(path) class CustomImageLoader(data.Dataset): ##自定义类型数据输入 def __init__(self, img_path, txt_path, dataset = '', data_transforms=None, loader = default_loader): im_list = [] im_labels = [] with open(txt_path, 'r') as files: for line in files: items = line.split() if items[0][0] == '/': # fnewname = '_'.join(items[0][1:-4].split('/')) imname = line.split()[0][1:] else: # fnewname = '_'.join(items[0][:-4].split('/')) imname = line.split()[0] im_list.append(os.path.join(img_path, imname)) im_labels.append(int(items[1])) self.imgs = im_list self.labels = im_labels self.data_tranforms = data_transforms self.loader = loader self.dataset = dataset def __len__(self): return len(self.imgs) def __getitem__(self, item): img_name = self.imgs[item] label = self.labels[item] img = self.loader(img_name) if self.data_tranforms is not None: try: img = self.data_tranforms[self.dataset](img) except: print("Cannot transform image: {}".format(img_name)) return img, label NUM_EPOCH=20 batch_size = 32 device = torch.device('cuda:0') ##对数据进行预处理,训练部分包括随机裁剪和水平变换 ##测试部分包括中心裁剪, 两个部分都包含了数据的正则化的过程 data_tranforms={ 'Train':transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225]) ]), 'Test':transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225]) ]) } image_dir = '/media/haitaizeng/00038FCE000387A5/cgw/Datasets/MIT67/Images' image_datasets = {x : CustomImageLoader(image_dir, txt_path=('/home/haitaizeng/stanforf/alex_mit/data_image/'+x+'Images.label'), data_transforms=data_tranforms, dataset=x) for x in ['Train', 'Test'] } dataloders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=batch_size, shuffle=True) for x in ['Train', 'Test']} dataset_sizes = {x: len(image_datasets[x]) for x in ['Train', 'Test']} Train_nums= 5360 Test_nums = 1340 def train_model(model, crtiation, optimizer,schedular, num_epochs=NUM_EPOCH): begin_time = time.time() best_weights = copy.deepcopy(model.state_dict())#copy the weights from the model best_acc = 0.0 for epoch in range(num_epochs): print("-*-" * 20) for phase in ['Train', 'Test']: if phase=='Train': schedular.step() model.train() else: model.eval() running_loss = 0.0 running_acc = 0.0 for images, labels in dataloders[phase]: images.to(device) labels.to(device) optimizer.zero_grad() with torch.set_grad_enabled(phase=='Train'): opt = model(images.cuda()) # opt = model(images) _,pred = torch.max(opt,1) labels = labels.cuda() loss = crtiation(opt, labels) if phase=='Train': loss.backward() optimizer.step() running_loss += loss.item()*images.size(0) running_acc += torch.sum(pred==labels) if phase == 'Train': nums = Train_nums elif phase=='Test': nums == Test_nums epoch_loss = running_loss/dataset_sizes[phase] epoch_acc = running_acc.double()/dataset_sizes[phase] print('epoch={}, Phase={}, Loss={:.4f}, ACC:{:.4f}'.format(epoch, phase, epoch_loss, epoch_acc)) if phase == 'Test' and epoch_acc>best_acc: # Upgrade the weights best_acc=epoch_acc best_weights = copy.deepcopy(model.state_dict()) time_elapes = time.time() - begin_time print('Training Complete in{:.0f}m {:0f}s'.format( time_elapes // 60, time_elapes % 60 )) print('Best Val ACC: {:}'.format(best_acc)) model.load_state_dict(best_weights) return models if __name__ == '__main__': NUMCLASS = 67 pthpath = '/home/haitaizeng/cgw/for_zht/CVPR19/resnet50_places365.pth.tar' # model_ft = models.__ dict__['resnet50'](num_classes=365) ## 加载的是pytorch库中预先写好的Resnet50的网络结构 model_ft = Resnet([3, 4, 6, 3], 365)##这是自行编写的Resnet50,用于后面的特征提取的操作 ##load pre-trained model for funetuning ckpt = torch.load(pthpath, map_location=lambda storage, loc: storage) state_dict = {str.replace(k, 'module.', ''): v for k, v in ckpt['state_dict'].items()} model_ft.load_state_dict(state_dict) ## change the last fully connedected layer num_fits = model_ft.fc.in_features model_ft.fc = nn.Linear(num_fits, NUMCLASS) ## run the model on the cuda---Nvidia -1080ti model_ft = model_ft.to(device) model_ft.cuda() ## cacluate the cross entropu loss criterion = nn.CrossEntropyLoss() ## using SGD to optimize optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9) ## learning rate decay ,when epoch ==10 exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=10, gamma=0.1) model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler, num_epochs=25)
来源:CSDN
作者:Python_print
链接:https://blog.csdn.net/Python_print/article/details/85099683