【PyTorch】7.2 模型Finetune


任务简介:

了解序列化与反序列化;了解transfer learning 与 model finetune

详细说明:

本节第一部分学习pytorch中的模型保存与加载,也常称为序列化与反序列化,本节将讲解序列化与反序列化的概念,进而对模型的保存与加载有深刻的认识,同时介绍pytorch中模型保存与加载的方法函数。

本节第二部分学习模型微调(Finetune)的方法,以及认识Transfer Learning(迁移学习)与Model Finetune之间的关系。

一、Transfer Learning & Model Finetune

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
主要做法是让特征提取层参数不更新或者缓慢更新

二、PyTorch中的 Finetune

在这里插入图片描述
构建AntsDataset:

class AntsDataset(Dataset):
    def __init__(self, data_dir, transform=None):

        self.label_name = {"ants": 0, "bees": 1}
        self.data_info = self.get_img_info(data_dir)  # data_info存储所有图片路径和标签,在DataLoader中通过index读取样本
        self.transform = transform

    def __getitem__(self, index):
        path_img, label = self.data_info[index]
        img = Image.open(path_img).convert('RGB')     # 0~255

        if self.transform is not None:
            img = self.transform(img)   # 在这里做transform,转为tensor等等

        return img, label

    def __len__(self):
        return len(self.data_info)

    def get_img_info(self,data_dir):
        data_info = list()
        for root, dirs, _ in os.walk(data_dir):
            # 遍历类别
            for sub_dir in dirs:
                img_names = os.listdir(os.path.join(root, sub_dir))
                img_names = list(filter(lambda x: x.endswith('.jpg'), img_names))

                # 遍历图片
                for i in range(len(img_names)):
                    img_name = img_names[i]
                    path_img = os.path.join(root, sub_dir, img_name)
                    label = self.label_name[sub_dir]
                    data_info.append((path_img, int(label)))

        if len(data_info) == 0:
            raise Exception("\ndata_dir:{} is a empty dir! Please checkout your path to images!".format(data_dir))
        return data_info

测试代码:

import os
import numpy as np
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
import torch.optim as optim
from matplotlib import pyplot as plt

import sys
hello_pytorch_DIR = os.path.abspath(os.path.dirname(__file__)+os.path.sep+".."+os.path.sep+"..")
sys.path.append(hello_pytorch_DIR)

from tools.my_dataset import AntsDataset
from tools.common_tools import set_seed
import torchvision.models as models
import torchvision
BASEDIR = os.path.dirname(os.path.abspath(__file__))
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print("use device :{}".format(device))

set_seed(1)  # 设置随机种子
label_name = {"ants": 0, "bees": 1}

# 参数设置
MAX_EPOCH = 25
BATCH_SIZE = 16
LR = 0.001
log_interval = 10
val_interval = 1
classes = 2
start_epoch = -1
lr_decay_step = 7


# ============================ step 1/5 数据 ============================
data_dir = os.path.abspath(os.path.join(BASEDIR, "data", "hymenoptera_data"))
# print(data_dir)
if not os.path.exists(data_dir):
    raise Exception("\n{} 不存在,请下载 07-02-数据-模型finetune.zip  放到\n{} 下,并解压即可".format(
        data_dir, os.path.dirname(data_dir)))

train_dir = os.path.join(data_dir, "train")
valid_dir = os.path.join(data_dir, "val")

norm_mean = [0.485, 0.456, 0.406]
norm_std = [0.229, 0.224, 0.225]

train_transform = transforms.Compose([
    transforms.RandomResizedCrop(224),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),
])

valid_transform = transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(224),
    transforms.ToTensor(),
    transforms.Normalize(norm_mean, norm_std),
])

# 构建MyDataset实例
train_data = AntsDataset(data_dir=train_dir, transform=train_transform)
valid_data = AntsDataset(data_dir=valid_dir, transform=valid_transform)

# 构建DataLoder
train_loader = DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
valid_loader = DataLoader(dataset=valid_data, batch_size=BATCH_SIZE)

# ============================ step 2/5 模型 ============================

# 1/3 构建模型
resnet18_ft = models.resnet18()

