在深度学习中,归一化技术是提高模型训练效率和性能的重要手段。归一化通过调整输入数据的分布,使得模型在训练过程中更易于收敛,减少过拟合的风险。本文将介绍几种常见的归一化技术,包括特征归一化、批归一化、层归一化和实例归一化。
在这里插入图片描述

一、特征归一化(Feature Normalization)

在深度学习和机器学习中,特征之间的量纲差异可能会对模型的训练和性能产生显著影响。当特征的量纲差异较大时,某些特征可能会在模型训练中占据主导地位,从而导致模型对这些特征的过度依赖,而忽略其他特征。这可能导致模型无法有效学习到数据的整体结构。假设我们有一个数据集,其中包含两个特征:

  • 特征 A:房屋面积(单位:平方英尺),取值范围为 [500, 5000]
  • 特征 B:房屋价格(单位:美元),取值范围为 [50,000, 500,000]

在这种情况下,特征 A 的值相对较小,而特征 B 的值相对较大。如果不进行归一化,模型在训练时可能会更关注特征 B,因为它的数值范围更大。这可能导致模型对房屋价格的预测过于敏感,而忽略了房屋面积的重要性。

特征归一化是将每个特征的值缩放到一个特定的范围,通常是 [0, 1] 或 [-1, 1]。这种方法可以消除特征之间的量纲差异,使得模型在训练时更快收敛。特征归一化通常用于输入数据的预处理阶段,尤其是在使用基于梯度的优化算法时。

对于特征xxx,特征归一化的公式如下:
x′=x−min(x)max(x)−min(x)x' = \frac{x - \text{min}(x)}{\text{max}(x) - \text{min}(x)}x=max(x)min(x)xmin(x)

import numpy as np# 创建示例数据
data = np.array([[10, 200, 30],[20, 150, 40],[30, 300, 50],[40, 250, 60],[50, 100, 70]])print("原始数据:")
print(data)# 特征归一化函数
def feature_normalization(data):# 计算每个特征的最小值和最大值min_vals = np.min(data, axis=0)max_vals = np.max(data, axis=0)# 应用归一化公式normalized_data = (data - min_vals) / (max_vals - min_vals)return normalized_data# 进行特征归一化
normalized_data = feature_normalization(data)print("\n归一化后的数据:")
print(normalized_data)
原始数据:
[[ 10 200  30][ 20 150  40][ 30 300  50][ 40 250  60][ 50 100  70]]归一化后的数据:
[[0.   0.5  0.  ][0.25 0.25 0.25][0.5  1.   0.5 ][0.75 0.75 0.75][1.   0.   1.  ]]

二、批归一化(Batch Normalization)

批归一化(Batch Normalization)是一种在神经网络中广泛使用的技术,旨在提高模型的训练速度和稳定性。它通过对每一层的输入进行归一化,使得输入的均值为 0,方差为 1,从而减少内部协变量偏移(Internal Covariate Shift)。

批归一化的公式如下:
x^=x−μBσB2+ϵ\hat{x} = \frac{x - \mu_B}{\sqrt{\sigma_B^2 + \epsilon}}x^=σB2+ϵxμB

其中:

  • x^\hat{x}x^是归一化后的输出。
  • xxx是当前批次的输入。
  • μB\mu_BμB是当前批次的均值,计算公式为:
    μB=1m∑i=1mxi\mu_B = \frac{1}{m} \sum_{i=1}^{m} x_iμB=m1i=1mxi
    其中mmm是当前批次的样本数量。
  • σB2\sigma_B^2σB2是当前批次的方差,计算公式为:
    σB2=1m∑i=1m(xi−μB)2\sigma_B^2 = \frac{1}{m} \sum_{i=1}^{m} (x_i - \mu_B)^2σB2=m1i=1m(xiμB)2
  • ϵ\epsilonϵ是一个小常数,通常设置为 1e−51e-51e51e−81e-81e8,用于防止除零错误。

