pytorch finetuning 자신의 그림 을 훈련 합 니 다.

1.pytorch finetuning 자신의 그림 을 훈련 합 니 다.
이 그림 을 읽 는 방식 은 torch 가 가지 고 있 는 ImageFolder 를 사용 합 니 다.읽 는 폴 더 는 큰 하위 파일 에서 분류 별로 분류 해 야 합 니 다.
내 가 지금 세 가지 유형 을 구분 하려 고 하 는 것 처럼

#perpare data set
#train data
train_data=torchvision.datasets.ImageFolder('F:/eyeDataSet/trainData',transform=transforms.Compose(
         [
            transforms.Scale(256),
            transforms.CenterCrop(224),
            transforms.ToTensor()
       ]))
print(len(train_data))
train_loader=DataLoader(train_data,batch_size=20,shuffle=True)
그 다음 에 fine tuning 자신의 네트워크 입 니 다.torch 에서 전체 네트워크 를 수정 한 후에 모든 인 자 를 훈련 시 킬 수 있 습 니 다.그 중의 일부분 만 훈련 할 수 있 습 니 다.저 는 마지막 연결 층 만 훈련 할 것 입 니 다.
torchvision 에 서 는 resnet,Vgg,Alexnet 등 자주 사용 되 는 모델 을 많이 제공 합 니 다.

# prepare model
mode1_ft_res18=torchvision.models.resnet18(pretrained=True)
for param in mode1_ft_res18.parameters():
    param.requires_grad=False
num_fc=mode1_ft_res18.fc.in_features
mode1_ft_res18.fc=torch.nn.Linear(num_fc,3)
자신의 유 틸 리 티 를 정의 합 니 다.이 매개 변 수 는 마지막 층 에 만 들 어 갑 니 다.

#loss function and optimizer
criterion=torch.nn.CrossEntropyLoss()
#parameters only train the last fc layer
optimizer=torch.optim.Adam(mode1_ft_res18.fc.parameters(),lr=0.001)
그리고 훈련 을 시작 할 수 있 습 니 다.다양한 인 자 를 정의 할 수 있 습 니 다.

#start train
#label  not  one-hot encoder
EPOCH=1
for epoch in range(EPOCH):
    train_loss=0.
    train_acc=0.
    for step,data in enumerate(train_loader):
        batch_x,batch_y=data
        batch_x,batch_y=Variable(batch_x),Variable(batch_y)
        #batch_y not one hot
        #out is the probability of eatch class
        # such as one sample[-1.1009  0.1411  0.0320],need to calculate the max index
        # out shape is batch_size * class
        out=mode1_ft_res18(batch_x)
        loss=criterion(out,batch_y)
        train_loss+=loss.data[0]
        # pred is the expect class
        #batch_y is the true label
        pred=torch.max(out,1)[1]
        train_correct=(pred==batch_y).sum()
        train_acc+=train_correct.data[0]
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if step%14==0:
            print('Epoch: ',epoch,'Step',step,
                  'Train_loss: ',train_loss/((step+1)*20),'Train acc: ',train_acc/((step+1)*20))
테스트 부분 과 훈련 부분 이 비슷 해서 일일이 설명 하지 않 겠 습 니 다.
이렇게 하면 자신의 네트워크 에 대한 훈련 테스트 를 완전 하 게 할 수 있 습 니 다.전체 코드 는 다음 과 같 습 니 다.

import torch
import numpy as np
import torchvision
from torchvision import transforms,utils
from torch.utils.data import DataLoader
from torch.autograd import Variable
#perpare data set
#train data
train_data=torchvision.datasets.ImageFolder('F:/eyeDataSet/trainData',transform=transforms.Compose(
           [
               transforms.Scale(256),
               transforms.CenterCrop(224),
               transforms.ToTensor()
         ]))
print(len(train_data))
train_loader=DataLoader(train_data,batch_size=20,shuffle=True)
 
#test data
test_data=torchvision.datasets.ImageFolder('F:/eyeDataSet/testData',transform=transforms.Compose(
           [
         transforms.Scale(256),
         transforms.CenterCrop(224),
         transforms.ToTensor()
         ]))
test_loader=DataLoader(test_data,batch_size=20,shuffle=True)
 
# prepare model
mode1_ft_res18=torchvision.models.resnet18(pretrained=True)
for param in mode1_ft_res18.parameters():
    param.requires_grad=False
num_fc=mode1_ft_res18.fc.in_features
mode1_ft_res18.fc=torch.nn.Linear(num_fc,3)
 
#loss function and optimizer
criterion=torch.nn.CrossEntropyLoss()
#parameters only train the last fc layer
optimizer=torch.optim.Adam(mode1_ft_res18.fc.parameters(),lr=0.001)
 
