首页 > 其他分享 >深度学习-1218

深度学习-1218

时间:2024-12-20 08:58:24浏览次数:6  
标签:初始化 nn 1218 functional 学习 init 深度 True self

1.nn.functional

今天学nn中一个很常用的模块:nn.functional,nn中的大多数layer,在functional中都有一个对应的函数。

nn.functional中的函数和nn.Module的主要区别在于:

用nn.Module实现的layer是一个特殊的类,都是由calss layer(nn.Module)定义的,会自动提取可学习的参数。

用nn.functional中的函数更像是纯函数,由def function(input)定义,我们来看看functional的使用方法:

线性层

input = t.randn(2,3)
model = nn.Linear(3,4)
output = model(input)#Module
output2 = nn.functional.linear(input,model.weight,model.bias)#function
output == output2
->tensor([[True, True, True, True],
        [True, True, True, True]])

ReLU

b = nn.functional.relu(input)
b2 = nn.ReLU()(input)
b == b2
->tensor([[True, True, True],
        [True, True, True]])

那到底什么时候用nn.Module,什么适合用nn.functional呢?

其实很简单,如果模型内有可学习的参数,最好用nn.Module,其实两者在性能上没有太大差异,具体使用取决于个人的喜好

比如激活函数(ReLU,sigmoid,tanh),池化(MaxPool)等没有u儿媳参数的,可用functional函数代替,对于卷积、全连接等具有可学习参数的网络,使用nn.Module

注意虽然dropout操作也没有可学习的操作,但建议还是使用nn.Dropout,因为drpout在训练和测试两个阶段的行为有差别,使用nn.Module能通过model.eval操作加以区分

我们来看一下组合使用两种方法例子:

from torch.nn import functional as F
class Net(nn.Module):
    def __init__(self):
        super(net,self).__init__()#这步到底在干嘛?
        self.conv1 = nn.Conv2d(3,6,5)
        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 = F.pool(F.relu(self.conv1(x)),2)#2*2卷积和的最大池化
        x = F.poo(F.relu(self.conv2(x)),2)
        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

这个例子就是昨天学的Lenet网络