批归一化的主要步骤如下:

  1. 计算均值和方差

    • 对于每个批次,计算当前批次的均值μB\mu_BμB和方差σB2\sigma_B^2σB2
  2. 归一化

    • 使用计算得到的均值和方差对输入进行归一化。
  3. 缩放和偏移

    • 在归一化后,批归一化还引入了两个可学习的参数γ\gammaγβ\betaβ,用于缩放和偏移:
      y=γx^+βy = \gamma \hat{x} + \betay=γx^+β
      其中yyy是最终的输出,γ\gammaγβ\betaβ是在训练过程中学习到的参数。

在训练阶段,批归一化会使用当前批次的均值和方差进行归一化。每个批次的均值和方差是动态计算的,这使得模型能够适应训练数据的变化。具体步骤如下:

  1. 计算当前批次的均值和方差
  2. 使用这些统计量对输入进行归一化
  3. 更新移动均值和方差,以便在推理阶段使用:
    μmoving=(1−α)⋅μB+α⋅μmoving\mu_{\text{moving}} = (1-\alpha) \cdot \mu_B + \alpha \cdot \mu_{\text{moving}}μmoving=(1α)μB+αμmoving
    σmoving2=(1−α)⋅σB2+α⋅σmoving2\sigma_{\text{moving}}^2 = (1-\alpha) \cdot \sigma_B^2 + \alpha \cdot \sigma_{\text{moving}}^2σmoving2=(1α)σB2+ασmoving2
    其中α\alphaα是滑动平均系数,通常设置为接近 1(如 0.9 或 0.99)。

在推理阶段,批归一化的处理方式与训练阶段有所不同。推理阶段不再使用当前批次的均值和方差,而是使用在训练阶段计算得到的移动均值和方差。具体步骤如下:

  1. 使用训练阶段计算的移动均值和方差进行归一化
    x^=x−μmovingσmoving2+ϵ \hat{x} = \frac{x - \mu_{\text{moving}}}{\sqrt{\sigma_{\text{moving}}^2 + \epsilon}}x^=σmoving2+ϵxμmoving
  2. 应用缩放和偏移
    y=γx^+βy = \gamma \hat{x} + \betay=γx^+β

