首页 > 其他分享 >4-3nn.functional和nn.Module

4-3nn.functional和nn.Module

时间:2024-03-10 17:56:04浏览次数:32  
标签:kernel nn 3nn self torch functional Module Parameter size

import torch 
import torchkeras
print("torch.__version__="+torch.__version__) 
print("torchkeras.__version__="+torchkeras.__version__) 
"""
torch.__version__=2.1.1+cu118
torchkeras.__version__=3.9.4
"""

1.nn.functional和nn.Module

前面我们介绍了Pytorch的张量的结构操作和数学运算中的一些常用API。

利用这些张量的API我们可以构建出神经网络相关的组件(如激活函数,模型层,损失函数)

Pytorch和神经网络相关的功能组件大多都封装在torch.nn模块下。

这些功能组件的绝大部分既有函数形式实现,也有类形式实现。

其中nn.functional(一般引入后改名为F)有各种功能组件的函数实现,例如:

激活函数:

  • F.relu
  • F.sigmoid
  • F.tanh
  • F.softmax

模型层:

  • F.linear
  • F.conv2d
  • F.max_pool2d
  • F.droupout2d
  • F.embedding

损失函数

  • F.binary_cross_entropy
  • F.mse_loss
  • F.cross_entropy

为了便于对参数进行管理,一般通过继承nn.Module转换成类的实现形式,并直接封装在nn模块下。例如:

激活函数

  • nn.ReLU
  • nn.Sigmoid
  • nn.Tanh
  • nn.Softmax

模型层

  • nn.Linear
  • nn.Conv2d
  • nn.MaxPool2d
  • nn.Dropout2d
  • nn.Embedding

损失函数

  • nn.BECLoss
  • nn.MSELoss
  • nn.CrossEntropyLoss

实际上nn.Module除了可以管理其引用的各种参数,还可以管理其引用的子模块,功能十分强大。

import torch

torch.relu(torch.tensor(-1.0))
"""
tensor(0.)
"""

import torch.nn.functional as F

F.relu(torch.tensor(-1.0))
"""
tensor(0.)
"""

2.使用nn.Module来管理参数(配合nn.Parameter使用)

在Pytorch中,模型的参数是需要被优化器训练的,因此,通常要设置参数为requires_grad=True的张量。

同时,在一个模型中,往往有许多的参数,要手动管理这些参数并不是一件容易的事情。

Pytorch一般将参数用nn.Parameter来表示,并且用nn.Module来管理其结构下的所有参数。

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

torch.randn(2, 2, requires_grad=True)
"""
tensor([[-0.1423, -0.3451],
        [ 0.1613,  1.0027]], requires_grad=True)
"""

# nn.Parameter具有requires_grad属性
w = nn.Parameter(torch.randn(2, 2))
print(w)
print(w.requires_grad)
"""
Parameter containing:
tensor([[ 0.1437, -1.5047],
        [-0.0155, -0.3239]], requires_grad=True)
True
"""

# nn、ParameterList可以将多个nn.Parameter组成一个列表
params_list = nn.ParameterList([nn.Parameter(torch.rand(8, i)) for i in range(1, 3)])
print(params_list)
print(params_list[0].requires_grad)
"""
ParameterList(
    (0): Parameter containing: [torch.float32 of size 8x1]
    (1): Parameter containing: [torch.float32 of size 8x2]
)
True
"""

# nn.ParameterDict可以将多个nn.Parameter组成一个字典
param_dict = nn.ParameterDict({
    'a': nn.Parameter(torch.rand(2, 2)),
    'b': nn.Parameter(torch.zeros(2))
})

print(param_dict)
print(param_dict['a'].requires_grad)
"""
ParameterDict(
    (a): Parameter containing: [torch.FloatTensor of size 2x2]
    (b): Parameter containing: [torch.FloatTensor of size 2]
)
True
"""

# 可以用Module将它们管理起来
# module.parameters()返回一个生成器,包括其结构下的所有parameters