# 2/3 加载参数
flag = 0
# flag = 1
if flag:
    path_pretrained_model = os.path.join(BASEDIR, "data", "finetune_resnet18-5c106cde.pth")
    if not os.path.exists(path_pretrained_model):
        raise Exception("\n{} 不存在,请下载 07-02-数据-模型finetune.zip\n放到 {}下,并解压即可".format(
            path_pretrained_model, os.path.dirname(path_pretrained_model)))
    state_dict_load = torch.load(path_pretrained_model)
    resnet18_ft.load_state_dict(state_dict_load)

# 法1 : 冻结卷积层
flag_m1 = 0
# flag_m1 = 1
if flag_m1:
    for param in resnet18_ft.parameters():
        param.requires_grad = False
    print("conv1.weights[0, 0, ...]:\n {}".format(resnet18_ft.conv1.weight[0, 0, ...]))


# 3/3 替换fc层
num_ftrs = resnet18_ft.fc.in_features
resnet18_ft.fc = nn.Linear(num_ftrs, classes)


resnet18_ft.to(device)
# ============================ step 3/5 损失函数 ============================
criterion = nn.CrossEntropyLoss()                                                   # 选择损失函数

# ============================ step 4/5 优化器 ============================
# 法2 : conv 小学习率
flag = 0
# flag = 1
if flag:
    fc_params_id = list(map(id, resnet18_ft.fc.parameters()))     # 返回的是parameters中全连接层参数的内存地址
    base_params = filter(lambda p: id(p) not in fc_params_id, resnet18_ft.parameters())
    optimizer = optim.SGD([
        {'params': base_params, 'lr': LR*0},   # 0
        {'params': resnet18_ft.fc.parameters(), 'lr': LR}], momentum=0.9)

else:
    optimizer = optim.SGD(resnet18_ft.parameters(), lr=LR, momentum=0.9)               # 选择优化器

scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=lr_decay_step, gamma=0.1)     # 设置学习率下降策略


# ============================ step 5/5 训练 ============================
train_curve = list()
valid_curve = list()

for epoch in range(start_epoch + 1, MAX_EPOCH):

    loss_mean = 0.
    correct = 0.
    total = 0.

    resnet18_ft.train()
    for i, data in enumerate(train_loader):

        # forward
        inputs, labels = data
        inputs, labels = inputs.to(device), labels.to(device)
        outputs = resnet18_ft(inputs)

        # backward
        optimizer.zero_grad()
        loss = criterion(outputs, labels)
        loss.backward()

        # update weights
        optimizer.step()

        # 统计分类情况
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).squeeze().cpu().sum().numpy()

        # 打印训练信息
        loss_mean += loss.item()
        train_curve.append(loss.item())
        if (i+1) % log_interval == 0:
            loss_mean = loss_mean / log_interval
            print("Training:Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
                epoch, MAX_EPOCH, i+1, len(train_loader), loss_mean, correct / total))
            loss_mean = 0.

            # if flag_m1:
            # print("epoch:{} conv1.weights[0, 0, ...] :\n {}".format(epoch, resnet18_ft.conv1.weight[0, 0, ...]))

    scheduler.step()  # 更新学习率

    # validate the model
    if (epoch+1) % val_interval == 0:

        correct_val = 0.
        total_val = 0.
        loss_val = 0.
        resnet18_ft.eval()
        with torch.no_grad():
            for j, data in enumerate(valid_loader):
                inputs, labels = data
                inputs, labels = inputs.to(device), labels.to(device)

                outputs = resnet18_ft(inputs)
                loss = criterion(outputs, labels)

                _, predicted = torch.max(outputs.data, 1)
                total_val += labels.size(0)
                correct_val += (predicted == labels).squeeze().cpu().sum().numpy()

                loss_val += loss.item()

            loss_val_mean = loss_val/len(valid_loader)
            valid_curve.append(loss_val_mean)
            print("Valid:\t Epoch[{:0>3}/{:0>3}] Iteration[{:0>3}/{:0>3}] Loss: {:.4f} Acc:{:.2%}".format(
                epoch, MAX_EPOCH, j+1, len(valid_loader), loss_val_mean, correct_val / total_val))

train_x = range(len(train_curve))
train_y = train_curve