下面代码展示了,手动计算的,批归一化,移动均值和方差与模型自动计算的结果一致性

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset# 定义简单的全连接神经网络模型
class SimpleFC(nn.Module):def __init__(self):super(SimpleFC, self).__init__()self.fc1 = nn.Linear(20, 1)  # 从 1 个输入特征到 1 个输出self.bn1 = nn.BatchNorm1d(1)  # 批归一化层def forward(self, x):fc_output = self.fc1(x)  # 全连接层x = self.bn1(fc_output)  # 批归一化return x, fc_output# 创建模型实例
model = SimpleFC()# 定义损失函数和优化器
criterion = nn.MSELoss()  # 均方误差损失
optimizer = optim.Adam(model.parameters(), lr=0.001)  # Adam 优化器# 生成随机正态分布数据
num_samples = 10000  # 样本数量
X = torch.randn(num_samples, 20)  # 1 个特征
y = torch.randn(num_samples, 1)  # 目标值# 创建数据集和数据加载器
dataset = TensorDataset(X, y)
batch_size = 5000  # 每个批次的样本数量
train_loader = DataLoader(dataset, batch_size=batch_size, shuffle=True)# 训练模型
num_epochs = 1  # 训练轮数
alpha = 0.9  # 滑动平均系数
moving_mean = torch.zeros(1)  # 初始化移动均值
moving_var = torch.ones(1)  # 初始化移动方差for epoch in range(num_epochs):model.train()  # 设置模型为训练模式for batch_idx, (images, labels) in enumerate(train_loader):optimizer.zero_grad()  # 清零梯度outputs, fc_output = model(images)  # 前向传播loss = criterion(outputs, labels)  # 计算损失loss.backward()  # 反向传播optimizer.step()  # 更新参数# 获取当前批次的均值和方差batch_mean = fc_output.mean(dim=0)  # 当前批次的均值batch_var = fc_output.var(dim=0)  # 当前批次的方差# 获取模型的批归一化层的移动均值和方差model_moving_mean = model.bn1.running_meanmodel_moving_var = model.bn1.running_var# 手动更新移动均值和方差moving_mean = alpha * moving_mean + (1 - alpha) * batch_meanmoving_var = alpha * moving_var + (1 - alpha) * batch_var# 打印当前批次的均值和方差print(f'Batch {batch_idx + 1}, Batch Mean: {batch_mean.data.numpy()}, Batch Var: {batch_var.data.numpy()}')# 打印模型自动计算的移动均值和方差print(f'Batch {batch_idx + 1}, Model Moving Mean: {model_moving_mean.data.numpy()}, Model Moving Var: {model_moving_var.data.numpy()}')# 打印手动计算的移动均值和方差print(f'Batch {batch_idx + 1}, Manual Moving Mean: {moving_mean.data.numpy()}, Manual Moving Var: {moving_var.data.numpy()}')# 验证手动计算的移动均值和方差与模型的自动计算结果一致assert torch.allclose(moving_mean, model_moving_mean), "Manual moving mean does not match model moving mean!"assert torch.allclose(moving_var,model_moving_var), "Manual moving variance does not match model moving variance!"# 测试模型
model.eval()  # 设置模型为评估模式
with torch.no_grad():  # 不计算梯度test_outputs, fc_output = model(X)  # 前向传播test_loss = criterion(test_outputs, y)  # 计算测试损失# 打印推理阶段的均值和方差
print(f'Test Loss: {test_loss.item()}')
print(f'Model Moving Mean: {model.bn1.running_mean.data.numpy()}')
print(f'Model Moving Var: {model.bn1.running_var.data.numpy()}')
Batch 1, Batch Mean: [0.07945078], Batch Var: [0.0101127]
Batch 1, Model Moving Mean: [0.00794508], Model Moving Var: [0.9010112]
Batch 1, Manual Moving Mean: [0.00794508], Manual Moving Var: [0.9010112]
Batch 2, Batch Mean: [0.07626408], Batch Var: [0.00997146]
Batch 2, Model Moving Mean: [0.01477698], Model Moving Var: [0.81190723]
Batch 2, Manual Moving Mean: [0.01477698], Manual Moving Var: [0.81190723]
Test Loss: 0.9921324253082275
Model Moving Mean: [0.01477698]
Model Moving Var: [0.81190723]

三、层归一化(Layer Normalization)

层归一化(Layer Normalization)是一种归一化技术,主要用于深度学习模型,特别是在处理序列数据(如循环神经网络 RNN 和 Transformer)时表现良好。与批归一化不同,层归一化是对每个样本的所有特征进行归一化,而不是对整个批次进行归一化

在层归一化中,“层”指的是神经网络中的一层,通常是一个全连接层或卷积层。层归一化的目标是对该层的输出进行归一化,以提高模型的训练效率和稳定性。

“样本特征”是指输入数据中每个样本的特征向量。在层归一化中,每个样本的特征向量包含多个特征值,这些特征值可以是不同的输入变量。例如,在图像分类任务中,一个样本的特征可能是图像的像素值;在文本处理任务中,一个样本的特征可能是词嵌入向量。

在层归一化中,我们会对每个样本的所有特征进行归一化处理。
x^=x−μσ2+ϵ\hat{x} = \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}}x^=σ2+ϵxμ

