大模型之layer_normalization

2.layer_normalization

1.Normalization

1.1 Batch Norm

为什么要进行BN呢?

  1. 在深度神经网络训练的过程中,通常以输入网络的每一个mini-batch进行训练,这样每个batch具有不同的分布,使模型训练起来特别困难。
  2. Internal Covariate Shift (ICS) 问题:在训练的过程中,激活函数会改变各层数据的分布,随着网络的加深,这种改变(差异)会越来越大,使模型训练起来特别困难,收敛速度很慢,会出现梯度消失的问题。

BN的主要思想: 针对每个神经元,使数据在进入激活函数之前,沿着通道计算每个batch的均值、方差,‘强迫’数据保持均值为0,方差为1的正态分布, 避免发生梯度消失。具体来说,就是把第1个样本的第1个通道,加上第2个样本第1个通道 … 加上第 N 个样本第1个通道,求平均,得到通道 1 的均值(注意是除以 N×H×W 而不是单纯除以 N,最后得到的是一个代表这个 batch 第1个通道平均值的数字,而不是一个 H×W 的矩阵)。求通道 1 的方差也是同理。对所有通道都施加一遍这个操作,就得到了所有通道的均值和方差。

BN的使用位置: 全连接层或卷积操作之后,激活函数之前。

BN算法过程:

  • 沿着通道计算每个batch的均值
  • 沿着通道计算每个batch的方差
  • 做归一化
  • 加入缩放和平移变量 γ \gamma γ β \beta β

加入缩放和平移变量的原因是:保证每一次数据经过归一化后还保留原有学习来的特征,同时又能完成归一化操作,加速训练 这两个参数是用来学习的参数。

BN的作用:

  1. 允许较大的学习率;
  2. 减弱对初始化的强依赖性
  3. 保持隐藏层中数值的均值、方差不变,让数值更稳定,为后面网络提供坚实的基础;
  4. 有轻微的正则化作用(相当于给隐藏层加入噪声,类似Dropout)

BN存在的问题:

  1. 每次是在一个batch上计算均值、方差,如果batch size太小,则计算的均值、方差不足以代表整个数据分布。
  2. batch size太大: 会超过内存容量;需要跑更多的epoch,导致总训练时间变长;会直接固定梯度下降的方向,导致很难更新。
1.2 Layer Norm

LayerNorm是大模型也是transformer结构中最常用的归一化操作,简而言之,它的作用是 对特征张量按照某一维度或某几个维度进行0均值,1方差的归一化 操作,计算公式为:

y = x − E ( x ) Var ( x ) + ϵ ⋅ γ + β \mathrm{y} = \frac{\mathrm{x} - \mathrm{E}(\mathrm{x})}{\sqrt{\text{Var}(\mathrm{x}) + \epsilon}} \cdot \gamma + \beta y=Var(x)+ϵ xE(x)γ+β

这里的 x x x 可以理解为** 张量中具体某一维度的所有元素**,比如对于 shape 为 (2,2,4) 的张量 input,若指定归一化的操作为第三个维度,则会对第三个维度中的四个张量(2,2,1),各进行上述的一次计算.

详细形式:

a i = ∑ j = 1 m w i j x j , y i = f ( a i + b i ) a_i = \sum_{j=1}^{m} w_{ij} x_j, \quad y_i = f\left(a_i + b_i\right) ai=j=1mwijxj,yi=f(ai+bi)

