毕业设计周记4

Pytorch总结

目录

Pytorch总结

PyTorch的概述

Pytorch基础

Tensor

Autograd模块

Optim模块

神经网络模块

Torchvision模块

 Pytorch小实战

图像分类

使用torchvision加载并且归一化CIFAR10的训练和测试数据集

定义一个卷积神经网络和损失函数

在训练样本数据上训练网络

在测试样本数据上测试网络

迁移学习

微调Convnet

将Convnet看成固定的特征提取器


PyTorch的概述

PyTorch是一个基于Torch的Python开源机器学习库,用来提供一个具有灵活性的深度学习开发平台。它主要由Facebookd的人工智能小组开发,不仅能够实现强大的GPU加速,同时还支持动态神经网络,这一点是现在很多主流框架如TensorFlow都不支持的。 PyTorch提供了两个高级功能: 具有强大的GPU加速的张量计算(如Numpy);包含自动求导系统的深度神经网络。

Pytorch基础

PyTorch有抽象的三个层次:Tensor: 张量,类似ndarray,可在GPU上运行 。Variable:计算图中的节点;存储数据和渐变 。Module:神经网络层,可以存储状态或可学习的权重。

Tensor

Tensors 类似于 NumPy 的 ndarrays ,Tensors 可以使用 GPU 进行计算。

#导入 Pytorch
import torch
#随机初始化的矩阵
a = torch.rand(5, 3)

同时Tensor和numpy.array之间也可以相互转换。

#紧接上面代码
#导入Numpy
import numpy as np
#numpy 和 tensor相互转换
b = a.numpy()
c = np.array([1,2,3],[2,4,5])
d = torch.from_numpy(c)

与numpy一样,科学计算库非常重要的一点是能够实现高效的数学功能。

import torch
a = torch.rand(3,3)
a.t()#转置
a.pow(2)#四则运算都行

Autograd模块

Autograd 包是 PyTorch 中所有神经网络的核心。该 Autograd 软件包为 Tensors 上的所有操作提供自动微分。自动微分操作又另外一个基本元素提供,Variable:

本质上Variable和Tensor没有区别,不过Variabel会放入一个计算图,然后进行前向传播,反向传播以及自动求导一个Variable里面包含着三个属性,data,grad和creator,其中creator表示得到这个Variabel的操作,比如乘法或者加法等等,grad表示方向传播的梯度,data表示取出这个Variabel里面的数据。

#导入 pytorch的自动求导工具包在torch.autograd中
from torch.autograd import Variable
import torch
x = Variable(torch.rand(5),requires_grad = True)
y = x*2
grads = torch.FloatTensor([1,2,3,4,5])
y.backward(grads)
print(x.grad)#输出 tensor([ 2.,  4.,  6.,  8., 10.])

Variable和tensor的区别和联系:Variable是篮子,而tensor是鸡蛋,鸡蛋应该放在篮子里才能方便拿走(定义variable时第一个参数就是tensor)。Variable这个篮子里除了装了tensor外还有requires_grad参数,表示是否需要对其求导,默认为False。Variable这个篮子呢,自身有一些属性:比如grad,梯度variable.grad是d(y)/d(variable)保存的是变量y对variable变量的梯度值,如果requires_grad参数为False,所以variable.grad返回值为None,如果为True,返回值就为对variable的梯度值;比如grad_fn,对于用户自己创建的变量(Variable()),grad_fn是为none的,也就是不能调用backward函数,但对于由计算生成的变量,如果存在一个生成中间变量的requires_grad为true,那其的grad_fn不为none,反则为none;比如data,这个就很简单,这个属性就是装的鸡蛋(tensor) 。