其中:

  • x^\hat{x}x^是归一化后的输出。
  • xxx是当前样本的输入特征向量。
  • μ\muμ是当前样本的均值,计算公式为:
    μ=1d∑i=1dxi\mu = \frac{1}{d} \sum_{i=1}^{d} x_iμ=d1i=1dxi
    其中ddd是特征的维度。
  • σ2\sigma^2σ2是当前样本的方差,计算公式为:
    σ2=1d∑i=1d(xi−μ)2\sigma^2 = \frac{1}{d} \sum_{i=1}^{d} (x_i - \mu)^2σ2=d1i=1d(xiμ)2
  • ϵ\epsilonϵ是一个小常数,通常设置为1e−51e-51e51e−81e-81e8,用于防止除零错误。

层归一化的主要步骤如下:

  1. 计算均值和方差

    • 对于每个样本,计算该样本全部特征的均值μ\muμ和方差σ2\sigma^2σ2
  2. 归一化

    • 使用计算得到的均值和方差对输入特征进行归一化。
  3. 缩放和偏移

    • 在归一化后,层归一化还引入了两个可学习的参数γ\gammaγβ\betaβ,用于缩放和偏移:
      y=γx^+β y = \gamma \hat{x} + \betay=γx^+β
      其中yyy是最终的输出,γ\gammaγβ\betaβ是在训练过程中学习到的参数。

在层归一化中,训练和推理阶段的处理方式是相同的。与批归一化不同,层归一化不依赖于批次的统计量,而是对每个样本的特征进行归一化。因此,无论是在训练阶段还是推理阶段,层归一化都使用当前样本的均值和方差进行归一化。这使得层归一化在处理小批量数据或单个样本时表现良好。

import torchdef layer_normalization(X, epsilon=1e-5):"""计算层归一化:param X: 输入特征矩阵,形状为 (num_samples, num_features):param epsilon: 防止除零错误的小常数:return: 归一化后的特征矩阵"""# 计算均值和方差mu = X.mean(dim=1, keepdim=True)  # 每个样本的均值sigma_squared = X.var(dim=1, keepdim=True)  # 每个样本的方差# 进行归一化X_normalized = (X - mu) / torch.sqrt(sigma_squared + epsilon)return X_normalized# 随机生成样本
num_samples = 5  # 样本数量
num_features = 4  # 每个样本的特征数量
X = torch.randn(num_samples, num_features)  # 生成随机正态分布数据print("原始特征矩阵:")
print(X)# 计算层归一化
X_normalized = layer_normalization(X)print("\n层归一化后的特征矩阵:")
print(X_normalized)
原始特征矩阵:
tensor([[-0.4186,  1.8211, -0.6178, -2.0494],[-0.3354, -1.9183, -0.5551,  0.7775],[ 0.0546,  0.5884, -0.8421, -0.2335],[ 0.3276, -0.5106, -0.0648,  0.0211],[ 0.6945, -0.8199,  0.5595, -2.3835]])层归一化后的特征矩阵:
tensor([[-0.0640,  1.3364, -0.1886, -1.0837],[ 0.1558, -1.2746, -0.0427,  1.1615],[ 0.2730,  1.1685, -1.2312, -0.2102],[ 1.1095, -1.3107, -0.0234,  0.2246],[ 0.8222, -0.2314,  0.7283, -1.3191]])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/95958.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/95958.shtml
英文地址,请注明出处:http://en.pswp.cn/web/95958.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Javaweb学习|实训总结|Week1】html基础,CSS(选择器、常用样式、盒子模型、弹性盒布局、CSS定位、动画),js(基本类型、运算符典例)

开学前三周先进行企业实训,主要学习Javaweb并实现一些小的项目,本篇笔记主要记录第一周实训的知识总结以及个人遇到的问题及解答,用于日后复习回顾和知识巩固,希望可以帮到同样在学Javaweb的大家 文章目录D1html基础D2块元素与行…

SQL 拓展指南:不同数据库差异对比(MySQL/Oracle/SQL Server 基础区别)