# 首先定义一个LeNet网络
class Net1(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.features = nn.Sequential(
                    nn.Conv2d(3, 6, 5),#1张图像,3个颜色通道,5*5卷积核
                    nn.ReLU(),#将负值变成0 ReLU
                    nn.MaxPool2d(2,2),#最大池化使用2*2的池化窗口,步幅为2   池化会在2*2的区域中选择内部的最大值
                    nn.Conv2d(6, 16, 5),
                    nn.ReLU(),
                    nn.MaxPool2d(2,2)
        )
        self.classifier = nn.Sequential(
            nn.Linear(16 * 5 * 5, 120),
            nn.ReLU(),
            nn.Linear(120, 84),
            nn.ReLU(),
            nn.Linear(84, 10)
        )

    def forward(self, x):
        x = self.features(x)
        x = x.view(-1, 16 * 5 * 5)
        x = self.classifier(x)
        return x

net = Net1()

只是在计算不可学习参数的层(激活层、池化层),将它们用函数代题,这样则可不用单独放置在构造函数__init__中,对于可学习参数的模块,也可用functional来代替,只是实现起来较为复杂,需要手动定义参乎上parameter,比如在实现自动逸的全连接时,需要将weight和bias两个参数单独拿出来,在构造函数中初始化为parameter

class MyLinear(nn.Module):
    def __init__(self):
        super(MyLinear, self).__init__()
        self.weight = nn.Parameter(t.randn(3, 4))
        self.bias = nn.Parameter(t.zeros(3))
    def forward(self):
        return F.linear(input, weight, bias)

2.初始化策略

在深度学习中,参数的初始化十分重要,良好的初始化能让模型更快收敛,并达到更高的水平。二糟糕的初始化会使得模型迅速瘫痪

pytorch中nn.Module的模块都采用了较合理的初始化策略,因此一般不用担心初始化问题

当然我们也可以自定义初始化去替换默认的初始化

注意,当我们使用Parameter时,自定义初始化尤为重要。因t.Tensor()返回的是内存中的随机数,很可能有极大值

这在实际训练网络中会造成溢出或梯度消失

pytorch中的nn.init模块就是专门为初始化为设计的:

#利用nn.init进行初始化
from torch.nn import init#常见的初始化权重共组 比如xavier_normal_, kaiming_normal_,或者 uniform_
linear = nn.Linear(3,4)#Linear会默认创建两个参数W(weight 权重矩阵) 和 B(偏置项)->weight形状[4,3],bias形状[4]
t.manual_seed(1)
init.xavier_normal_(linear.weight)#正态分布初始化weight 
->Parameter containing:
tensor([[ 0.3535,  0.1427,  0.0330],
        [ 0.3321, -0.2416, -0.0888],
        [-0.8140,  0.2040, -0.5493],
        [-0.3010, -0.4769, -0.0311]], requires_grad=True)

由于该层输入特征数是(3),输出特征数为(4)

根据正态分布:

std = (\frac{2}{inputsize+outsize})^{1/2}

计算权重矩阵[4,3]的标准差

我们也可以直接计算并替换权重:

# 直接初始化
import math
t.manual_seed(1)

# xavier初始化的计算公式
std = math.sqrt(2)/math.sqrt(7.)#计算了标准差,这里的2是计算的个数,sqrt则是3+4=7,输入和输出特征数的和
linear.weight.data.normal_(0,std)#这里直接用均值0和标准差std对linear的权重进行了替换
->tensor([[ 0.3535,  0.1427,  0.0330],
        [ 0.3321, -0.2416, -0.0888],
        [-0.8140,  0.2040, -0.5493],
        [-0.3010, -0.4769, -0.0311]])

两种方法初始的权重一致

进而,我们可以对所有参数进行初始化:


for name, params in net.named_parameters():
    if name.find('linear') != -1:
        # init linear
        params[0] # weight
        params[1] # bias
    elif name.find('conv') != -1:
        pass
    elif name.find('norm') != -1:
        pass

遍历模型中的所有参数,将'Linear','conv','norm'的函数层进行初始化

代码只对linear进行了修改,其他跳过

标签:初始化,nn,1218,functional,学习,init,深度,True,self
From: https://blog.csdn.net/m0_65881366/article/details/144569535

相关文章

  • 初步学习指针小作业
    一、初识指针的概念在C语言中,指针是一种变量,它存储的是另一个变量的内存地址。 就好像你有很多信箱(变量),每个信箱都有一个编号(内存地址)。指针就是一个小纸条,上面写着某个信箱的编号,通过这个编号就能找到对应的信箱。 例如,有一个变量 inta=10; ,可以定义一个指针变量......
  • LVGL学习 - Visual Studio外部“.c.h”文件添加
    一、首先把文件添加至工程,现有项选择所需添加的“.c.h”文件但还是会有如下报错,解决方法在第2步。二、“.c”文件需要添加“extern"C"”下图截至官方文档我试了只添加“extern"C"”,多个地方添加过还是不行,后面仿照LVGL官方代码,添加如下图,原报错搞定。点击查看代码#ifd......
  • 2024-2025-1 20241401 《计算机基础与程序设计》 第十三周学习总结
    班级链接2024计算机基础与程序设计作业要求第十三周作业教材学习内容总结《C语言程序设计》第12章结构体的定义和使用:结构体类型的定义,以及结构体变量的创建和使用。结构体允许将不同数据类型的成员组合成一个整体,以便于管理和引用。结构体变量的初始化:结构体......
  • CSS学习记录17
    CSS圆角通过CSSborder-radius属性,可以实现任何元素的“圆角”样式。CSSborder-radius属性用于定义元素角的半径。使用此属性可以为元素添加圆角。#rcorners1{border-radius:25px;background:#73AD21;padding:20px;width:200px;height:150px;}......
  • Cadence学习笔记 8 添加分页符
    基于Cadence17.4,四层板4路HDMI电路更多Cadence学习笔记:Cadence学习笔记1原理图库绘制Cadence学习笔记2PCB封装绘制Cadence学习笔记3MCU主控原理图绘制​Cadence学习笔记4单片机原理图绘制​Cadence学习笔记5四路HDMI原理图绘制Cadence学习笔记6-7电源_LED电路......
  • 深度学习笔记06-VGG16-Pytorch实现人脸识别
    本文通过调用预训练模型VGG16并进行模型微调,从而实现人脸识别。文章目录前言一、加载数据1.导入库2.导入数据3.定义transforms4.查看类别5.划分数据集6.加载数据二、调用VGG161.加载预训练模型2.模型微调三、训练模型1.训练函数2.测试函数3.动态学习率设......
  • C语言学习笔记
    目录一、为什么要学C1.1C的优点1.2C的缺点二、计算机基础2.1字节2.2进制三、C的数据类型3.1数据的储存3.2补码、原码和反码3.2.1原码和反码3.2.2补码3.3变量四、运算符和表达式4.1运算符4.2运算符优先级一、为什么要学C作为诞生于1972年的编程语言,已......
  • 【深入STL:C++容器与算法】深度解析string类的使用
    文章目录1️⃣什么是stringstring的设计以及编码问题2️⃣string的重要接口......
  • 机器学习报错1
    报错:Traceback(mostrecentcalllast):File"D:\devtools\python\lib\site-packages\pandas\compat\_optional.py",line135,inimport_optional_dependencymodule=importlib.import_module(name)File"D:\devtools\python\lib\importlib\......
  • Git安装及基础学习
    Git学习Git安装概述:Git是一个开源的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理,是目前使用范围最广的版本管理工具。下载安装:下载地址:https://git-scm.com/下载后傻瓜式一键安装,建议安装在英文目录下安装完成后在开始菜单中能够找到......