train_iters = len(train_loader)
valid_x = np.arange(1, len(valid_curve)+1) * train_iters*val_interval # 由于valid中记录的是epochloss,需要对记录点进行转换到iterations
valid_y = valid_curve

plt.plot(train_x, train_y, label='Train')
plt.plot(valid_x, valid_y, label='Valid')

plt.legend(loc='upper right')
plt.ylabel('loss value')
plt.xlabel('Iteration')
plt.show()

输出:

use device :cuda
Training:Epoch[000/025] Iteration[010/016] Loss: 0.7606 Acc:50.00%
Valid:	 Epoch[000/025] Iteration[010/010] Loss: 0.7346 Acc:45.75%
Training:Epoch[001/025] Iteration[010/016] Loss: 0.7407 Acc:47.50%
Valid:	 Epoch[001/025] Iteration[010/010] Loss: 0.7113 Acc:46.41%
Training:Epoch[002/025] Iteration[010/016] Loss: 0.7006 Acc:53.12%
Valid:	 Epoch[002/025] Iteration[010/010] Loss: 0.6760 Acc:60.13%
Training:Epoch[003/025] Iteration[010/016] Loss: 0.7177 Acc:47.50%
Valid:	 Epoch[003/025] Iteration[010/010] Loss: 0.7280 Acc:54.90%
Training:Epoch[004/025] Iteration[010/016] Loss: 0.7200 Acc:48.12%
Valid:	 Epoch[004/025] Iteration[010/010] Loss: 0.6659 Acc:61.44%
Training:Epoch[005/025] Iteration[010/016] Loss: 0.7629 Acc:53.12%
Valid:	 Epoch[005/025] Iteration[010/010] Loss: 0.6694 Acc:63.40%
Training:Epoch[006/025] Iteration[010/016] Loss: 0.6931 Acc:56.25%
Valid:	 Epoch[006/025] Iteration[010/010] Loss: 0.7751 Acc:54.90%
Training:Epoch[007/025] Iteration[010/016] Loss: 0.7033 Acc:54.37%
Valid:	 Epoch[007/025] Iteration[010/010] Loss: 0.6611 Acc:60.78%
Training:Epoch[008/025] Iteration[010/016] Loss: 0.6637 Acc:60.62%
Valid:	 Epoch[008/025] Iteration[010/010] Loss: 0.6633 Acc:58.17%
Training:Epoch[009/025] Iteration[010/016] Loss: 0.6678 Acc:58.13%
Valid:	 Epoch[009/025] Iteration[010/010] Loss: 0.6611 Acc:63.40%
Training:Epoch[010/025] Iteration[010/016] Loss: 0.6537 Acc:63.12%
Valid:	 Epoch[010/025] Iteration[010/010] Loss: 0.6634 Acc:58.82%
Training:Epoch[011/025] Iteration[010/016] Loss: 0.6653 Acc:60.00%
Valid:	 Epoch[011/025] Iteration[010/010] Loss: 0.6626 Acc:59.48%
Training:Epoch[012/025] Iteration[010/016] Loss: 0.6718 Acc:58.13%
Valid:	 Epoch[012/025] Iteration[010/010] Loss: 0.6600 Acc:62.09%
Training:Epoch[013/025] Iteration[010/016] Loss: 0.6632 Acc:59.38%
Valid:	 Epoch[013/025] Iteration[010/010] Loss: 0.6611 Acc:61.44%
Training:Epoch[014/025] Iteration[010/016] Loss: 0.6569 Acc:60.00%
Valid:	 Epoch[014/025] Iteration[010/010] Loss: 0.6595 Acc:62.75%
Training:Epoch[015/025] Iteration[010/016] Loss: 0.6483 Acc:60.00%
Valid:	 Epoch[015/025] Iteration[010/010] Loss: 0.6608 Acc:60.78%
Training:Epoch[016/025] Iteration[010/016] Loss: 0.6516 Acc:63.12%
Valid:	 Epoch[016/025] Iteration[010/010] Loss: 0.6614 Acc:60.78%
Training:Epoch[017/025] Iteration[010/016] Loss: 0.6514 Acc:63.75%
Valid:	 Epoch[017/025] Iteration[010/010] Loss: 0.6614 Acc:60.78%
Training:Epoch[018/025] Iteration[010/016] Loss: 0.6640 Acc:60.00%
Valid:	 Epoch[018/025] Iteration[010/010] Loss: 0.6612 Acc:58.17%
Training:Epoch[019/025] Iteration[010/016] Loss: 0.6438 Acc:65.62%
Valid:	 Epoch[019/025] Iteration[010/010] Loss: 0.6604 Acc:61.44%
Training:Epoch[020/025] Iteration[010/016] Loss: 0.6479 Acc:64.38%
Valid:	 Epoch[020/025] Iteration[010/010] Loss: 0.6614 Acc:59.48%
Training:Epoch[021/025] Iteration[010/016] Loss: 0.6624 Acc:57.50%
Valid:	 Epoch[021/025] Iteration[010/010] Loss: 0.6618 Acc:61.44%
Training:Epoch[022/025] Iteration[010/016] Loss: 0.6800 Acc:58.13%
Valid:	 Epoch[022/025] Iteration[010/010] Loss: 0.6622 Acc:60.13%
Training:Epoch[023/025] Iteration[010/016] Loss: 0.6556 Acc:62.50%
Valid:	 Epoch[023/025] Iteration[010/010] Loss: 0.6610 Acc:58.82%
Training:Epoch[024/025] Iteration[010/016] Loss: 0.6757 Acc:57.50%
Valid:	 Epoch[024/025] Iteration[010/010] Loss: 0.6600 Acc:59.48%

