zoukankan      html  css  js  c++  java
  • 4 pytorch基础

    书《深度学习之PyTorch实战计算机视觉》第六章

    这次主要记录三部分内容:

    自动梯度

    • 向后传播自动化

    自定义传播函数

    • 重写向前传播和向后传播

    模型搭建和参数优化


    自动梯度

    实现对模型中后向传播梯度的自动计算,后向传播自动化(loss.backward)

    torch.autograd实现后向传播中的链式求导

    Variable类对我们定义的Tensor数据类型进行封装。用X代表我们选中的节点,是一个Variable对象,那么X.data代表Tensor数据类型的变量,X.grad是Variable类型的变量,想要访问梯度值需要使用X.grad.data

    loss.backward()是后向传播计算部分,自动计算每个节点的梯度并根据需求进行保留

    import torch
    from torch.autograd import Variable
    batch_n = 100
    hidden_layer = 100
    input_data = 1000
    output_data = 10
    
    x = Variable(torch.randn(batch_n, input_data), requires_grad = False)
    y = Variable(torch.randn(batch_n, output_data), requires_grad = False)
    
    w1 = Variable(torch.randn(input_data, hidden_layer), requires_grad = True) #权重1是1000*100
    w2 = Variable(torch.randn(hidden_layer, output_data), requires_grad = True)#权重2是100*10
    
    epoch_n = 20
    learning_rate = le-6
    
    for epoch in range(epoch_n):
        y_pred = x.mm(w1).clamp(min=0).mm(w2)
        loss = (y_pred-y).pow(2).sum()
        print("Epoch:{}, Loss:{:.4f}".format(epoch, loss.data[0]))
    
        loss.backward()
    
        w1.data -=learning_rate*w1.grad.data
        w2.data -=learning_rate*w2.grad.data
        
        w1.grad.data.zero_()
        w2.grad.data.zero_()

    自定义传播函数

    torch.nn.Module重写前向传播forward和后向传播backward

    import torch
    from torch.autograd import Variable
    batch_n = 100
    hidden_layer = 100
    input_data = 1000
    output_data = 10
    
    '''相比于前面代码添加部分'''
    class Model(torch.nn.module):
        def __init__(self):
            super(Module, self).__init__()
    
        def forward(self, input, w1, w2):  #实现向前传播矩阵运算
            x = torch.mm(x, w1)
            x = torch.clamp(x, min=0)
            x = torch.mm(x, w2)
            return x
    
        def backward(self):      #实现向后传播自动梯度计算
            pass
    
    model = Model()
    
    '''
    上面模型搭建好了,下面对模型进行训练和参数优化
    '''
    
    x = Variable(torch.randn(batch_n, input_data), requires_grad = False)
    y = Variable(torch.randn(batch_n, output_data), requires_grad = False)
    
    w1 = Variable(torch.randn(input_data, hidden_layer), requires_grad = True)
    w2 = Variable(torch.randn(hidden_layer, output_data), requires_grad = True)
    
    epoch_n = 20
    learning_rate = le-6
    
    for epoch in range(epoch_n):
        y_pred = model(x, w1, w2)   #有改动,原来是x.mm(w1).clamp(min=0).mm(w2)
        loss = (y_pred-y).pow(2).sum()
        print("Epoch:{}, Loss:{:.4f}".format(epoch, loss.data[0]))
    
        loss.backward()
    
        w1.data -=learning_rate*w1.grad.data
        w2.data -=learning_rate*w2.grad.data
    
        w1.grad.data.zero_()
        w2.grad.data.zero_()

    模型搭建和参数优化

     torch.nn包

    • torch.nn.Sequential

      序列容器,通过嵌套各种类,实现对网络模型的搭建,参数会按照我们定义好的序列自动传递下去

    • torch.nn.Linear

      线性层。参数有三个,分别是输入特征数,输出特征数和是否使用偏置,偏置参数是一个布尔值,默认为True,即使用偏置。

    • torch.nn.ReLU

      非线性激活函数,在定义时默认不需要传入参数。除此之外,还包括PReLU,LeakyReLU,Tanh,Sigmod,Softmax等。

    • 损失函数

      包括:

    (1)torch.nn.MSELoss:使用均方误差函数计算损失值

      

       (2)torch.nn.L1Loss:使用平均绝对误差计算损失值

      

       (3)torch.nn.CrossEntropyLoss:计算交叉熵

      信息量:它是用来衡量一个事件的不确定性的;一个事件发生的概率越大,不确定性越小,则它所携带的信息量就越小。:它是用来衡量一个系统的混乱程度的,代表一个系统中信息量的总和;信息量总和越大,表明这个系统不确定性就越大交叉熵:它主要刻画的是实际输出(概率)与期望输出(概率)的距离,也就是交叉熵的值越小,两个概率分布就越接近。假设概率分布p为期望输出,概率分布q为实际输出, [公式] 为交叉熵,则

    [公式]

    但是Pytorch中计算的交叉熵并不是采用上式,而是下面这个

    [公式]   

    torch.optim包

    实现神经网络权重参数优化更新自动化。该包提供了许多方法,SGD,AdaGrad,RMSProp,Adam等。

    接下来使用自动化的优化函数对前面的代码进行替换

    import torch
    from torch.autograd import Variable
    #设置参数
    batch_n = 100
    hidden_layer = 100
    input_data = 1000
    output_data = 10
    
    x = Variable(torch.randn(batch_n, input_data), requires_grad = False)
    y = Variable(torch.randn(batch_n, output_data), requires_grad = False)
    
    #构建模型
    models = torch.nn.Sequential(
        torch.nn.Linear(input_data, hidden_layer),
        torch.nn.ReLU(),
        torch.nn.Linear(hidden_layer, output_data)
    )
    #设置超参数
    epoch_n = 20
    learning_rate = le-6
    #定义损失函数和权重优化参数
    loss_fn = torch.nn.MSELoss()
    optimzer = torch.optim.Adam(models.parameters(), lr = learning_rate)
    
    for epoch in range(epoch_n):
        y_pred = models(x) 
        loss = loss_fn(y_pred, y) #有改动 loss = (y_pred-y).pow(2).sum()
        print("Epoch:{}, Loss:{:.4f}".format(epoch, loss.data[0]))
    
        optimer.zero_grad() #实现模型参数梯度归零,代替前面w1.grad.data.zero_()和w2
        loss.backward()
        optimer.step()  #实现梯度更新,代替前面w1.data -=learning_rate*w1.grad.data和w2

    这一部分就记录到这里。

  • 相关阅读:
    SQL 的单引号转义字符
    Oracle中row_number()、rank()、dense_rank() 的区别
    Hibernate之mappedBy与@JoinColumn
    spring定时任务的注解实现方式
    springmvc常用注解之@Controller和@RequestMapping
    out.print()与out.write()的区别
    idea 中 找不到程序包 的坑
    Thymeleaf学习
    unknow command 'iscan',使用redis desktop manager 无法读取redis存储的数据
    Struts2框架简单介绍
  • 原文地址:https://www.cnblogs.com/loyolh/p/13477019.html
Copyright © 2011-2022 走看看