在学习 SQL 的过程中,你可能会发现:同样的 “建表语句” 在 MySQL 能运行,在 Oracle 却报错;“分页查询” 的写法在 SQL Server 和 MySQL 完全不同。这是因为 MySQL、Oracle、SQL Server 是三大主流关系型数据库,虽都支…

论文阅读:DMD | Improved Distribution Matching Distillation for Fast Image Synthesis

论文地址:https://arxiv.org/abs/2405.14867 项目官网:https://tianweiy.github.io/dmd2/ 代码地址:https://github.com/tianweiy/DMD2 发表时间:2024年5月24日 分布匹配蒸馏(DMD)生成的一步生成器能够与教…

嵌入式 Linux 启动流程详解 (以 ARM + U-Boot 为例)

嵌入式 Linux 启动流程详解 (以 ARM U-Boot 为例) 对于嵌入式开发者而言,深入理解系统的启动流程至关重要。这不仅有助于进行底层驱动开发和系统移植,还能在遇到启动失败等问题时,快速定位和解决。本文将详细分解基于 ARM 架构的嵌入式 Linu…

在前端开发中,html中script 的type分别有哪几种?分别什么情况用到?

以下是 HTML 中<script>标签type属性的常见取值、说明及使用场景&#xff1a;type 值说明使用场景不写&#xff08;空值&#xff09;HTML5 中默认等同于text/javascript&#xff0c;表示普通 JavaScript 脚本绝大多数传统 JavaScript 代码&#xff0c;包括内联脚本和外部…

2025职教技能大赛汽车制造与维修赛道速递-产教融合实战亮剑​

各位职教同仁&#xff0c;2025年世界职业院校技能大赛总决赛争夺赛&#xff08;汽车制造与维修赛道&#xff09;国内赛区的战报新鲜出炉&#xff01;本次大赛以“技炫青春 能创未来”为主题&#xff0c;聚焦汽车产业链高质量发展需求&#xff0c;在真实场景中比拼技能&#xff…

日志 | Spring Boot 日志配置通用规律(AI问答)

Spring Boot 日志配置通用规律。想看特定日志&#xff0c;怎么打开日志开关 文章目录一、一句话总结二、AI问答版提问词AI的响应&#x1f4ca; Spring Boot 日志配置通用规律1. 基本语法结构2. 日志级别&#xff08;从详细到简洁&#xff09;&#x1f3af; 常用日志配置分类1. …

DJANGO后端服务启动报错及解决

1.报错信息[2025-09-05 17:08:54 0800] [23438] [INFO] Worker exiting (pid: 23438) [2025-09-05 17:08:54 0800] [23440] [ERROR] Exception in worker process Traceback (most recent call last):File "/www/SOP/lib64/python3.11/site-packages/gunicorn/arbiter.py&…

Qt 中的 Q_OBJECT 宏详解 —— 从源码到底层机制的全面剖析

Qt 中的 Q_OBJECT 宏详解 —— 从源码到底层机制的全面剖析 文章目录Qt 中的 Q_OBJECT 宏详解 —— 从源码到底层机制的全面剖析摘要一、Q_OBJECT 宏是什么&#xff1f;二、Q_OBJECT 宏背后的源码三、moc 工具的作用四、信号与槽调用流程五、没有 Q_OBJECT 会怎样&#xff1f;六…

GD32自学笔记:5.定时器中断

定时器中断功能主要是两点&#xff1a;1.怎么配置的定时器中断时间间隔&#xff1b;2.中断里长什么样一、定时器中断配置函数直接在bsp_basic_timer.c里找到下面函数&#xff1a;void basic_timer_config(uint16_t pre,uint16_t per) {/* T 1/f, time T * pre,pertime (pre …

[Godot入门大全]目录

1 免责声明 资源分享免责声明&#xff1a; 本平台/本人所分享的各类资源&#xff08;包括但不限于文字、图片、音频、视频、文档等&#xff09;&#xff0c;均来源于公开网络环境中的可分享内容或已获授权的传播素材。 本平台/本人仅出于信息交流、资源共享之目的进行传播&…