a ˉ i = a i − μ σ ⋅ g i , y i = f ( a ˉ i + b i ) \bar{a}_i = \frac{a_i - \mu}{\sigma} \cdot g_i, \quad y_i = f\left(\bar{a}_i + b_i\right) aˉi=σaiμgi,yi=f(

<think> 我们正在处理一个关于TensorFlow的错误:`No registered '_MklLayerNorm' OpKernel for 'GPU' devices`,该错误与节点`ft_transformer/layer_normalization_8/add`相关。错误信息表明,系统没有为GPU设备注册名为`_MklLayerNorm`的操作内核(OpKernel),而注册信息显示只有CPU设备支持该操作,且支持的数据类型为`DT_BFLOAT16`和`DT_FLOAT`。 根据错误信息,我们可以推断出以下关键点: 1. 该错误发生在尝试在GPU上执行`_MklLayerNorm`操作时。 2. 当前环境中,`_MklLayerNorm`操作仅支持在CPU上运行,而不支持GPU。 解决方案的思路应该是: - 确保使用的层归一化操作(Layer Normalization)有对应的GPU实现。 - 或者,检查是否错误地使用了依赖于MKL(Math Kernel Library)的特定操作(如`_MklLayerNorm`),而该操作可能只在CPU上可用。 根据引用[1],我们了解到Layer Normalization(层归一化)在NLP领域应用广泛。在Transformer架构(如BERT、BART等)中,层归一化是一个关键组件。因此,这个错误很可能是在使用类似Transformer的模型(如ft_transformer)时出现的。 另外,引用[2]和[3]提到了关于transformers库的模块导入错误,虽然问题不同,但提示我们可能需要更新或检查transformers库的版本。 引用[4]提到了一个修改tokenizer_class为processor_class的解决方案,但这与当前问题关系不大。 根据经验,这个错误可能是由于TensorFlow的版本问题,或者使用的模型代码中指定了MKL相关的操作,而这些操作在GPU上不可用。MKL是Intel的数学库,通常用于加速CPU计算,但不会在GPU上运行。 可能的解决方案: 1. **检查TensorFlow版本和MKL支持**:确保安装的TensorFlow版本支持在GPU上进行层归一化操作。如果是使用MKL优化的TensorFlow版本(如从Intel官网下载的版本),则可能默认启用了MKL操作,但这些操作可能不支持GPU。尝试安装官方标准的TensorFlow-GPU版本。 2. **强制禁用MKL**:如果错误是由于尝试在GPU上使用MKL操作造成的,可以尝试通过设置环境变量来禁用MKL,让TensorFlow使用其原生的GPU操作。 ```bash export TF_DISABLE_MKL=1 export TF_ENABLE_MKL_NATIVE_FORMAT=0 ``` 3. **检查模型代码**:查看模型中定义层归一化的部分,确认是否使用了自定义操作(custom op)或者是否显式指定了使用MKL操作。如果使用了自定义操作,需要确保该操作有GPU实现。 4. **使用标准的层归一化**:如果模型代码中使用了`_MklLayerNorm`这样的操作,可能是由于使用了特定的优化层。尝试将其替换为标准的`tf.keras.layers.LayerNormalization`。 5. **更新TensorFlow和transformers库**:确保使用的库是最新的,因为可能在新版本中修复了这个问题。 6. **在CPU上运行**:如果以上方法都不可行,可以尝试将运行设备设置为CPU(不推荐,因为会降低速度),但这只是临时解决方案。 具体步骤建议: - 首先,尝试设置环境变量禁用MKL,然后重新运行程序。 - 如果不行,检查模型代码中关于层归一化的定义,看是否有特殊操作。如果是使用Hugging Face Transformers库,确保库是最新版本,因为该库通常使用标准的层归一化层。 - 如果使用的是自定义层归一化,尝试替换为`tf.keras.layers.LayerNormalization`。 由于错误信息中提到了节点`ft_transformer/layer_normalization_8/add`,这个`add`操作可能是层归一化中的一部分(例如,在计算均值和方差后的缩放和平移步骤)。如果整个操作被封装为一个自定义操作`_MklLayerNorm`,那么在没有GPU实现的情况下,我们需要避免使用这个MKL版本的操作。 如果问题仍然存在,可能需要查看TensorFlow的GitHub issues页面,看是否有其他人遇到相同问题并提供了解决方案。 最后,考虑到引用中提到的transformers库的错误,虽然与当前问题不直接相关,但建议确保transformers库是最新版本,以避免其他兼容性问题。 **相关问题**: 1. 如何检查TensorFlow是否使用了MKL? 2. 如何查看TensorFlow中某个操作(Op)支持的设备(CPU/GPU)和数据类型? 3. 在TensorFlow中如何替换模型中的特定层? 4. 如何更新Hugging Face Transformers库? 5. 在TensorFlow中如何设置运行设备(CPU/GPU)? </think> ### 解决`No registered '_MklLayerNorm' OpKernel for 'GPU' devices`错误的分析与方案 #### 📌 **错误原因分析** 1. **核心问题** 错误表明 TensorFlow 在执行层归一化(Layer Normalization)操作时,无法在 GPU 上找到名为 `_MklLayerNorm` 的算子内核(OpKernel)。注册信息显示该操作仅支持 CPU 设备且兼容 `DT_BFLOAT16` 和 `DT_FLOAT` 数据类型: - `device='CPU'; T in [DT_BFLOAT16]` - `device='CPU'; T in [DT_FLOAT]` 节点 `ft_transformer/layer_normalization_8/add` 要求 GPU 支持,但当前环境未提供 GPU 实现 [^1]。 2. **关键影响因素** - **MKL 依赖**:`_MklLayerNorm` 是 Intel MKL(数学核心库)优化的算子,通常仅支持 CPU [^1]。 - **TensorFlow 版本**:旧版本 TF 或未正确编译 GPU 支持的版本可能导致此问题。 - **模型结构**:某些自定义层(如 `LayerNormalization`)可能隐式调用了 MKL 算子 [^1][^4]。 --- #### 🛠️ **解决方案步骤** ##### 1. **禁用 MKL 优化(首选方案)** 通过环境变量强制 TensorFlow 使用原生 GPU 算子替代 MKL: ```bash # 在运行代码前设置环境变量 export TF_DISABLE_MKL=1 export TF_ENABLE_MKL_NATIVE_FORMAT=0 ``` **效果**:跳过 MKL 算子,改用 TensorFlow 内置的 CUDA 兼容层归一化实现 [^1]。 ##### 2. **替换层归一化实现** 若使用自定义层(如 Transformers 库),显式指定 GPU 兼容的归一化层: ```python # 示例:修改模型中的 LayerNormalization 层 from tensorflow.keras.layers import LayerNormalization # 替换原有层 x = LayerNormalization(epsilon=1e-6)(x) # 确保未调用 _MklLayerNorm ``` **验证**:检查模型代码中是否包含 `_MklLayerNorm` 关键字 [^1][^4]。 ##### 3. **更新库版本** 确保 TensorFlow 和 Transformers 库版本兼容: ```bash # 更新 TensorFlow(GPU 版本) pip install tensorflow-gpu --upgrade # 更新 Transformers 库 pip install transformers --upgrade ``` > 💡 **注意**:Transformers 库的某些版本存在模块导入问题(如引用[2][3]),更新可修复依赖 [^2][^3]。 ##### 4. **强制使用 GPU 算子注册** 在代码中显式注册 GPU 算子(需 TF 源码编译支持): ```python from tensorflow.python.framework import ops @ops.RegisterGradient("LayerNorm") def _LayerNormGrad(op, grad): # 自定义 GPU 梯度计算逻辑 return grad_computation_result ``` > ⚠️ **高级用户**:需参考 [TensorFlow 自定义算子文档](https://www.tensorflow.org/guide/create_op)。 ##### 5. **降级数据类型(临时方案)** 若仍报错,强制使用 `DT_FLOAT` 替代 `DT_BFLOAT16`: ```python # 在模型定义中设置 dtype from tensorflow.keras import mixed_precision mixed_precision.set_global_policy('float32') # 禁用 BFLOAT16 ``` --- #### 💎 **总结建议** 1. **优先尝试方案 1**(禁用 MKL),90% 案例可解决 [^1]。 2. 检查模型代码是否包含 `_MklLayerNorm` 调用(如自定义层)。 3. 确保环境安装 `tensorflow-gpu` 而非 `tensorflow`(CPU 版本)。 4. 监控 GPU 显存使用:`nvidia-smi` 确认计算任务是否在 GPU 执行。 > 若问题持续,请提供以下信息: > - TensorFlow 版本 (`pip show tensorflow`) > - GPU 型号及 CUDA 版本 (`nvidia-smi`) > - 完整的错误堆栈日志 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值