module = nn.Module()
module.w = nn.Parameter(torch.randn(2, 2))
module.params_list = nn.ParameterList([nn.Parameter(torch.rand(8,i)) for i in range(1,3)])
module.params_dict = nn.ParameterDict({
    'a': nn.Parameter(torch.rand(2, 2)),
    'b': nn.Parameter(torch.zeros(2))
})

num_param = 0
for param in module.named_parameters():
    print(param)
    num_param = num_param + 1
print('number of Parameters=', num_param)
"""
('w', Parameter containing:
tensor([[-0.9218, -0.0231],
        [-0.6829,  0.9799]], requires_grad=True))
('params_list.0', Parameter containing:
tensor([[0.6197],
        [0.4622],
        [0.8464],
        [0.9107],
        [0.3164],
        [0.0340],
        [0.0739],
        [0.4249]], requires_grad=True))
('params_list.1', Parameter containing:
tensor([[0.9176, 0.5050],
        [0.2121, 0.7156],
        [0.2281, 0.5439],
        [0.5997, 0.7202],
        [0.9591, 0.6104],
        [0.5161, 0.1679],
        [0.8338, 0.5305],
        [0.2937, 0.0653]], requires_grad=True))
('params_dict.a', Parameter containing:
tensor([[0.7809, 0.4616],
        [0.2082, 0.4271]], requires_grad=True))
('params_dict.b', Parameter containing:
tensor([0., 0.], requires_grad=True))
number of Parameters= 5
"""

# 实践当中,一般通过继承nn.Module来构建模块类,并将所有含有需要学习的参数的部分放在构造函数中

# 以下范例为Pytorch中nn.Linear的源码的简化版本
# 可以看到它将需要学习的参数放在了__init__构造函数中,并在forward中调用F.linear函数来实现计算逻辑

class Linear(nn.Module):
    __constants__ = ['in_features', 'out_features']
    def __init__(self, infeatures, out_features, bias=True):
        super().__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.weight = nn.Parameter(torch.Tensor(out_features, in_features))
        if bias:
            self.bias = nn.Parameter(torch.Tensor(out_features))
        else:
            self.register_parameter('bias', None)

    def forward(self, input):
        return F.linear(input, self.weight, self.bias)

3.使用nn.Module来管理子模块

一般情况下,我们都很少直接使用nn.Parameter来定义参数构建模型,而是通过拼装一些常用的模型层来构造模型。

这些模型层也是继承自nn.Module的对象,本身也有包括参数,属于我们要定义的模块的子模块。

nn.Module提供了一些方法可以管理这些子模块。

  • children()方法:返回生成器,包括模块下的所有子模块
  • named_children()方法:返回一个生成器,包括模块下的所有子模块,以及它们的名字
  • modules()方法:返回一个生成器,包括模块下的所有各个层级的模块,包括模块本身
  • named_modules()方法:返回一个生成器,包括模块下的所有各个层级的模块以及它们的名字,包括模块本身

其中children()方法和named_children()方法较多使用。

modules()方法和named_modules()方法较少使用,其功能可以通过多个named_children()的嵌套使用实现。

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.embedding = nn.Embedding(num_embeddings=10000, embedding_dim=3, padding_idx=1)
        self.conv = nn.Sequential()
        self.conv.add_module('conv_1', nn.Conv1d(in_channels=3, out_channels=16, kernel_size=5))
        self.conv.add_module('pool_1', nn.MaxPool1d(kernel_size=2))
        self.conv.add_module('relu_1', nn.ReLU())
        self.conv.add_module('conv_2', nn.Conv1d(in_channels=16, out_channels=128, kernel_size=2))
        self.conv.add_module('pool_2', nn.MaxPool1d(kernel_size=2))
        self.conv.add_module('relu_2', nn.ReLU())

        self.dense = nn.Sequential()
        self.dense.add_module('flatten', nn.Flatten())
        self.dense.add_module('linear', nn.Linear(6144, 1))

    def forward(self, x):
        x = self.embedding(x).transpose(1, 2)
        x = self.conv(x)
        y = self.dense(x)
        return y