使用 StringRedisTemplate 实现 ZSet 滚动查询(处理相同分数场景)

1. 为什么需要改进当 ZSet 中存在相同分数 (score) 的元素时&#xff0c;单纯使用分数作为偏移会导致数据漏查或重复。例如&#xff1a;多条记录具有相同时间戳&#xff08;作为分数&#xff09;分页查询时可能跳过相同分数的元素或重复查询相同分数的元素改进方案&#xff1a;…

【Android】安装2025版AndroidStudio开发工具开发老安卓旧版App

为了开发老旧的安卓App&#xff0c;这里记录一下2025版AndroidStudio的安装过程&#xff0c;如果卸载以后&#xff0c;可以按照此文章的步骤顺利重新安装继续使用。 文章目录安装包Android SDK新建项目新建页面构建项目Gradle下载失败构建失败构建完成编译失败安装失败关于APP在…

Python跳过可迭代对象前部元素完全指南:从基础到高并发系统实战

引言&#xff1a;跳过前部元素的核心价值在数据处理和系统开发中&#xff0c;跳过可迭代对象的前部元素是常见且关键的操作。根据2024年数据处理报告&#xff1a;92%的数据清洗需要跳过文件头部85%的日志分析需要忽略初始记录78%的网络协议处理需跳过头部信息65%的机器学习训练…

ConcurrentHashMap扩容机制

ConcurrentHashMap的扩容为了提高效率&#xff0c;是多线程并发的每个线程控制一部分范围节点的扩容(根据cpu与数组长度确定控制多大范围)有两个核心参数sizeCtl&#xff1a;标记扩容状态 负数时代表正在扩容&#xff0c;存储量参与扩容的线程数&#xff0c;正数代表出发扩容的…

Spring Cloud Gateway 进行集群化部署

如果将 Gateway 单独部署为一个服务而不做任何高可用处理&#xff0c;它确实会成为一个单点故障&#xff08;SPOF, Single Point of Failure&#xff09;。如果这个唯一的 Gateway 实例因为服务器宕机、应用崩溃、部署更新或其他任何原因而不可用&#xff0c;那么整个系统的所有…

计算机网络:以太网中的数据传输

以太网中&#xff0c;数据的传输依赖于一系列标准化的技术规范&#xff0c;核心包括帧结构封装、介质访问控制机制和物理层编码技术&#xff0c;具体如下&#xff1a; 1. 以“帧&#xff08;Frame&#xff09;”为基本传输单元 以太网在数据链路层将网络层的数据包&#xff08;…

元器件--USB TypC接口

USB TypC接口下图这些都是USB接口A口与B口的区别USB A口和B口最初由USB-IF在1996年引入。根据当时的USB协议&#xff0c;A口主要用于主设备&#xff08;如电脑&#xff09;&#xff0c;而B口则用于从设备&#xff08;如打印机和摄像头&#xff09;。随着USB-C接口的日益普及&am…

多线程之HardCodedTarget(type=OssFileClient, name=file, url=http://file)异常

多线程之HardCodedTarget(typeOssFileClient, namefile, urlhttp://file)异常 摘要&#xff1a; 文档描述了多线程环境下调用Feign客户端OssFileClient时出现的HardCodedTarget异常。异常发生在异步保存文件到ES时&#xff0c;Feign调用未返回预期结果而直接打印了客户端对象。…

计算机视觉(十二):人工智能、机器学习与深度学习

人工智能 (AI)&#xff1a;宏大的目标 人工智能是最广泛、最宏大的概念&#xff0c;它的目标是让机器能够模仿人类的智能行为&#xff0c;例如&#xff1a; 推理&#xff1a;像下棋程序一样&#xff0c;通过逻辑来做决策。规划&#xff1a;为实现一个目标而制定步骤&#xff0c…