【HuggingFace Transformers】BertSelfOutput 和 BertOutput源码解析

本文主要是介绍【HuggingFace Transformers】BertSelfOutput 和 BertOutput源码解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

BertSelfOutput 和 BertOutput源码解析

  • 1. 介绍
    • 1.1 共同点
      • (1) 残差连接 (Residual Connection)
      • (2) 层归一化 (Layer Normalization)
      • (3) Dropout
      • (4) 线性变换 (Linear Transformation)
    • 1.2 不同点
      • (1) 处理的输入类型
      • (2) 线性变换的作用
      • (3) 输入的特征大小
  • 2. 源码解析
    • 2.1 BertSelfOutput 源码解析
    • 2.2 BertOutput 源码解析

1. 介绍

BertSelfOutputBertOutputBERT 模型中两个相关但不同的模块。它们在功能上有许多共同点,但也有一些关键的不同点。以下通过共同点和不同点来介绍它们。

1.1 共同点

BertSelfOutputBertOutput 都包含残差连接、层归一化、Dropout 和线性变换,并且这些操作的顺序相似。

(1) 残差连接 (Residual Connection)

两个模块都应用了残差连接,即将模块的输入直接与经过线性变换后的输出相加。这种结构可以帮助缓解深层神经网络中的梯度消失问题,使信息更直接地传递,保持梯度流动顺畅。

(2) 层归一化 (Layer Normalization)

在应用残差连接后,两个模块都使用层归一化 (LayerNorm) 来规范化输出。这有助于加速训练,稳定网络性能,并减少内部分布变化的问题。

(3) Dropout

两个模块都包含一个 Dropout 层,用于随机屏蔽一部分神经元的输出,增强模型的泛化能力,防止过拟合。

(4) 线性变换 (Linear Transformation)

两个模块都包含一个线性变换 (dense 层)。这个线性变换用于调整数据的维度,并为后续的残差连接和层归一化做准备。

1.2 不同点

BertSelfOutput 专注于处理自注意力机制的输出,而 BertOutput 则处理前馈神经网络的输出。它们的输入特征维度也有所不同,线性变换的作用在两个模块中也略有差异。

(1) 处理的输入类型

  • BertSelfOutput:处理自注意力机制 (BertSelfAttention) 的输出。它关注的是如何将注意力机制生成的特征向量与原始输入结合起来。
  • BertOutput:处理的是前馈神经网络的输出。它将经过注意力机制处理后的特征进一步加工,并整合到当前层的最终输出中。

(2) 线性变换的作用

  • BertSelfOutput:线性变换的作用是对自注意力机制的输出进行进一步的变换和投影,使其适应后续的处理流程。
  • BertOutput:线性变换的作用是对前馈神经网络的输出进行变换,使其与前一层的输出相结合,并准备传递到下一层。

(3) 输入的特征大小

  • BertSelfOutput:输入和输出的特征维度保持一致,都是 BERT 模型的隐藏层大小 (hidden_size)。
  • BertOutput:输入的特征维度是中间层大小 (intermediate_size),输出则是 BERT 模型的隐藏层大小 (hidden_size)。这意味着 BertOutput 的线性变换需要将中间层的维度转换回隐藏层的维度。

2. 源码解析

源码地址:transformers/src/transformers/models/bert/modeling_bert.py

2.1 BertSelfOutput 源码解析

# -*- coding: utf-8 -*-
# @time: 2024/7/15 14:27import torch
from torch import nnclass BertSelfOutput(nn.Module):def __init__(self, config):super().__init__()self.dense = nn.Linear(config.hidden_size, config.hidden_size)  # 定义线性变换层,将自注意力输出映射到 hidden_size 维度self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)  # 层归一化self.dropout = nn.Dropout(config.hidden_dropout_prob)  # Dropout层def forward(self, hidden_states: torch.Tensor, input_tensor: torch.Tensor) -> torch.Tensor:hidden_states = self.dense(hidden_states)  # 对自注意力机制的输出进行线性变换hidden_states = self.dropout(hidden_states)  # Dropout操作hidden_states = self.LayerNorm(hidden_states + input_tensor)  # 残差连接后进行层归一化return hidden_states

2.2 BertOutput 源码解析

# -*- coding: utf-8 -*-
# @time: 2024/8/22 15:41import torch
from torch import nnclass BertOutput(nn.Module):def __init__(self, config):super().__init__()self.dense = nn.Linear(config.intermediate_size, config.hidden_size)  # 定义线性变换层,将前馈神经网络输出从 intermediate_size 映射到 hidden_sizeself.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)  # 层归一化self.dropout = nn.Dropout(config.hidden_dropout_prob)  # Dropout层def forward(self, hidden_states: torch.Tensor, input_tensor: torch.Tensor) -> torch.Tensor:hidden_states = self.dense(hidden_states)  # 对前馈神经网络的输出进行线性变换hidden_states = self.dropout(hidden_states)  # Dropout操作hidden_states = self.LayerNorm(hidden_states + input_tensor)  # 残差连接后进行层归一化return hidden_states

这篇关于【HuggingFace Transformers】BertSelfOutput 和 BertOutput源码解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1111922

相关文章

MySQL字符串转数值的方法全解析

《MySQL字符串转数值的方法全解析》在MySQL开发中,字符串与数值的转换是高频操作,本文从隐式转换原理、显式转换方法、典型场景案例、风险防控四个维度系统梳理,助您精准掌握这一核心技能,需要的朋友可... 目录一、隐式转换:自动但需警惕的&ld编程quo;双刃剑”二、显式转换:三大核心方法详解三、典型场景

SQL 注入攻击(SQL Injection)原理、利用方式与防御策略深度解析

《SQL注入攻击(SQLInjection)原理、利用方式与防御策略深度解析》本文将从SQL注入的基本原理、攻击方式、常见利用手法,到企业级防御方案进行全面讲解,以帮助开发者和安全人员更系统地理解... 目录一、前言二、SQL 注入攻击的基本概念三、SQL 注入常见类型分析1. 基于错误回显的注入(Erro

C++ 多态性实战之何时使用 virtual 和 override的问题解析

《C++多态性实战之何时使用virtual和override的问题解析》在面向对象编程中,多态是一个核心概念,很多开发者在遇到override编译错误时,不清楚是否需要将基类函数声明为virt... 目录C++ 多态性实战:何时使用 virtual 和 override?引言问题场景判断是否需要多态的三个关

Springboot主配置文件解析

《Springboot主配置文件解析》SpringBoot主配置文件application.yml支持多种核心值类型,包括字符串、数字、布尔值等,文章详细介绍了Profile环境配置和加载位置,本文... 目录Profile环境配置配置文件加载位置Springboot主配置文件 application.ym

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

一文解析C#中的StringSplitOptions枚举

《一文解析C#中的StringSplitOptions枚举》StringSplitOptions是C#中的一个枚举类型,用于控制string.Split()方法分割字符串时的行为,核心作用是处理分割后... 目录C#的StringSplitOptions枚举1.StringSplitOptions枚举的常用

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

MyBatis延迟加载与多级缓存全解析

《MyBatis延迟加载与多级缓存全解析》文章介绍MyBatis的延迟加载与多级缓存机制,延迟加载按需加载关联数据提升性能,一级缓存会话级默认开启,二级缓存工厂级支持跨会话共享,增删改操作会清空对应缓... 目录MyBATis延迟加载策略一对多示例一对多示例MyBatis框架的缓存一级缓存二级缓存MyBat