深度學習:歸一化技術

在深度學習中,歸一化技術是提高模型訓練效率和性能的重要手段。歸一化通過調整輸入數據的分布,使得模型在訓練過程中更易于收斂,減少過擬合的風險。本文將介紹幾種常見的歸一化技術,包括特征歸一化、批歸一化、層歸一化和實例歸一化。
在這里插入圖片描述

一、特征歸一化(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)x?min(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?=m1?i=1m?xi?
    其中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?=m1?i=1m?(xi??μB?)2
  • ?\epsilon?是一個小常數,通常設置為 1e?51e-51e?51e?81e-81e?8,用于防止除零錯誤。

批歸一化的主要步驟如下:

  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μ=d1?i=1d?xi?
    其中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=d1?i=1d?(xi??μ)2
  • ?\epsilon?是一個小常數,通常設置為1e?51e-51e?51e?81e-81e?8,用于防止除零錯誤。

層歸一化的主要步驟如下:

  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…