Autograd可以根据用户对Variable的操作来构建其计算图。对于Varialbe的属性和方法,requires_grad:variable默认是不需要被求导的,即requires_grad属性默认为False,如果某一个节点的requires_grad为True,那么所有依赖它的节点requires_grad都为True。volatile:variable的volatile属性默认为False,如果某一个variable的volatile属性被设为True,那么所有依赖它的节点volatile属性都为True。volatile属性为True的节点不会求导,volatile的优先级比requires_grad高。retain_graph:多次反向传播(多层监督)时,梯度是累加的。一般来说,单次反向传播后,计算图会free掉,也就是反向传播的中间缓存会被清空(这就是动态度的特点)。为进行多次反向传播需指定retain_graph=True来保存这些缓存。.backward()反向传播,求解Variable的梯度,放在中间缓存中。

Optim模块

Torch.optim是一个实现各种优化算法的模块,用于构建神经网络。它支持大多数常用的方法,因此我们不必从头开始构建它们。下面是使用Adam优化器的代码:

optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

神经网络模块

神经网络可以通过 torch.nn 包来构建。使用torch.nn包中的工具来构建神经网络 需要以下几步:定义神经网络的权重,搭建网络结构;遍历整个数据集进行训练;将数据输入神经网络;计算loss;计算网络权重的梯度;更新网络权重,典型的用一个简单的更新方法:weight = weight - learning_rate *gradient。

先看看仅用Tensor实现的神经网络: 

'''Tensors 操作 '''
import torch
dtype = torch.FloatTensor #GPU:torch.cuda.FloatTensor
N,D_in,H,D_out = 64,1000,100,10
x = torch.randn(N,D_in).type(dtype)
y = torch.randn(N,D_out).type(dtype)
w1 = torch.randn(D_in,H).type(dtype)
w2 = torch.randn(H,D_out).type(dtype)
lr = 1e-6 #学习率

for t in range(500):
    #前向传递:计算预测和损失
    h = x.mm(w1) #xh权重
    h_relu = h.clamp(min=0) #relu激活函数
    y_pred = h_relu.mm(w2)#hy权重
    loss = (y_pred - y ).pow(2).sum()#损失函数L2
    #反动传递:手动计算梯度
    grad_y_pred  =2.0 *(y_pred - y)#损失求导
    grad_w2 = h_relu.t().mm(grad_y_pred)
    grad_h_relu = grad_y_pred.mm(w2.t())
    grad_h = grad_h_relu.clone() #clone 和copy
    grad_h[h<0] = 0
    grad_w1 = x.t().mm(grad_h)
    #计算权重的梯度
    w1 -= lr * grad_w1
    w2 -= lr * grad_w2

使用Variable的自动求导后实现的:

import torch
from torch.autograd import Variable
"""from … import 语句  让你从模块中导入一个指定的部分到当前命名空间"""
""" 使用导入的项目名即可"""
class ReLU(torch.autograd.Function): 
'''New Autograd Functions'''
    def forward(self,x):
        self.save_for_backward(x)
         return x.clamp(min=0)
    def backward(self,grad_y):
        x, = self.saved_tensors
        grad_input = grad_y.clone()
        grad_input[x<0] = 0
        return grad_input
'''Autograd'''
N,D_in,H,D_out = 64,1000,100,10

x = Variable(torch.randn(N,D_in),requires_grad=False)
y = Variable(torch.randn(N,D_out),requires_grad=False)#我们不希望有关数据的渐变(损失)
w1 = Variable(torch.randn(D_in,H),requires_grad=True)#想要权重的梯度
w2 = Variable(torch.randn(H,D_out),requires_grad=True)

lr = 1e-6
for t in range(500):
    relu = ReLU()
    j = j + 1
    y_pred = relu.forward(x.mm(w1)).mm(w2)#自己创建的激活函数
    # y_pred = x.mm(w1).clamp(min=0).mm(w2)
    loss = (y_pred - y).pow(2).sum() #求损失
    if w1.grad:#计算相对于w1和w2的损失梯度(首先为零)
        w1.grad.data.zero_()
    if w2.grad:
        w2.grad.data.zero_()#在grad更新时,每一次运算后都需要将上一次的梯度记录清空
    loss.backward()#计算梯度
    w1.data -= lr * w1.grad.data #更新
    w2.data -= lr * w2.grad.data

 基于torch.nn 包来构建Module实现神经网络的:

'''pytorch nn
    用于神经网络的高级包装
'''
import torch
from torch.autograd import Variable

N,D_in,H,D_out = 64,1000,100,10
x = Variable(torch.randn(N,D_in))
y = Variable(torch.randn(N,D_out),requires_grad= False)

model = torch.nn.Sequential(
        torch.nn.Linear(D_in,H),
        torch.nn.ReLU(),
        torch.nn.Linear(H,D_out)
)
'''
将我们的模型定义为一系列层
nn还定义了常见的损失函数
'''
loss_fn = torch.nn.MSELoss(size_average=False)
#  A reduce = False,返回向量形式的 loss 
#  B reduce = True, 返回标量形式的loss
#    C  size_average = True,返回 loss.mean();
#   D  如果 size_average = False,返回 loss.sum()
#  默认情况下:两个参数都为True.
lr = 1e-4
'''
PyTorch: optim
'''
#对不同的更新规则使用优化器
optimizer = torch.optim.Adam(model.parameters(),lr = lr)

'''使用optim'''
for t in range(500):
    y_pred = model(x)
    loss = loss_fn(y_pred,y)

    optimizer.zero_grad() #区别 model.zero_grad()
    loss.backward()

    optimizer.step()#计算梯度后更新所有参数
'''
Pytorch DataLoaders
DataLoader包装数据集,并为您提供小型化,多线程
当您需要加载自定义数据时,只需编写自己的Dataset类
'''
import torch
from torch.autograd import Variable
from torch.utils.data import TensorDataset,DataLoader

'''
基于nn
Define New Modules
PyTorch模块是一个神经网络层; 它输入和输出变量
模块可以包含权重(作为变量)或其他模块
您可以使用自动格式定义自己的模块!
'''
class TwoLayerNet(torch.nn.Module):
    '''将我们的整个模型定义为单个模块'''
    def __init__(self,D_in,D_out,H):
        '''初始化器设置两个子项(模块可以包含模块'''
        super(TwoLayerNet,self).__init__()
        self.linear1 = torch.nn.Linear(D_in,H)
        self.linear2 = torch.nn.Linear(H,D_out)

    def forward(self):
        '''使用子模块定义转发,并在变量上自动格式化操作无需定义向后 - 自动调整将处理它'''
        h_relu = self.linear1(x).clamp(min = 0)
        y_pred = self.linear2(h_relu)
        return y_pred

N,D_in,H,D_out = 64,1000,100,10
x = torch.randn(N,D_in)
y = torch.randn(N,D_out)

loader = DataLoader(TensorDataset(x,y),batch_size= 8)

'''构建和训练我们的模型实例'''
module1 = TwoLayerNet(D_in,D_out,H)
loss_fn = torch.nn.MSELoss(size_average=False)
optimizer = torch.optim.SGD(module1.parameters(),lr=1e-4)

for epoch in range(10):
    for x_batch, y_batch in loader:
        """在装载机上迭代形成小批量
            装载机给定标,所以你需要包装变量
        """
        x_var,y_var = Variable(x),Variable(y)
        y_pred = module1(x)
        loss = loss_fn(y_pred,y)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

Torchvision模块

Torchvision包服务于PyTorch框架,包括了计算机视觉中一些流行的数据集、网络模型以及常见的图片变换方法,主要由以下几部分构成:torchvision.datasets: 一些加载数据的函数和常用的数据集接口;torchvision.models:包含常用的模型结构(含预训练模型);torchvision.transforms:常见的图片变换,如裁剪、旋转等;torchvision.utils:其它一些有用的方法。

'''
Pytorch
预训练模型
'''
import torch
import torchvision
#PyTorch框架中torchvision模块下有:torchvision.datasets、torchvision.models、torchvision.transforms这3个子包。
'''此模块下有常用的 alexnet、densenet、inception、resnet、squeezenet、vgg(关于网络详情请查看)等常用的网络结构,
并且提供了预训练模型,我们可以通过简单调用来读取网络结构和预训练模型,同时使用fine tuning(微调)来使用。'''
alexnet = torchvision.models.alexnet(pretrained=True)
vgg16 = torchvision.models.vgg16(pretrained=True)
resnet101 = torchvision.models.resnet101(pretrained=True)

 Pytorch小实战

