大模型基础——从零实现一个Transformer(3)
大模型基础——从零实现一个Transformer(1)-CSDN博客
一、前言
之前两篇文章已经讲了Transformer的Embedding,Tokenizer,Attention,Position Encoding,
本文我们继续了解Transformer中剩下的其他组件.
二、归一化
2.1 Layer Normalization

layerNorm是针对序列数据提出的一种归一化方法,主要在layer维度进行归一化,即对整个序列进行归一化。
layerNorm会计算一个layer的所有activation的均值和方差,利用均值和方差进行归一化。
𝜇=∑𝑖=1𝑑𝑥𝑖
𝜎=1𝑑∑𝑖=1𝑑(𝑥𝑖−𝜇)2
归一化后的激活值如下:
𝑦=𝑥−𝜇𝜎+𝜖𝛾+𝛽
其中 𝛾 和 𝛽 是可训练的模型参数。 𝛾 是缩放参数,新分布的方差 𝛾2 ; 𝛽 是平移系数,新分布的均值为 𝛽 。 𝜖 为一个小数,添加到方差上,避免分母为0。
2.2 LayerNormalization 代码实现
import torch
import torch.nn as nnclass LayerNorm(nn.Module):def __init__(self,num_features,eps=1e-6):super().__init__()self.gamma = nn.Parameter(torch.ones(num_features))self.beta = nn.Parameter(torch.zeros(num_features))self.eps = epsdef forward(self,x):"""Args:x (Tensor): (batch_size, seq_length, d_model)Returns:Tensor: (batch_size, seq_length, d_model)"""mean = x.mean(dim=-1,keepdim=True)std = x.std(dim=-1,keepdim=True,unbiased=False)normalized_x = (x - mean) / (std + self.eps)return self.gamma * normalized_x + self.betaif __name__ == '__main__':batch_size = 2seqlen = 3hidden_dim = 4# 初始化一个随机tensorx = torch.randn(batch_size,seqlen,hidden_dim)print(x)# 初始化LayerNormlayer_norm = LayerNorm(num_features=hidden_dim)output_tensor = layer_norm(x)print("output after layer norm:\n,",output_tensor)torch_layer_norm = torch.nn.LayerNorm(normalized_shape=hidden_dim)torch_output_tensor = torch_layer_norm(x)print("output after torch layer norm:\n",torch_output_tensor)
三、残差连接
残差连接(residual connection,skip residual,也称为残差块)其实很简单

x为网络层的输入,该网络层包含非线性激活函数,记为F(x),用公式描述的话就是:

代码简单实现
x = x + layer(x)
四、前馈神经网络
4.1 Position-wise Feed Forward
Position-wise Feed Forward(FFN),逐位置的前馈网络,其实就是一个全连接前馈网络。目的是为了增加非线性,增强模型的表示能力。
它一个简单的两层全连接神经网络,不是将整个嵌入序列处理成单个向量,而是独立地处理每个位置的嵌入。所以称为position-wise前馈网络层。也可以看为核大小为1的一维卷积。
目的是把输入投影到特定的空间,再投影回输入维度。
FFN具体的公式如下:
𝐹𝐹𝑁(𝑥)=𝑓(𝑥𝑊1+𝑏1)𝑊2+𝑏2
上述公式对应FFN中的向量变换操作,其中f为非线性激活函数。
4.2 FFN代码实现
from torch import nn,Tensor
from torch.nn import functional as Fclass PositonWiseFeedForward(nn.Module):def __init__(self,d_model:int ,d_ff: int ,dropout: float=0.1) -> None:''':param d_model: dimension of embeddings:param d_ff: dimension of feed-forward network:param dropout: dropout ratio'''super().__init__()self.ff1 = nn.Linear(d_model,d_ff)self.ff2 = nn.Linear(d_ff,d_model)self.dropout = nn.Dropout(dropout)def forward(self,x: Tensor) -> Tensor:''':param x: (batch_size, seq_length, d_model) output from attention:return: (batch_size, seq_length, d_model)'''return self.ff2(self.dropout(F.relu(self.ff1(x))))
五、Transformer Encoder Block