net = Net()

i = 0
for child in net.children():
    i += 1
    print(child, '\n')
print('child number', i)
"""
Embedding(10000, 3, padding_idx=1) 

Sequential(
  (conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
  (pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (relu_1): ReLU()
  (conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
  (pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (relu_2): ReLU()
) 

Sequential(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear): Linear(in_features=6144, out_features=1, bias=True)
) 

child number 3
Selection deleted
"""

i = 0
for name, child in net.named_children():
    i += 1
    print(name, ':', child, '\n')
print('child number', i)
"""
embedding : Embedding(10000, 3, padding_idx=1) 

conv : Sequential(
  (conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
  (pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (relu_1): ReLU()
  (conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
  (pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (relu_2): ReLU()
) 

dense : Sequential(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear): Linear(in_features=6144, out_features=1, bias=True)
) 

child number 3
"""

i = 0
for module in net.modules():
    i += 1
    print(module)
print('module number:', i)
"""
Net(
  (embedding): Embedding(10000, 3, padding_idx=1)
  (conv): Sequential(
    (conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
    (pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (relu_1): ReLU()
    (conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
    (pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
    (relu_2): ReLU()
  )
  (dense): Sequential(
    (flatten): Flatten(start_dim=1, end_dim=-1)
    (linear): Linear(in_features=6144, out_features=1, bias=True)
  )
)
Embedding(10000, 3, padding_idx=1)
Sequential(
  (conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
  (pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (relu_1): ReLU()
  (conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
  (pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (relu_2): ReLU()
)
Conv1d(3, 16, kernel_size=(5,), stride=(1,))
MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
ReLU()
Conv1d(16, 128, kernel_size=(2,), stride=(1,))
MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
ReLU()
Sequential(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear): Linear(in_features=6144, out_features=1, bias=True)
)
Flatten(start_dim=1, end_dim=-1)
Linear(in_features=6144, out_features=1, bias=True)
module number: 12
"""

下面我们通过named_children方法找到embedding层,并将其参数设置为不可训练(相当于冻结embedding层)

children_dict = {
    name: module for name, module in net.named_children()
}
print(children_dict)
embedding = children_dict['embedding']
embedding.requires_grad_(False)  # 冻结其参数
"""
{'embedding': Embedding(10000, 3, padding_idx=1), 'conv': Sequential(
  (conv_1): Conv1d(3, 16, kernel_size=(5,), stride=(1,))
  (pool_1): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (relu_1): ReLU()
  (conv_2): Conv1d(16, 128, kernel_size=(2,), stride=(1,))
  (pool_2): MaxPool1d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  (relu_2): ReLU()
), 'dense': Sequential(
  (flatten): Flatten(start_dim=1, end_dim=-1)
  (linear): Linear(in_features=6144, out_features=1, bias=True)
)}
Embedding(10000, 3, padding_idx=1)
"""

# 可以看到其第一层的参数已经不可以被训练了
for param in embedding.parameters():
    print(param.requires_grad)
    print(param.numel())
"""
False
30000
"""

from torchkeras import summary

summary(net, input_shape=(200, ), input_dtype=torch.LongTensor);
"""
--------------------------------------------------------------------------
Layer (type)                            Output Shape              Param #
==========================================================================
Embedding-1                             [-1, 200, 3]               30,000
Conv1d-2                               [-1, 16, 196]                  256
MaxPool1d-3                             [-1, 16, 98]                    0
ReLU-4                                  [-1, 16, 98]                    0
Conv1d-5                               [-1, 128, 97]                4,224
MaxPool1d-6                            [-1, 128, 48]                    0
ReLU-7                                 [-1, 128, 48]                    0
Flatten-8                                 [-1, 6144]                    0
Linear-9                                     [-1, 1]                6,145
==========================================================================
Total params: 40,625
Trainable params: 10,625
Non-trainable params: 30,000
--------------------------------------------------------------------------
Input size (MB): 0.000763
Forward/backward pass size (MB): 0.287788
Params size (MB): 0.154972
Estimated Total Size (MB): 0.443523
--------------------------------------------------------------------------
"""

