pytorch 分类任务 custom_data 迁移学习 这个流程全代码, 很有通用性
# -*- coding:utf-8 -*-
from __future__ import print_function
from __future__ import division
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import torchvision
from torchvision import datasets, models, transforms
import matplotlib.pyplot as plt
import time
import os
import copy
#screws_train.py
#print("PyTorch Version: ", torch.__version__)
#print("Torchvision Version: ", torchvision.__version__)
#pip install torch==1.3.0+cpu torchvision==0.4.1+cpu -f https://download.pytorch.org/whl/torch_stable.html
#server 虚拟环境 /dataa/three/pytorch1.3 是一样的版本
def train_model(model, dataloaders, criterion, optimizer, scheduler, num_epochs=25, is_inception=False):
since = time.time()
val_acc_history = []
best_model_wts = copy.deepcopy(model.state_dict())
best_acc = 0.0
for epoch in range(num_epochs):
print('Epoch {}/{}'.format(epoch, num_epochs - 1))
print('-' * 10)
print("第%d个epoch的学习率:%f" % (epoch, optimizer.param_groups[0]['lr']))
# 每个 epoch 包含 training 和 validation phase.
for phase in ['train', 'val']:
if phase == 'train':
model.train() # Set model to training mode
else:
model.eval() # Set model to evaluate mode
running_loss = 0.0
running_corrects = 0
# Iterate over data.
for inputs, labels in dataloaders[phase]:
inputs = inputs.to(device)
labels = labels.to(device)
# zero the parameter gradients
optimizer.zero_grad()
# forward
# track history if only in train
with torch.set_grad_enabled(phase == 'train'):
# 计算模型输出及 loss.
# 对于 inception 模型,训练时,其还包括一个辅助 loss;
# 最终的 loss 是辅助 loss 和最终输出 loss 的两者之和. 但,测试时,只考虑最终输出的 loss.
if is_inception and phase == 'train':
outputs, aux_outputs = model(inputs)
loss1 = criterion(outputs, labels)
loss2 = criterion(aux_outputs, labels)
loss = loss1 + 0.4 * loss2
else:
outputs = model(inputs)
loss = criterion(outputs, labels)
_, preds = torch.max(outputs, 1)
# backward + optimize only if in training phase
if phase == 'train':
loss.backward()
optimizer.step()
# statistics
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds == labels.data)
epoch_loss = running_loss / len(dataloaders[phase].dataset)
epoch_acc = running_corrects.double() / len(dataloaders[phase].dataset)
print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase, epoch_loss, epoch_acc))
# deep copy the model
#if phase == 'val' and epoch_acc > best_acc: # after 100 epoch save model
if phase == 'val' and epoch_acc > best_acc and epoch >=100:
best_acc = epoch_acc
best_model_wts = copy.deepcopy(model.state_dict())
if phase == 'val':
val_acc_history.append(epoch_acc)
scheduler.step()
print()
time_elapsed = time.time() - since
print('Training complete in {:.0f}m {:.0f}s'.format(
time_elapsed // 60, time_elapsed % 60))
print('Best val Acc: {:4f}'.format(best_acc))
# load best model weights
model.load_state_dict(best_model_wts)
print(f"------> saved model in { val_acc_history.index(best_acc) } epoch ")
return model, val_acc_history
# 将模型用于特征提取(feature extraction) 时,需要设置 .requires_grad=False
def set_parameter_requires_grad(model, feature_extracting):
if feature_extracting:
for param in model.parameters():
param.requires_grad = False
# step 3 Network initialization and setup
def initialize_model(model_name, num_classes, feature_extract, use_pretrained=True):
model_ft = None
input_size = 0
if model_name == "resnet":
# Resnet18 是非常特殊的(也只是对resnet18是这样 resnet152和alexnet一样加载)
#https://blog.csdn.net/lscelory/article/details/81482586
model_ft = models.resnet18(pretrained=False)
# print(model_ft)
model_ft.load_state_dict(torch.load('/root/.cache/torch/checkpoints/resnet18-5c106cde.pth'))
set_parameter_requires_grad(model_ft, feature_extract)
num_ftrs = model_ft.fc.in_features
model_ft.fc = nn.Linear(num_ftrs, num_classes)
input_size