在这里插入图片描述
效果不是很好,加载预训练模型:

# 2/3 加载参数
# flag = 0
flag = 1
if flag:
    path_pretrained_model = os.path.join(BASEDIR, "data", "finetune_resnet18-5c106cde.pth")
    if not os.path.exists(path_pretrained_model):
        raise Exception("\n{} 不存在,请下载 07-02-数据-模型finetune.zip\n放到 {}下,并解压即可".format(
            path_pretrained_model, os.path.dirname(path_pretrained_model)))
    state_dict_load = torch.load(path_pretrained_model)
    resnet18_ft.load_state_dict(state_dict_load)

输出:

use device :cuda
Training:Epoch[000/025] Iteration[010/016] Loss: 0.6880 Acc:59.38%
Valid:	 Epoch[000/025] Iteration[010/010] Loss: 0.3854 Acc:86.27%
Training:Epoch[001/025] Iteration[010/016] Loss: 0.3548 Acc:84.38%
Valid:	 Epoch[001/025] Iteration[010/010] Loss: 0.2308 Acc:93.46%
Training:Epoch[002/025] Iteration[010/016] Loss: 0.2293 Acc:88.12%
Valid:	 Epoch[002/025] Iteration[010/010] Loss: 0.2060 Acc:94.12%
Training:Epoch[003/025] Iteration[010/016] Loss: 0.1986 Acc:93.12%
Valid:	 Epoch[003/025] Iteration[010/010] Loss: 0.1973 Acc:94.12%
Training:Epoch[004/025] Iteration[010/016] Loss: 0.1991 Acc:91.25%
Valid:	 Epoch[004/025] Iteration[010/010] Loss: 0.1902 Acc:94.12%
Training:Epoch[005/025] Iteration[010/016] Loss: 0.2084 Acc:91.88%
Valid:	 Epoch[005/025] Iteration[010/010] Loss: 0.1885 Acc:95.42%
Training:Epoch[006/025] Iteration[010/016] Loss: 0.1806 Acc:93.75%
Valid:	 Epoch[006/025] Iteration[010/010] Loss: 0.1872 Acc:94.77%
Training:Epoch[007/025] Iteration[010/016] Loss: 0.1127 Acc:95.62%
Valid:	 Epoch[007/025] Iteration[010/010] Loss: 0.1973 Acc:94.77%
Training:Epoch[008/025] Iteration[010/016] Loss: 0.1506 Acc:93.75%
Valid:	 Epoch[008/025] Iteration[010/010] Loss: 0.1857 Acc:94.77%
Training:Epoch[009/025] Iteration[010/016] Loss: 0.1268 Acc:92.50%
Valid:	 Epoch[009/025] Iteration[010/010] Loss: 0.1853 Acc:94.77%
Training:Epoch[010/025] Iteration[010/016] Loss: 0.1052 Acc:95.62%
Valid:	 Epoch[010/025] Iteration[010/010] Loss: 0.1876 Acc:94.77%
Training:Epoch[011/025] Iteration[010/016] Loss: 0.1736 Acc:93.12%
Valid:	 Epoch[011/025] Iteration[010/010] Loss: 0.1883 Acc:94.77%
Training:Epoch[012/025] Iteration[010/016] Loss: 0.0827 Acc:98.75%
Valid:	 Epoch[012/025] Iteration[010/010] Loss: 0.1888 Acc:94.77%
Training:Epoch[013/025] Iteration[010/016] Loss: 0.1625 Acc:96.25%
Valid:	 Epoch[013/025] Iteration[010/010] Loss: 0.1951 Acc:94.77%
Training:Epoch[014/025] Iteration[010/016] Loss: 0.1458 Acc:93.12%
Valid:	 Epoch[014/025] Iteration[010/010] Loss: 0.1956 Acc:94.77%
Training:Epoch[015/025] Iteration[010/016] Loss: 0.0784 Acc:98.12%
Valid:	 Epoch[015/025] Iteration[010/010] Loss: 0.1933 Acc:94.77%
Training:Epoch[016/025] Iteration[010/016] Loss: 0.1067 Acc:96.25%
Valid:	 Epoch[016/025] Iteration[010/010] Loss: 0.1902 Acc:94.77%
Training:Epoch[017/025] Iteration[010/016] Loss: 0.1345 Acc:94.38%
Valid:	 Epoch[017/025] Iteration[010/010] Loss: 0.1895 Acc:94.77%
Training:Epoch[018/025] Iteration[010/016] Loss: 0.1272 Acc:93.75%
Valid:	 Epoch[018/025] Iteration[010/010] Loss: 0.1878 Acc:94.77%
Training:Epoch[019/025] Iteration[010/016] Loss: 0.1504 Acc:95.00%
Valid:	 Epoch[019/025] Iteration[010/010] Loss: 0.1977 Acc:94.77%
Training:Epoch[020/025] Iteration[010/016] Loss: 0.1076 Acc:95.62%
Valid:	 Epoch[020/025] Iteration[010/010] Loss: 0.1911 Acc:94.77%
Training:Epoch[021/025] Iteration[010/016] Loss: 0.1230 Acc:95.62%
Valid:	 Epoch[021/025] Iteration[010/010] Loss: 0.1963 Acc:94.77%
Training:Epoch[022/025] Iteration[010/016] Loss: 0.1330 Acc:94.38%
Valid:	 Epoch[022/025] Iteration[010/010] Loss: 0.1942 Acc:94.77%
Training:Epoch[023/025] Iteration[010/016] Loss: 0.0731 Acc:98.75%
Valid:	 Epoch[023/025] Iteration[010/010] Loss: 0.1906 Acc:94.77%
Training:Epoch[024/025] Iteration[010/016] Loss: 0.1502 Acc:94.38%
Valid:	 Epoch[024/025] Iteration[010/010] Loss: 0.1955 Acc:94.77%