如图所示,编码器(Encoder)由N个编码器块(Encoder Block)堆叠而成,我们依次实现。
from torch import nn,Tensor
## 之前实现的函数引入
from llm_base.attention.MultiHeadAttention1 import MultiHeadAttention
from llm_base.layer_norm.normal_layernorm import LayerNorm
from llm_base.ffn.PositionWiseFeedForward import PositonWiseFeedForwardfrom typing import *class EncoderBlock(nn.Module):def __init__(self,d_model: int,n_heads: int,d_ff: int,dropout: float,norm_first: bool = False):''':param d_model: dimension of embeddings:param n_heads: number of heads:param d_ff: dimension of inner feed-forward network:param dropout:dropout ratio:param norm_first : if True, layer norm is done prior to attention and feedforward operations(Pre-Norm).Otherwise it's done after(Post-Norm). Default to False.'''super().__init__()self.norm_first = norm_firstself.attention = MultiHeadAttention(d_model,n_heads,dropout)self.norm1 = LayerNorm(d_model)self.ff = PositonWiseFeedForward(d_model,d_ff,dropout)self.norm2 = LayerNorm(d_model)self.dropout1 = nn.Dropout(dropout)self.dropout2 = nn.Dropout(dropout)# self attention sub layerdef _self_attention_sub_layer(self,x: Tensor, attn_mask: Tensor, keep_attentions: bool) -> Tensor:x = self.attention(x,x,x,attn_mask,keep_attentions)return self.dropout1(x)# ffn sub layerdef _ffn_sub_layer(self,x: Tensor) -> Tensor:x = self.ff(x)return self.dropout2(x)def forward(self,src: Tensor,src_mask: Tensor == None,keep_attentions: bool= False) -> Tuple[Tensor,Tensor]:''':param src: (batch_size, seq_length, d_model):param src_mask: (batch_size, 1, seq_length):param keep_attentions:whether keep attention weigths or not. Defaults to False.:return:(batch_size, seq_length, d_model) output of encoder block'''# pass througth multi-head attention# src (batch_size, seq_length, d_model)# attn_score (batch_size, n_heads, seq_length, k_length)x = src# post LN or pre LNif self.norm_first:# pre LNx = x + self._self_attention_sub_layer(self.norm1(x),src_mask,keep_attentions)x = x + self._ffn_sub_layer(self.norm2(x))else:x = self.norm1(x + self._self_attention_sub_layer(x,src_mask,keep_attentions))x = self.norm2(x + self._ffn_sub_layer(x))return x
5.1 Post Norm Vs Pre Norm
公式区别
Pre Norm 和 Post Norm 的式子分别如下:

在大模型的区别
Post-LN :是在 Transformer 的原始版本中使用的归一化方案。在此方案中,每个子层(例如,自注意力机制或前馈网络)的输出先通过子层自身的操作,然后再通过层归一化(Layer Normalization)
Pre-LN:是先对输入进行层归一化,然后再传递到子层操作中。这样的顺序对于训练更深的网络可能更稳定,因为归一化的输入可以帮助缓解训练过程中的梯度消失和梯度爆炸问题。

5.2为什么Pre效果弱于Post

