当前位置: 首页 > article >正文

从0开始深度学习(20)——延后初始化和自定义层

一般情况下,模型参数在被创建时就被立即初始化了,但如果使用了延后初始化技术,就能在首次传入数据后,再初始化参数,旨在输入维度未知的情况下,预定义灵活的模型,动态推断各个层的参数大小。

有时我们会遇到或要自己发明一个现在在深度学习框架中还不存在的层。 在这些情况下,必须构建自定义层。本节将展示如何构建自定义层。

1 延后初始化的使用场景

  1. 动态输入形状:在某些情况下,模型的输入形状可能不是固定的,而是动态变化的。例如,在自然语言处理任务中,输入句子的长度可能会有所不同。
  2. 简化模型定义:延后初始化可以简化模型的定义,避免在模型构建阶段手动指定每个层的输入和输出形状。

2 pytorch实现延后初始化

在 PyTorch 中,可以通过 torch.nn.Lazy 模块来实现延后初始化。torch.nn.Lazy 模块提供了一些常见的层,如 LazyLinearLazyConv2d 等,这些层在第一次前向传播时自动确定参数的形状。

以下是一个简单的示例,展示了如何使用 torch.nn.LazyLinear 进行延后初始化:

import torch
import torch.nn as nn

class LazyNet(nn.Module):
    def __init__(self):
        super(LazyNet, self).__init__()
        self.lazy_linear = nn.LazyLinear(out_features=10)
		# 没有指定输出维度,只指定了输出维度
    def forward(self, x):
        x = self.lazy_linear(x)
        return x

# 创建模型实例
net = LazyNet()

# 创建一个输入张量,假设输入形状为 (batch_size, input_features)
input_data = torch.randn(32, 100)

# 第一次前向传播,此时会自动确定 `LazyLinear` 层的输入形状
output = net(input_data)

print(output.shape)  # 输出形状为 (32, 10)

运行结果:
在这里插入图片描述

3 自定义层

3.1 不带参数的层

我们构造一个没有任何参数的自定义层,下面的CenteredLayer类要从其输入中减去均值。 要构建它,我们只需继承基础层类并实现前向传播功能。

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


class CenteredLayer(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, X):
        return X - X.mean()

传入一些数据进行验证

layer = CenteredLayer()
layer(torch.FloatTensor([1, 2, 3, 4, 5]))

在这里插入图片描述
现在,我们可以将层作为组件合并到更复杂的模型中。作为额外的健全性检查,我们可以在向该网络发送随机数据后,检查均值是否为0。 由于我们处理的是浮点数,因为存储精度的原因,我们仍然可能会看到一个非常小的非零数。

net = nn.Sequential(nn.Linear(8, 128), CenteredLayer())
Y = net(torch.rand(4, 8))
Y.mean()

在这里插入图片描述

3.2 带参数的层

下面我们继续定义具有参数的层, 这些参数可以通过训练进行调整。现在,让我们实现自定义版本的全连接层。 回想一下,该层需要两个参数,一个用于表示权重,另一个用于表示偏置项。 在此实现中,我们使用修正线性单元作为激活函数。 该层需要输入参数:in_units和units,分别表示输入数和输出数。

class MyLinear(nn.Module):
    def __init__(self, in_units, units):
        super().__init__()
        self.weight = nn.Parameter(torch.randn(in_units, units))
        self.bias = nn.Parameter(torch.randn(units,))
    def forward(self, X):
        linear = torch.matmul(X, self.weight.data) + self.bias.data
        return F.relu(linear)

接下来实例化模型,并访问其参数:

linear = MyLinear(5, 3)
linear.weight

在这里插入图片描述
我们可以使用自定义层直接执行前向传播计算。

linear(torch.rand(2, 5))

在这里插入图片描述
我们还可以使用自定义层构建模型,就像使用内置的全连接层一样使用自定义层。

net = nn.Sequential(MyLinear(64, 8), MyLinear(8, 1))
net(torch.rand(2, 64))

在这里插入图片描述
我们可以通过基本层类设计自定义层。这允许我们定义灵活的新层


http://www.kler.cn/news/363822.html

相关文章:

  • 解决:如何在opencv中得到与matlab立体标定一样的矫正图?(python版opencv)
  • 使用Redisson的布隆过滤器解决缓存穿透问题
  • 高薪、高含金量、高性价比的“三高”证书——PMP证书
  • NLP 技术:AI 是如何理解人类语言的
  • SpringBoot整合HTTPS
  • CUDA 共享内存 shared memory
  • Text实现美团部分样式
  • 代码随想录刷题学习日记
  • 基础知识 main函数形参 C语言
  • C++:模板的特化与分离编译
  • Python re 模块:正则表达式的强大工具
  • 全局滚动和局部滚动
  • 多模态大语言模型(MLLM)-Deepseek Janus
  • Spring AI 1.0.0 M1版本新特性!
  • 代码随想录算法训练营第二十二天|Day22 回溯算法
  • Oracle10g运维 表增删改查
  • 【Vue.js设计与实现】第三篇第11章:渲染器-快速 Diff 算法-阅读笔记
  • 文案创作新思路:Python与文心一言API的完美结合
  • 《计算机视觉》—— 基于dlib库的人脸关键部位的轮廓检测
  • 【MySQL】详解表的约束
  • 【途牛旅游网-注册/登录安全分析报告】
  • vue2.x中的数据劫持
  • 视频剪辑和转换gif一体化UI页面【可以解决gif体积过大】
  • 【YOLOv11】制作使用YOLOv11的docker环境
  • 一道面试题:为什么要使用Docker?
  • Java项目-基于springboot框架的智慧外贸系统项目实战(附源码+文档)