#start train
#label  not  one-hot encoder
EPOCH=1
for epoch in range(EPOCH):
    train_loss=0.
    train_acc=0.
    for step,data in enumerate(train_loader):
        batch_x,batch_y=data
        batch_x,batch_y=Variable(batch_x),Variable(batch_y)
        #batch_y not one hot
        #out is the probability of eatch class
        # such as one sample[-1.1009  0.1411  0.0320],need to calculate the max index
        # out shape is batch_size * class
        out=mode1_ft_res18(batch_x)
        loss=criterion(out,batch_y)
        train_loss+=loss.data[0]
        # pred is the expect class
        #batch_y is the true label
        pred=torch.max(out,1)[1]
        train_correct=(pred==batch_y).sum()
        train_acc+=train_correct.data[0]
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        if step%14==0:
            print('Epoch: ',epoch,'Step',step,
                  'Train_loss: ',train_loss/((step+1)*20),'Train acc: ',train_acc/((step+1)*20))
 
    #print('Epoch: ', epoch, 'Train_loss: ', train_loss / len(train_data), 'Train acc: ', train_acc / len(train_data))
 
# test model
mode1_ft_res18.eval()
eval_loss=0
eval_acc=0
for step ,data in enumerate(test_loader):
    batch_x,batch_y=data
    batch_x,batch_y=Variable(batch_x),Variable(batch_y)
    out=mode1_ft_res18(batch_x)
    loss = criterion(out, batch_y)
    eval_loss += loss.data[0]
    # pred is the expect class
    # batch_y is the true label
    pred = torch.max(out, 1)[1]
    test_correct = (pred == batch_y).sum()
    eval_acc += test_correct.data[0]
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
print( 'Test_loss: ', eval_loss / len(test_data), 'Test acc: ', eval_acc / len(test_data))
2.PyTorch 는 예비 훈련 모델 을 이용 하여 Fine-tuning 을 진행 합 니 다.
Deep Learning 분야 에서 많은 하위 분야 의 응용,예 를 들 어 일부 동물 의 식별,음식의 식별 등 이 있다.공 개 된 사용 가능 한 데이터 베 이 스 는 ImageNet 등 데이터 베이스 에 비해 규모 가 너무 작 아서 깊이 있 는 네트워크 모델 을 이용 하여 train from scratch 를 직접 사용 하지 못 해 의합 을 일 으 키 기 쉽다.이 럴 때 대규모 데이터 베이스 에서 이미 훈련 을 마 친 모델 을 가 져 와 목표 데이터 베이스 에서 Fine-tuning(미세 조정)을 직접 진행 해 야 한다.이 이미 훈련 을 거 친 모델 은 목표 데이터 세트 에 있어 상대 적 으로 좋 은 매개 변수 초기 화 방법 일 뿐이다.특히 빅 데이터 세트 가 목표 데이터 세트 구조 와 비슷 하 다 면목표 데이터 세트 에서 미세 조정 을 통 해 좋 은 효 과 를 얻 을 수 있다.
Fine-tune 예비 훈련 네트워크 의 절차:
1.우선 예비 훈련 모델 분류 층 의 전체 연결 층 의 수 를 변경 합 니 다.일반 목표 데이터 세트 의 유형 수 는 대규모 데이터 베이스 의 유형 수 와 일치 하지 않 기 때문에 목표 데이터 세트 에 있 는 훈련 집합 의 유형 수로 변경 하면 됩 니 다.일치 하면 변경 할 필요 가 없습니다.
2.분류 기 앞의 네트워크 의 모든 층 의 매개 변 수 를 고정 시킨다.즉,학습 에 참여 하지 못 하 게 하고 역방향 전 파 를 하지 않 고 분류 층 의 네트워크 만 훈련 할 수 있다.이때 학습 율 은 크게 설정 할 수 있다.예 를 들 어 원래 의 초기 학습 율 의 10 배 또는 몇 배 또는 0.01 등 이다.이때 네트워크 훈련 이 비교적 빠르다.분류 층 을 제외 하고 다른 층 은 역방향 전 파 를 할 필요 가 없 기 때문이다.서로 다른 학습 율 설정 을 많이 시도 할 수 있 습 니 다.
3.다음은 상대 적 으로 작은 학 습 률 을 설정 하고 전체 네트워크 를 훈련 하 는 것 이다.이때 인터넷 훈련 이 느 려 졌 다.
다음은 PyTorch 딥 러 닝 프레임 워 크 인 Fine-tune 프 리 트 레이 닝 네트워크 를 이용 하 는 과정 에서 관련 된 고정 적 인 학습 가능 매개 변수,서로 다른 층 에 서로 다른 학 습 률 을 설정 하 는 등 상세 하 게 설명 한다.
1.PyTorch 가 특정 층 의 고정 네트워크 에 대한 학습 가능 한 매개 변수 방법:

class Net(nn.Module):
    def __init__(self, num_classes=546):
        super(Net, self).__init__()
        self.features = nn.Sequential(
 
            nn.Conv2d(1, 64, kernel_size=3, stride=2, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
 
            nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
        )
 
        self.Conv1_1 = nn.Sequential(
 
            nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
 
            nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(64),
        )
 
  for p in self.parameters():
            p.requires_grad=False
        self.Conv1_2 = nn.Sequential(
 
            nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
 
            nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(64),
        )
상기 코드 와 같이 모델 Net 네트워크 에서 self.features 와 self.conv11 층 의 매개 변 수 는 고정 되 어 있어 서 배 울 수 없습니다.이것 은 주로 코드 를 봅 니 다.

for p in self.parameters():
    p.requires_grad=False
삽 입 된 위치 에 이 코드 앞의 모든 층 의 매개 변 수 는 배 울 수 없고 역방향 전파 과정 도 없다.또한 특정한 층 의 매개 변 수 를 학습 할 수 없 도록 지정 할 수 있 습 니 다.다음 과 같 습 니 다.

for p in  self.features.parameters():
    p.requires_grad=False
self.features 층 의 모든 매개 변 수 는 배 울 수 없습니다.
상기 코드 설정 이 진정 으로 적용 되 려 면 네트워크 를 훈련 할 때 유 틸 리 티 를 다음 과 같이 설정 해 야 합 니 다.

 optimizer = torch.optim.SGD(filter(lambda p: p.requires_grad, model.parameters()), args.lr,
        momentum=args.momentum,
        weight_decay=args.weight_decay)
2.PyTorch 는 층 에 따라 학습 율 을 설정 합 니 다.

model = Net()
conv1_2_params = list(map(id, model.Conv1_2.parameters()))
base_params = filter(lambda p: id(p) not in conv1_2_params,
                     model.parameters())
optimizer = torch.optim.SGD([
            {'params': base_params},
            {'params': model.Conv1_2.parameters(), 'lr': 10 * args.lr}], args.lr,             
            momentum=args.momentum, weight_decay=args.weight_decay)
상기 코드 는 모델 Net 네트워크 의 self.conv1 를 표시 합 니 다.2 층 의 학 습 률 은 전입 학 습 률 의 10 배로 설정,baseparams 학습 에 명확 한 설정 이 없 으 면 기본적으로 들 어 오 는 학습 율 args.lr 입 니 다.
주의:

[{'params': base_params}, {'params': model.Conv1_2.parameters(), 'lr': 10 * args.lr}]
목록 에 있 는 사전 구 조 를 표시 합 니 다.
이런 방법 은 서로 다른 학 습 률 을 설정 하 는 것 이 유연 하지 않 고 서로 다른 층 에 유연 한 학 습 률 을 설정 할 수 있 으 며 다음 과 같은 방법 으로 adjustlearning_rate 함수 설정:

def adjust_learning_rate(optimizer, epoch, args):
    lre = []
    lre.extend([0.01] * 10)
    lre.extend([0.005] * 10)
    lre.extend([0.0025] * 10)
    lr = lre[epoch]
    optimizer.param_groups[0]['lr'] = 0.9 * lr
    optimizer.param_groups[1]['lr'] = 10 * lr
    print(param_group[0]['lr'])
    print(param_group[1]['lr'])
상기 코드 중의 optimizer.paramgroups[0]는[{'params':baseparams}, {'params': model.Conv1_2.parameters(),'lr':10*args.lr}]의'params':baseparams},optimizer.param_groups[1]대표{'params':model.conv12.parameters(),'lr':10*args.lr}.여기 설 치 된 학 습 률 은 args.lr 를 덮어 씁 니 다.개인 적 으로 상기 코드 는 학 습 률 을 설정 하 는 데 더욱 유연 하 다 고 생각 합 니 다.상기 코드 도 다음 과 같이 실현 할 수 있 습 니 다.(학습 율 을 마음대로 설정 하고 상기 코드 와 일치 하지 않 음)

def adjust_learning_rate(optimizer, epoch, args):
    lre = np.logspace(-2, -4, 40)
    lr = lre[epoch]
    for i in range(len(optimizer.param_groups)):
        param_group = optimizer.param_groups[i]
        if i == 0:
            param_group['lr'] = 0.9 * lr
        else:
            param_group['lr'] = 10 * lr
        print(param_group['lr'])
다음은 SGD 유 틸 리 티 의 PyTorch 구현 과 모든 매개 변수의 설정 과 의 미 를 표시 합 니 다.구체 적 으로 다음 과 같 습 니 다.

import torch
from .optimizer import Optimizer, required
 