相关文章:
大模型基础——从零实现一个Transformer(3)
大模型基础——从零实现一个Transformer(1)-CSDN博客 一、前言 之前两篇文章已经讲了Transformer的Embedding,Tokenizer,Attention,Position Encoding, 本文我们继续了解Transformer中剩下的其他组件. 二、归一化 2.1 Layer Normalization layerNorm是针对序列数据提出的一种…...
一二三应用开发平台应用开发示例——概述、应用开发示例简介及创建前后端模块
概述 对于应用开发平台的核心基石——系统管理模块,我精心撰写了一份详尽的说明手册。该手册旨在从使用者的角度出发,不仅全面阐述系统的各项属性和功能,更着重强调使用过程中的注意事项和最佳实践。 在手册的编写过程中,我特别…...
springboot+minio+kkfileview实现文件的在线预览
在原来的文章中已经讲述过springbootminio的开发过程,这里不做讲述。 原文章地址: https://blog.csdn.net/qq_39990869/article/details/131598884?spm1001.2014.3001.5501 如果你的项目只是需要在线预览图片或者视频那么可以使用minio自己的预览地址进…...
HTML5+CSS3小实例:粘性文字的滚动效果
实例:粘性文字的滚动效果 技术栈:HTML+CSS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-sca…...
Java 关于抽象 -- Java 语言的抽象类、接口和函数式接口
大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 008 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自…...
用 Notepad++ 写 Java 程序
安装包 百度网盘 提取码:6666 安装步骤 双击安装包开始安装。 安装完成: 配置编码 用 NotePad 写 Java 程序时,需要设置编码。 在 设置,首选项,新建 中进行设置,可以对每一个新建的文件起作用。 Note…...
malloc brk mmap
malloc 是一个库函数,通常在 C 标准库中实现,用于动态内存分配。malloc 的具体实现可能因库、操作系统和平台而异,但通常它会与底层操作系统提供的内存管理功能进行交互。 对于大多数现代操作系统(如 Unix、Linux、Windows 等&am…...
java多线程相关概念
在Java多线程编程中,有几个关键的术语需要理解: 1.线程(Thread):线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。 2.进程(Process):进程是系统进行资源分配和调度…...
【html】简单网页模板源码
大家每一次在写网页的时候会不会因为布局而困扰今天就给大家带来一个我自己亲自编写的网页的基本的模板大家可以直接去利用,大家也可以利用自己的想法去做空间的美化和完善。 源码: html: <!DOCTYPE html> <html lang"zh"><…...
借助Historian Connector + TDengine,打造工业创新底座
在工业自动化的领域中,数据的采集、存储和分析是实现高效决策和操作的基石。AVEVA Historian (原 Wonderware Historian) 作为领先的工业实时数据库,专注于收集和存储高保真度的历史工艺数据。与此同时,TDengine 作为一款专为时序数据打造的高…...
51单片机-实机演示(LED点阵)
目录 前言: 一.线位置 二.扩展 三.总结 前言: 这是一篇关于51单片机实机LED点阵的插线图和代码说明.另外还有一篇我写的仿真的连接在这:http://t.csdnimg.cn/ZNLCl,欢迎大家的点赞,评论,关注. 一.线位置 接线实机图. 引脚位置注意: 1. *-* P00->RE8 P01->RE7 …...
STM32硬件接口I2C应用(基于MP6050)
目录 概述 1 STM32Cube控制配置I2C 1.1 I2C参数配置 1.2 使用STM32Cube产生工程 2 HAL库函数介绍 2.1 初始化函数 2.2 写数据函数 2.3 读数据函数 3 认识MP6050 3.1 MP6050功能介绍 3.2 加速计测量寄存器 编辑3.3 温度计量寄存器 3.4 陀螺仪测量寄存器 4 MP60…...
基于JSP的贝儿米幼儿教育管理系统
开头语: 你好呀,我是计算机学长猫哥!如果您对本系统感兴趣或者有相关需求,文末可以找到我的联系方式。 开发语言: Java 数据库: MySQL 技术: JSP技术 工具: IDEA/Eclipse、…...
数字化与文化交融,树莓集团助力园区文化升级
树莓集团在产业园运营领域建设了特色空间布局,包括产业实训基地、产业办公中心、业务资源平台、产学研中心、数字资产空间、双创孵化空间、产业实验室和人才项目转化中心等八大板块,共同构建了一个全面而深入的产业支撑体系,为园区文化建设提…...
【原创课程】如何制作安装板
具体步骤如下: 第一步:新建页类型为“安装板布局图(交互式)”并修改页描述为“安装板布局图”。 第二步:新建安装板 第三步:设置图纸上符号元件的部件,双击符号,弹出常规设备窗口,点击部件进行选择 第四步:打开2D安装板导航器,将图纸中的设备拖拽到安装板上 第五步…...
简单聊聊【java.util.Stream】,更新中
public class Main {public static void main(String[] args) {List<Integer> numbers Arrays.asList(1, 2, 3, 4, 5, 6); // 原始容器:java.util.Arrays.ArrayList#ArrayList// 创建一个 Stream,过滤出偶数,并打印它们numbers.str…...
GIS之arcgis系列07:conda环境下安装arcpy环境
首先将python27环境下的“Desktop10.8.pth”拷贝到anaconda环境下。 路径如下(仅参考): C:\Python27\ArcGIS10.8\Lib\site-packages\Desktop10.8.pth D:\Anaconda\Lib\site-packages 在anaconda prompt中穿创建一个新环境 conda create -…...
容器运行nslookup提示bash: nslookup: command not found【笔记】
在容器中提示bash: nslookup: command not found,表示容器中没有安装nslookup命令。 可以通过以下命令安装nslookup: 对于基于Debian/Ubuntu的容器,使用以下命令: apt-get update apt-get install -y dnsutils对于基于CentOS/R…...
解析 Spring 框架中的三种 BeanName 生成策略
在 Spring 框架中,定义 Bean 时不一定需要指定名称,Spring 会智能生成默认名称。本文将介绍 Spring 的三种 BeanName 生成器,包括在 XML 配置、Java 注解和组件扫描中使用的情况,并解释它们如何自动创建和管理 Bean 名称。 1. Be…...
细说ARM MCU的串口接收数据的实现过程
目录 一、硬件及工程 1、硬件 2、软件目的 3、创建.ioc工程 二、 代码修改 1、串口初始化函数MX_USART2_UART_Init() (1)MX_USART2_UART_Init()串口参数初始化函数 (2)HAL_UART_MspInit()串口功能模块初始化函数 2、串口…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