图像分类

使用torchvision加载并且归一化CIFAR10的训练和测试数据集

加载并归一化 CIFAR10 使用 torchvision。CIFAR10数据集,它包含十个类别:‘airplane’, ‘automobile’, ‘bird’, ‘cat’, ‘deer’, ‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’。CIFAR-10 中的图像尺寸为33232,也就是RGB的3层颜色通道,每层通道内的尺寸为32*32。torchvision 数据集的输出是范围在[0,1]之间的 PILImage,要转换成归一化范围为[-1,1]之间的张量 Tensors。

import torch
import torchvision
import torchvision.transforms as transforms
#
# #加载并归一化 CIFAR10 使用 torchvision ,用它来加载 CIFAR10 数据非常简单

transform = transforms.Compose(
    [transforms.ToTensor(),#range 0~1
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])#(channel-mean)/std  因为是RGB (x-0.5)/0.5 range -1~1

trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                        download=False, transform=transform)# 我是本地下载的数据集 不需要从网上再下载了
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
                                          shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                       download=False, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
                                         shuffle=False, num_workers=2)

classes = ('plane', 'car', 'bird', 'cat',
           'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
print("Initializing Datasets and Dataloaders...")

本地离线下载的数据集,需要在文件cifar.py 修改 url 成本地路径才行。

    base_folder = 'cifar-10-batches-py'
    # url = "https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz"
    url ="file:///D:/python_ducment/Python_Project/Pytorch/data/cifar-10-python.tar.gz" #修改为你自己的本地路径
    filename = "cifar-10-python.tar.gz"
    tgz_md5 = 'c58f30108f718f92721af3b95e74349a'
    train_list = [
        ['data_batch_1', 'c99cafc152244af753f735de768cd75f'],
        ['data_batch_2', 'd4bba439e000b95fd0a9bffe97cbabec'],
        ['data_batch_3', '54ebc095f3ab1f0389bbae665268c751'],
        ['data_batch_4', '634d18415352ddfa80567beed471001a'],
        ['data_batch_5', '482c414d41f54cd18b22e5b47cb7c3cb'],
    ]

定义一个卷积神经网络和损失函数

import torch.nn as nn
import torch.nn.functional as F


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


net = Net()

import torch.optim as optim
#定义一个损失函数和优化器 让我们使用分类交叉熵Cross-Entropy 作损失函数,动量SGD做优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

在训练样本数据上训练网络

数据迭代器上循环传给网络和优化器输入测试集数据。通过训练数据集对网络进行了2次训练。

for epoch in range(2):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # get the inputs
        inputs, labels = data

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

在测试样本数据上测试网络

将用神经网络的输出作为预测的类标来检查网络的预测性能,用样本的真实类标来校对。如果预测是正确的,将样本添加到正确预测的列表里。先展示图片

import matplotlib.pyplot as plt
import numpy as np

# functions to show an image
def imshow(img):
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))#顺序是0 12 对于的位置xyz
'''因为在plt.imshow在现实的时候输入的是(imagesize,imagesize,channels)imshow中,参数img的格式为(channels,imagesize,imagesize),这两者的格式不一致,我们需要调用一次np.transpose函数'''
    plt.show()

# get some random testing images
dataiter = iter(testloader)#iter() 函数用来生成迭代器。
images, labels = dataiter.next()

# show images
imshow(torchvision.utils.make_grid(images))
# print labels
print('GroundTruth:'+ ' '.join('%5s' % classes[labels[j]] for j in range(4)))
outputs = net(images)# 将测试集图片放入神经网络  这些样本应该预测成什么
_, predicted = torch.max(outputs, 1) #输出是预测与十个类的近似程度,与某一个类的近似程度越高,网络就越认为图像是属于这一类别。