class SGD(Optimizer):
    r"""Implements stochastic gradient descent (optionally with momentum).
    Nesterov momentum is based on the formula from
    `On the importance of initialization and momentum in deep learning`__.
    Args:
        params (iterable): iterable of parameters to optimize or dicts defining
            parameter groups
        lr (float): learning rate
        momentum (float, optional): momentum factor (default: 0)
        weight_decay (float, optional): weight decay (L2 penalty) (default: 0)
        dampening (float, optional): dampening for momentum (default: 0)
        nesterov (bool, optional): enables Nesterov momentum (default: False)
    Example:
        >>> optimizer = torch.optim.SGD(model.parameters(), lr=0.1, momentum=0.9)
        >>> optimizer.zero_grad()
        >>> loss_fn(model(input), target).backward()
        >>> optimizer.step()
    __ http://www.cs.toronto.edu/%7Ehinton/absps/momentum.pdf
    .. note::
        The implementation of SGD with Momentum/Nesterov subtly differs from
        Sutskever et. al. and implementations in some other frameworks.
        Considering the specific case of Momentum, the update can be written as
        .. math::
                  v = \rho * v + g \\
                  p = p - lr * v
        where p, g, v and :math:`\rho` denote the parameters, gradient,
        velocity, and momentum respectively.
        This is in contrast to Sutskever et. al. and
        other frameworks which employ an update of the form
        .. math::
             v = \rho * v + lr * g \\
             p = p - v
        The Nesterov version is analogously modified.
    """
 
    def __init__(self, params, lr=required, momentum=0, dampening=0,
                 weight_decay=0, nesterov=False):
        if lr is not required and lr < 0.0:
            raise ValueError("Invalid learning rate: {}".format(lr))
        if momentum < 0.0:
            raise ValueError("Invalid momentum value: {}".format(momentum))
        if weight_decay < 0.0:
            raise ValueError("Invalid weight_decay value: {}".format(weight_decay))
 
        defaults = dict(lr=lr, momentum=momentum, dampening=dampening,
                        weight_decay=weight_decay, nesterov=nesterov)
        if nesterov and (momentum <= 0 or dampening != 0):
            raise ValueError("Nesterov momentum requires a momentum and zero dampening")
        super(SGD, self).__init__(params, defaults)
 
    def __setstate__(self, state):
        super(SGD, self).__setstate__(state)
        for group in self.param_groups:
            group.setdefault('nesterov', False)
 
    def step(self, closure=None):
        """Performs a single optimization step.
        Arguments:
            closure (callable, optional): A closure that reevaluates the model
                and returns the loss.
        """
        loss = None
        if closure is not None:
            loss = closure()
 
        for group in self.param_groups:
            weight_decay = group['weight_decay']
            momentum = group['momentum']
            dampening = group['dampening']
            nesterov = group['nesterov']
 
            for p in group['params']:
                if p.grad is None:
                    continue
                d_p = p.grad.data
                if weight_decay != 0:
                    d_p.add_(weight_decay, p.data)
                if momentum != 0:
                    param_state = self.state[p]
                    if 'momentum_buffer' not in param_state:
                        buf = param_state['momentum_buffer'] = torch.zeros_like(p.data)
                        buf.mul_(momentum).add_(d_p)
                    else:
                        buf = param_state['momentum_buffer']
                        buf.mul_(momentum).add_(1 - dampening, d_p)
                    if nesterov:
                        d_p = d_p.add(momentum, buf)
                    else:
                        d_p = buf
 
                p.data.add_(-group['lr'], d_p)
 
        return loss
경험 총화:
Fine-tuning 에 있 을 때 층 의 매개 변 수 를 분리 해서 학습 할 수 있 는 지 여 부 를 설정 하지 않 는 것 이 좋 습 니 다.이렇게 하면 일반 효과 떡 이 이상 적 이지 않 습 니 다.일반 준칙 을 만 들 면 됩 니 다.즉,먼저 Fine-tuning 분류 층,학습 율 을 크게 설정 한 다음 에 전체 네트워크 를 작은 학습 율 로 설정 하고 모든 층 이 함께 훈련 합 니 다.
Fine-tune 분류 층 을 거치 지 않 고 전체 네트워크 의 모든 층 을 함께 훈련 하 는 것 은 분류 층 의 학습 율 이 상대 적 으로 높 을 뿐 이렇게 해도 되 고 어떤 효과 가 더 좋 은 지 평가 한 적 이 없다.삼원 조 손실(triplet loss)을 softmax loss 로 훈련 하 는 네트워크 로 미세 조정 할 때 계단 형의 초등학교 습 률 을 설정 할 수 있 고 전체 네트워크 의 모든 층 이 함께 훈련 하면 효과 가 비교적 좋 으 며 먼저 Fine-tune 분류 층 의 앞 층 의 출력 을 사용 하지 않 아 도 된다.
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기