在这里插入图片描述
可以看出准确率很快就达到了95%

下面测试冻结卷积层:

# 法1 : 冻结卷积层
# flag_m1 = 0
flag_m1 = 1
if flag_m1:
    for param in resnet18_ft.parameters():
        param.requires_grad = False
    print("conv1.weights[0, 0, ...]:\n {}".format(resnet18_ft.conv1.weight[0, 0, ...]))

输出:

use device :cuda
conv1.weights[0, 0, ...]:
 tensor([[-0.0104, -0.0061, -0.0018,  0.0748,  0.0566,  0.0171, -0.0127],
        [ 0.0111,  0.0095, -0.1099, -0.2805, -0.2712, -0.1291,  0.0037],
        [-0.0069,  0.0591,  0.2955,  0.5872,  0.5197,  0.2563,  0.0636],
        [ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006,  0.0576],
        [-0.0275,  0.0160,  0.0726, -0.0541, -0.3328, -0.4206, -0.2578],
        [ 0.0306,  0.0410,  0.0628,  0.2390,  0.4138,  0.3936,  0.1661],
        [-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]])
Training:Epoch[000/025] Iteration[010/016] Loss: 0.7759 Acc:45.62%
epoch:0 conv1.weights[0, 0, ...] :
 tensor([[-0.0104, -0.0061, -0.0018,  0.0748,  0.0566,  0.0171, -0.0127],
        [ 0.0111,  0.0095, -0.1099, -0.2805, -0.2712, -0.1291,  0.0037],
        [-0.0069,  0.0591,  0.2955,  0.5872,  0.5197,  0.2563,  0.0636],
        [ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006,  0.0576],
        [-0.0275,  0.0160,  0.0726, -0.0541, -0.3328, -0.4206, -0.2578],
        [ 0.0306,  0.0410,  0.0628,  0.2390,  0.4138,  0.3936,  0.1661],
        [-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],
       device='cuda:0')
Valid:   Epoch[000/025] Iteration[010/010] Loss: 0.4140 Acc:84.31%
Training:Epoch[001/025] Iteration[010/016] Loss: 0.4420 Acc:80.00%
epoch:1 conv1.weights[0, 0, ...] :
 tensor([[-0.0104, -0.0061, -0.0018,  0.0748,  0.0566,  0.0171, -0.0127],
        [ 0.0111,  0.0095, -0.1099, -0.2805, -0.2712, -0.1291,  0.0037],
        [-0.0069,  0.0591,  0.2955,  0.5872,  0.5197,  0.2563,  0.0636],
        [ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006,  0.0576],
        [-0.0275,  0.0160,  0.0726, -0.0541, -0.3328, -0.4206, -0.2578],
        [ 0.0306,  0.0410,  0.0628,  0.2390,  0.4138,  0.3936,  0.1661],
        [-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],
       device='cuda:0')
Valid:   Epoch[001/025] Iteration[010/010] Loss: 0.2643 Acc:90.85%
Training:Epoch[002/025] Iteration[010/016] Loss: 0.3811 Acc:80.62%
epoch:2 conv1.weights[0, 0, ...] :
 tensor([[-0.0104, -0.0061, -0.0018,  0.0748,  0.0566,  0.0171, -0.0127],
        [ 0.0111,  0.0095, -0.1099, -0.2805, -0.2712, -0.1291,  0.0037],
        [-0.0069,  0.0591,  0.2955,  0.5872,  0.5197,  0.2563,  0.0636],
        [ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006,  0.0576],
        [-0.0275,  0.0160,  0.0726, -0.0541, -0.3328, -0.4206, -0.2578],
        [ 0.0306,  0.0410,  0.0628,  0.2390,  0.4138,  0.3936,  0.1661],
        [-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],
       device='cuda:0')
Valid:   Epoch[002/025] Iteration[010/010] Loss: 0.2335 Acc:91.50%
Training:Epoch[003/025] Iteration[010/016] Loss: 0.2952 Acc:86.25%
epoch:3 conv1.weights[0, 0, ...] :
 tensor([[-0.0104, -0.0061, -0.0018,  0.0748,  0.0566,  0.0171, -0.0127],
        [ 0.0111,  0.0095, -0.1099, -0.2805, -0.2712, -0.1291,  0.0037],
        [-0.0069,  0.0591,  0.2955,  0.5872,  0.5197,  0.2563,  0.0636],
        [ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006,  0.0576],
        [-0.0275,  0.0160,  0.0726, -0.0541, -0.3328, -0.4206, -0.2578],
        [ 0.0306,  0.0410,  0.0628,  0.2390,  0.4138,  0.3936,  0.1661],
        [-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],
       device='cuda:0')
Valid:   Epoch[003/025] Iteration[010/010] Loss: 0.2113 Acc:92.16%
Training:Epoch[004/025] Iteration[010/016] Loss: 0.4194 Acc:83.75%
......

发现卷积核参数没有改变

设置conv 小学习率,这里设置学习率为0:

# ============================ step 4/5 优化器 ============================
# 法2 : conv 小学习率
# flag = 0
flag = 1
if flag:
    fc_params_id = list(map(id, resnet18_ft.fc.parameters()))     # 返回的是parameters的 内存地址
    base_params = filter(lambda p: id(p) not in fc_params_id, resnet18_ft.parameters())
    optimizer = optim.SGD([
        {'params': base_params, 'lr': LR*0},   # 0
        {'params': resnet18_ft.fc.parameters(), 'lr': LR}], momentum=0.9)

else:
    optimizer = optim.SGD(resnet18_ft.parameters(), lr=LR, momentum=0.9)               # 选择优化器

scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=lr_decay_step, gamma=0.1) 

输出:

use device :cuda
conv1.weights[0, 0, ...]:
 tensor([[-0.0104, -0.0061, -0.0018,  0.0748,  0.0566,  0.0171, -0.0127],
        [ 0.0111,  0.0095, -0.1099, -0.2805, -0.2712, -0.1291,  0.0037],
        [-0.0069,  0.0591,  0.2955,  0.5872,  0.5197,  0.2563,  0.0636],
        [ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006,  0.0576],
        [-0.0275,  0.0160,  0.0726, -0.0541, -0.3328, -0.4206, -0.2578],
        [ 0.0306,  0.0410,  0.0628,  0.2390,  0.4138,  0.3936,  0.1661],
        [-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]])
Training:Epoch[000/025] Iteration[010/016] Loss: 0.7759 Acc:45.62%
epoch:0 conv1.weights[0, 0, ...] :
 tensor([[-0.0104, -0.0061, -0.0018,  0.0748,  0.0566,  0.0171, -0.0127],
        [ 0.0111,  0.0095, -0.1099, -0.2805, -0.2712, -0.1291,  0.0037],
        [-0.0069,  0.0591,  0.2955,  0.5872,  0.5197,  0.2563,  0.0636],
        [ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006,  0.0576],
        [-0.0275,  0.0160,  0.0726, -0.0541, -0.3328, -0.4206, -0.2578],
        [ 0.0306,  0.0410,  0.0628,  0.2390,  0.4138,  0.3936,  0.1661],
        [-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],
       device='cuda:0')
Valid:   Epoch[000/025] Iteration[010/010] Loss: 0.4140 Acc:84.31%
Training:Epoch[001/025] Iteration[010/016] Loss: 0.4420 Acc:80.00%
epoch:1 conv1.weights[0, 0, ...] :
 tensor([[-0.0104, -0.0061, -0.0018,  0.0748,  0.0566,  0.0171, -0.0127],
        [ 0.0111,  0.0095, -0.1099, -0.2805, -0.2712, -0.1291,  0.0037],
        [-0.0069,  0.0591,  0.2955,  0.5872,  0.5197,  0.2563,  0.0636],
        [ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006,  0.0576],
        [-0.0275,  0.0160,  0.0726, -0.0541, -0.3328, -0.4206, -0.2578],
        [ 0.0306,  0.0410,  0.0628,  0.2390,  0.4138,  0.3936,  0.1661],
        [-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],
       device='cuda:0')
Valid:   Epoch[001/025] Iteration[010/010] Loss: 0.2643 Acc:90.85%
Training:Epoch[002/025] Iteration[010/016] Loss: 0.3811 Acc:80.62%
epoch:2 conv1.weights[0, 0, ...] :
 tensor([[-0.0104, -0.0061, -0.0018,  0.0748,  0.0566,  0.0171, -0.0127],
        [ 0.0111,  0.0095, -0.1099, -0.2805, -0.2712, -0.1291,  0.0037],
        [-0.0069,  0.0591,  0.2955,  0.5872,  0.5197,  0.2563,  0.0636],
        [ 0.0305, -0.0670, -0.2984, -0.4387, -0.2709, -0.0006,  0.0576],
        [-0.0275,  0.0160,  0.0726, -0.0541, -0.3328, -0.4206, -0.2578],
        [ 0.0306,  0.0410,  0.0628,  0.2390,  0.4138,  0.3936,  0.1661],
        [-0.0137, -0.0037, -0.0241, -0.0659, -0.1507, -0.0822, -0.0058]],
       device='cuda:0')
Valid:   Epoch[002/025] Iteration[010/010] Loss: 0.2335 Acc:91.50%
Training:Epoch[003/025] Iteration[010/016] Loss: 0.2952 Acc:86.25%

在这里插入图片描述
可以看到,卷积层的参数没有发生变化。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值