print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))

看看网络在整个数据集上的表现

correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)#dim是max函数索引的维度0/1,0是每列的最大值,1是每行的最大值
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))

'''分类看准确率'''
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()#squeeze()函数将表示向量的数组转换为秩为1的数组
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()
            class_total[label] += 1


for i in range(10):
    print('Accuracy of %5s : %2d %%' % (
        classes[i], 100 * class_correct[i] / class_total[i]))

迁移学习

微调Convnet

使用预训练的网络来初始化自己的网络,而不是随机初始化。其他的训练步骤不变。    

  • 导入相关的包   

import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim import lr_scheduler
import numpy as np
import torchvision
from torchvision import datasets, models, transforms
import matplotlib.pyplot as plt
import time
import os
import copy

plt.ion()   # interactive mode
'''因为python可视化库matplotlib的显示模式默认为阻塞(block)模式。什么是阻塞模式那?
我的理解就是在plt.show()之后,程序会暂停到那儿,并不会继续执行下去。
如果需要继续执行程序,就要关闭图片。那如何展示动态图或多个窗口呢?
这就要使用plt.ion()这个函数,使matplotlib的显示模式转换为交互(interactive)模式。
即使在脚本中遇到plt.show(),代码还是会继续执行'''
  • 加载数据

训练一个模型来分类蚂蚁ants和蜜蜂bees。ants和bees各有约120张训练图片。每个类有75张验证图片。离线下载数据集,并解压到目录下。

#训练集数据扩充和归一化
#在验证集上仅需要归一化
data_transforms = {
    'train': transforms.Compose([
        transforms.RandomResizedCrop(224), #随机裁剪一个area然后再resize
        transforms.RandomHorizontalFlip(), #随机水平翻转
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
    'val': transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ]),
}

data_dir = 'data/hymenoptera_data'
image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x),
                                          data_transforms[x])
                  for x in ['train', 'val']}
dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4,
                                             shuffle=True, num_workers=4)
              for x in ['train', 'val']}
dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}
class_names = image_datasets['train'].classes

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
  • 可视化部分图像数据

可视化部分训练图像,以便了解数据扩充。

def imshow(inp, title=None):
    """Imshow for Tensor."""
    inp = inp.numpy().transpose((1, 2, 0))
    mean = np.array([0.485, 0.456, 0.406])
    std = np.array([0.229, 0.224, 0.225])
    inp = std * inp + mean # unnormalize
    inp = np.clip(inp, 0, 1) #截取数组中0~1的部分
    plt.imshow(inp)
    if title is not None:
        plt.title(title)
    plt.pause(0.001)  # pause a bit so that plots are updated


# 获取一批训练数据
inputs, classes = next(iter(dataloaders['train']))

# 批量制作网格
out = torchvision.utils.make_grid(inputs)

imshow(out, title=[class_names[x] for x in classes])
  • 训练模型

编写一个通用函数来训练模型:调整学习率;保存最优模型。

def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
    since = time.time()

    best_model_wts = copy.deepcopy(model.state_dict())#copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象
    best_acc = 0.0

    for epoch in range(num_epochs):
        print('Epoch {}/{}'.format(epoch, num_epochs - 1))
        print('-' * 10)

        # 每个epoch都有一个训练和验证阶段
        for phase in ['train', 'val']:
            if phase == 'train':
                #scheduler.step()
                model.train()  # Set model to training mode
            else:
                model.eval()   # Set model to evaluate mode

            running_loss = 0.0
            running_corrects = 0

            # 迭代数据.
            for inputs, labels in dataloaders[phase]:
                inputs = inputs.to(device)
                labels = labels.to(device)

                # 零参数梯度
                optimizer.zero_grad()

                # 前向
                # track history if only in train
                with torch.set_grad_enabled(phase == 'train'):
                    outputs = model(inputs)
                    _, preds = torch.max(outputs, 1)
                    loss = criterion(outputs, labels)

                    # 后向+仅在训练阶段进行优化
                    if phase == 'train':
                        loss.backward()
                        optimizer.step()

                # 统计
                running_loss += loss.item() * inputs.size(0)
                running_corrects += torch.sum(preds == labels.data)

            if phase == 'train':
                scheduler.step()

            epoch_loss = running_loss / dataset_sizes[phase]
            epoch_acc = running_corrects.double() / dataset_sizes[phase]

            print('{} Loss: {:.4f} Acc: {:.4f}'.format(
                phase, epoch_loss, epoch_acc))

            # 深度复制mo
            if phase == 'val' and epoch_acc > best_acc:
                best_acc = epoch_acc
                best_model_wts = copy.deepcopy(model.state_dict())


    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))

    # 加载最佳模型权重
    model.load_state_dict(best_model_wts)
    return model
  • 可视化模型的预测结果