标签:kernel,nn,3nn,self,torch,functional,Module,Parameter,size
From: https://www.cnblogs.com/lotuslaw/p/18064490

相关文章

  • Tengine 安装 nginx-module-vts 模块
      使用Tengine作为反向代理服务器,发现Tengine日志中接口请求过慢,需要绘制grafana展示详细的接口情况------------------------------------------------------------------------------------------------------------------------------------解决思路#......
  • vue3 报错解决:找不到模块或其相应的类型声明。(Vue 3 can not find module)
    当我们在引入应该组件的时候提示找不到这个组件但是项目明明就有这个物理文件报错原因:typescript只能理解.ts文件,无法理解.vue文件 这个时候我们应该这样首先原因:1、volar插件没开takeover模式去看volar插件介绍,开takeover模式2、volar未选择tyscript最新版本解决:1、......
  • 对于core-js相关的报错 core-js/modules/es.array.push.js in ./node_modules/.store
    Thesedependencieswerenotfound:*core-js/modules/es.array.push.jsin./node_modules/.store/@[email protected]/node_modules/@babel/runtime/helpers/construct.js,./node_modules/.store/@[email protected]/node_modules/@babel/runtime/helpers/esm/obj......
  • 解决git submodule拉取失败的方法
    在项目的根目录创建脚本get_submodules_recursive.sh,写入以下内容:#!/bin/bashpull_submodule_recursive(){if[-f".gitmodules"];thenecho".gitmodulesfound"#backupcp.gitmodules.gitmodules.bakwhilereadline......
  • 2024-03-06 Module '"@nestjs/platform-express"' has no exported member 'Expr
    问题描述:nestjs后端开发,遇到跨域问题,打算用express来配合处理,结果引入express的一个模块失败。app.modules.tsimport{MiddlewareConsumer,Module,NestModule}from'@nestjs/common';import{AppController}from'./app.controller';import{AppService}from'.......
  • CommonJS和ES Module 的区别
    最近开始接触web编程,一上来就看到一堆关于module的信息,commomJSmodule和ESmodule直接给我看懵了。网上搜一下,总结一下。大概意思就是CommonJS先出现,用在nodejs编程中。这玩意在浏览器中支持的不太好,随着时间的推移浏览器代码也需要模块化呀,于是ESmodule就出现了。ES......
  • css Module里less里嵌套css,使用的时候,style.xxx不用嵌套吗?
    在CSSModules中,使用Less编译器编译并转换成模块化CSS后,你不需要在JavaScript中通过style.xxx的方式进行嵌套引用。当你在Less文件中使用嵌套语法编写样式时,编译过程会自动将这些嵌套转换为扁平化的类名,并且生成一个映射对象。例如,在Less文件(假设为styles.module.less)中:.contain......
  • vite+vue3 遇到报错 Uncaught SyntaxError: Cannot use import statement outside a m
    按照报错找到了对应的位置import{createApp}from'/node_modules/.vite/deps/vue.js?v=d0a669cf'importAppfrom'/src/pages/project1/App.vue'//import'./index.css'//importrouterfrom"./router"//createApp(App).mount(&#......
  • maven 包管理平台-05-multi module 多模块
    拓展阅读maven包管理平台-01-maven入门介绍+Maven、Gradle、Ant、Ivy、Bazel和SBT的详细对比表格maven包管理平台-02-windows安装配置+mac安装配置maven包管理平台-03-mavenprojectmaven项目的创建入门maven包管理平台-04-mavenarchetype项目原型maven包......
  • 解决uniapp项目中使用vant Weapp图标组件报错问题(Module build failed from ./node_mo
    解决uniapp项目中使用vantWeapp图标组件报错问题(Modulebuildfailedfrom./node_modules/postcss-loader/src/index):https://blog.csdn.net/it_cgq/article/details/111991644?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170909210216800225582870%2522%252C%252......