展示部分预测图像的通用函数

#一个通用的展示少量预测图片的函数
def visualize_model(model, num_images=6):
    was_training = model.training
    model.eval()
    images_so_far = 0
    fig = plt.figure()

    with torch.no_grad():
        for i, (inputs, labels) in enumerate(dataloaders['val']):
            inputs = inputs.to(device)
            labels = labels.to(device)

            outputs = model(inputs)
            _, preds = torch.max(outputs, 1)

            for j in range(inputs.size()[0]):
                images_so_far += 1
                ax = plt.subplot(num_images//2, 2, images_so_far)
                ax.axis('off')
                ax.set_title('predicted: {}'.format(class_names[preds[j]]))
                imshow(inputs.cpu().data[j])

                if images_so_far == num_images:
                    model.train(mode=was_training)
                    return
        model.train(mode=was_training)
  •  训练和评估模型

加载预训练模型并重置最终完全连接的图层,训练和评估模型。

model_ft = models.resnet18(pretrained=False)
model_ft.load_state_dict(torch.load('D:/python_ducment/Python_Project/Pytorch/weight/resnet18-5c106cde.pth'))
num_ftrs = model_ft.fc.in_features
model_ft.fc = nn.Linear(num_ftrs, 2)

model_ft = model_ft.to(device)

criterion = nn.CrossEntropyLoss()

# 观察所有参数都正在优化
optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)

# 每7个epochs衰减LR通过设置gamma=0.1
exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)

model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler,
                       num_epochs=25)

# #模型评估效果可视化
visualize_model(model_ft)

plt.ioff()
plt.show()

Convnet看成固定的特征提取器

首先固定ConvNet除了最后的全连接层外的其他所有层。最后的全连接层被替换成一个新的随机 初始化的层,只有这个新的层会被训练[只有这层参数会在反向传播时更新]

前面与微调一样,只需要冻结除最后一层之外的所有网络。通过设置requires_grad == Falsebackward()来冻结参数,这样在反向传播backward()的时候他们的梯度就不会被计算。

model_ft = models.resnet18(pretrained=False)
model_ft.load_state_dict(torch.load('D:/python_ducment/Python_Project/Pytorch/weight/resnet18-5c106cde.pth'))

for param in model_conv.parameters():
    param.requires_grad = False

# Parameters of newly constructed modules have requires_grad=True by default
num_ftrs = model_conv.fc.in_features
model_conv.fc = nn.Linear(num_ftrs, 2)

model_conv = model_conv.to(device)

criterion = nn.CrossEntropyLoss()

# Observe that only parameters of final layer are being optimized as
# opposed to before.
optimizer_conv = optim.SGD(model_conv.fc.parameters(), lr=0.001, momentum=0.9)

# Decay LR by a factor of 0.1 every 7 epochs
exp_lr_scheduler = lr_scheduler.StepLR(optimizer_conv, step_size=7, gamma=0.1)

model_conv = train_model(model_conv, criterion, optimizer_conv,
                         exp_lr_scheduler, num_epochs=25)

visualize_model(model_conv)

plt.ioff()
plt.show()

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值