一文讀懂現代卷積神經網絡—稠密連接網絡(DenseNet)

目錄

什么是 DenseNet?

?稠密塊(Dense Block)詳解

一、稠密塊的核心思想

二、稠密塊的結構組成

1. 卷積單元(的結構)

2. 密集連接的具體方式

3. 關鍵參數:增長率(Growth Rate, k)

4. 過渡層(Transition Layer)

三、稠密塊的優勢

四、與 ResNet 殘差塊的對比

過渡層(Transition Layer)詳解

一、什么是過渡層?

二、過渡層的核心作用

三、過渡層的典型結構

四、設計細節與參數

五、與 ResNet 中對應組件的對比

DenseNet 的作用

DenseNet 與 ResNet 的核心區別

ResNet和DenseNet的結構示意圖

為啥卷積塊中采用?“批量歸一化(BN)→ 激活函數 → 卷積層”?的順序?

1. 批量歸一化(BN)放在最前:從根源穩定輸入分布

2. 激活函數放在 BN 之后:讓激活更 “有效”

3. 卷積層放在最后:利用穩定輸入提升參數學習效率

?完整代碼

實驗結果


什么是 DenseNet?

稠密連接網絡(Dense Convolutional Network,簡稱 DenseNet)是 2017 年由 Huang 等人提出的一種深層卷積神經網絡,其核心創新是“稠密連接(Dense Connection)”:網絡中的每個層都會與前面所有層直接連接,即第l層的輸入是前l-1層的輸出的拼接(而非簡單相加)。

核心結構

  • 稠密塊(Dense Block):由多個卷積層組成,層間通過稠密連接融合特征。設第i層的輸出為x_i,則第l層的輸入為前所有層輸出的拼接:x_l = H_l([x_0, x_1, ..., x_{l-1}])其中[x_0, ..., x_{l-1}]表示通道維度上的拼接,H_l是第l層的卷積操作(含 BN、ReLU、卷積核)。

  • 過渡層(Transition Layer):用于連接不同的稠密塊,通過 1×1 卷積降維和 2×2 平均池化減小特征圖尺寸,防止網絡參數爆炸。

  • 稠密塊(dense block)和過渡層(transition layer)。 前者定義如何連接輸入和輸出,而后者則控制通道數量,使其不會太復雜。

?稠密塊(Dense Block)詳解

稠密塊(Dense Block)是深度學習網絡?DenseNet(Densely Connected Convolutional Networks)?的核心組成單元,其設計核心是通過密集連接(Dense Connection)?實現極致的特征重用,是對傳統卷積網絡和 ResNet 中 “跳躍連接” 的進一步升級。

一、稠密塊的核心思想

傳統卷積網絡中,每一層的輸入僅來自上一層;ResNet 通過 “跳躍連接” 讓層的輸入包含上一層的輸出(元素相加);而稠密塊則更進一步 ——每一層的輸入是前面所有層的輸出的拼接(Concatenation)

具體來說,若稠密塊包含?L?層,第?l?層(記為H_l)的輸入是第?0,1,...,l-1?層的輸出的拼接,輸出為?x_l = H_l([x_0, x_1, ..., x_{l-1}]),其中:

  • x_0?是稠密塊的初始輸入特征圖;
  • [x_0, x_1, ..., x_{l-1}]?表示將這些特征圖在通道維度上拼接;
  • H_l是第?l?層的卷積操作(通常包含 BN、ReLU、卷積等子操作)。

這種 “密集連接” 使得特征在網絡中能夠被充分傳遞和復用,從根本上解決了深層網絡的 “特征衰減” 問題。

二、稠密塊的結構組成

一個典型的稠密塊由多個 “卷積單元” 和 “密集連接” 組成,同時為了控制計算量,通常會包含瓶頸層(Bottleneck)?和過渡層(Transition Layer)(過渡層用于連接不同稠密塊,非稠密塊內部結構,但需結合理解)。

1. 卷積單元(H_l的結構)

稠密塊中的每一層?\(H_l\)?通常由以下子操作組成(順序固定):

  • BN(Batch Normalization):標準化特征,加速訓練;
  • ReLU:非線性激活,增強表達能力;
  • 1x1 卷積(可選,瓶頸層):減少輸入特征的通道數(如將通道數壓縮至原來的 1/4),降低計算量;
  • 3x3 卷積:提取局部特征,輸出固定數量的特征圖(由 “增長率” 決定)。

其中,1x1 卷積作為 “瓶頸層” 是 DenseNet 的重要優化:若直接對拼接后的高維特征做 3x3 卷積,計算量會爆炸;而 1x1 卷積可先將通道數降至較低維度(如 4k,k 為增長率),再用 3x3 卷積輸出 k 個特征圖,既保證特征提取效率,又控制了參數規模。

2. 密集連接的具體方式

假設稠密塊的初始輸入特征圖為x_0(通道數為?k_0),每一層的輸出特征圖通道數為?k(即 “增長率”),則:

  • 第 1 層輸入:x_0,輸出:x_1 = H_1(x_0)(通道數?k);
  • 第 2 層輸入:[x_0, x_1](通道數k_0 + k),輸出:x_2 = H_2([x_0, x_1])(通道數?k);
  • 第 3 層輸入:[x_0, x_1, x_2](通道數?k_0 + 2k),輸出:x_3 = H_3([x_0, x_1, x_2])(通道數?k);
  • ...
  • 第?L?層輸入:[x_0, x_1, ..., x_{L-1}](通道數?k_0 + (L-1)k),輸出:x_L = H_L([x_0, ..., x_{L-1}])(通道數?k)。

最終,整個稠密塊的輸出是所有層輸出的拼接:[x_0, x_1, ..., x_L](通道數?k_0 + Lk)。

3. 關鍵參數:增長率(Growth Rate, k)

增長率?k?是稠密塊的核心參數,定義為每一層輸出的特征圖通道數。它控制了特征圖的增長速度:

  • 若?k?較小(如 12、24),即使層數較多,拼接后的總通道數也不會過大,保證計算效率;
  • 實驗表明,較小的?k(如 k=12)即可讓 DenseNet 達到優異性能,說明密集連接對特征的利用率極高。
4. 過渡層(Transition Layer)

稠密塊之間通過 “過渡層” 連接,作用是壓縮特征圖通道數并降低尺寸,避免網絡冗余

  • 過渡層通常由 “BN + 1x1 卷積 + 2x2 平均池化” 組成;
  • 1x1 卷積將前一個稠密塊的輸出通道數壓縮(如壓縮至原來的 θ 倍,θ∈(0,1],稱為 “壓縮因子”);
  • 平均池化將特征圖尺寸減半(如從 32x32 變為 16x16),控制網絡深度和計算量。

三、稠密塊的優勢

  1. 極致的特征重用 每一層都能直接訪問前面所有層的特征,特征在網絡中被反復利用,避免了傳統網絡中 “特征隨層數增加而衰減” 的問題。

  2. 緩解梯度消失 反向傳播時,梯度可通過密集連接直接從深層傳遞到淺層,大幅緩解深層網絡的梯度消失問題,使訓練更深的網絡成為可能。

  3. 參數效率更高 由于特征重用充分,DenseNet 無需像其他網絡(如 ResNet)那樣通過增加通道數提升性能,小增長率?k?即可實現高準確率,參數規模通常小于 ResNet。

  4. 正則化效果 密集連接增加了層之間的相互依賴,一定程度上減少了過擬合,提升模型泛化能力。

四、與 ResNet 殘差塊的對比

對比維度稠密塊(Dense Block)殘差塊(Residual Block)
連接方式特征圖拼接(Concatenation)特征圖元素相加(Element-wise Add)
輸入來源前面所有層的輸出僅上一層的輸出(跨層相加)
特征利用效率極高(所有歷史特征直接參與當前層)較高(僅上一層特征與當前層特征融合)
特征維度變化隨層數線性增長(由增長率 k 控制)基本不變(相加不改變通道數)
計算量控制依賴瓶頸層(1x1 卷積)和過渡層依賴殘差連接的 “恒等映射”

過渡層(Transition Layer)詳解

過渡層(Transition Layer)是稠密連接網絡(DenseNet)?中的關鍵組件,主要用于連接相鄰的稠密塊(Dense Block),并實現特征圖的降維和壓縮,在保證網絡效率的同時控制模型復雜度。以下從定義、作用、結構細節及設計意義展開詳解:

一、什么是過渡層?

過渡層是 DenseNet 中位于兩個稠密塊之間的連接模塊,其核心功能是對前一個稠密塊輸出的特征圖進行處理,為下一個稠密塊提供合適維度的輸入。由于稠密塊會通過密集連接生成大量特征圖(如一個包含 12 層的稠密塊可能輸出數百個特征圖),過渡層的作用類似于 “橋梁”,通過降維減少特征數量,避免網絡參數和計算量過度膨脹。

二、過渡層的核心作用
  1. 特征降維 稠密塊的輸出特征圖數量通常較多(例如,每個稠密塊會累計生成?k \times L?個特征圖,其中?k?是增長率,L?是塊內層數)。過渡層通過卷積操作將特征圖數量按比例壓縮(通常壓縮至原來的?\theta?倍,\theta稱為壓縮因子,一般取 0.5),減少后續計算量。

  2. 空間尺寸縮減 通過池化操作(通常是 2×2 的平均池化)將特征圖的空間尺寸(高和寬)縮小一半,與傳統卷積網絡中 “下采樣→增大感受野” 的設計思路一致,幫助網絡捕捉更全局的特征。

  3. 特征融合與平滑 過渡層中的卷積操作(通常是 1×1 卷積)可以對稠密塊輸出的多通道特征進行融合,減少冗余信息,同時保持特征的連續性,為下一個稠密塊的輸入提供更精煉的特征。

三、過渡層的典型結構

過渡層的結構簡潔,通常由兩個操作組成,按順序執行:

  1. 1×1 卷積

    • 作用:對輸入特征圖進行通道壓縮(降維),并融合通道間的信息。
    • 細節:卷積核數量為前一個稠密塊輸出特征數的\theta倍(\theta \in (0,1]),當\theta=1時不壓縮),步長為 1, padding 為 0。
    • 示例:若前一個稠密塊輸出 200 個特征圖,\theta=0.5,則 1×1 卷積后輸出 100 個特征圖。
  2. 2×2 平均池化

    • 作用:將特征圖的空間尺寸(如H \times W)縮減為?H/2 \times W/2,實現下采樣。
    • 細節:池化核大小 2×2,步長 2,無 padding,確保尺寸減半。
四、設計細節與參數
  • 壓縮因子\theta:是 DenseNet 的重要超參數,控制特征壓縮比例。當?\theta < 1時,DenseNet 稱為 “壓縮 DenseNet”(如 DenseNet-C),若?\theta = 1則不壓縮。實驗中\theta =0.5?是常用設置,可在精度和效率間取得平衡。
  • 激活函數與歸一化:過渡層的 1×1 卷積后通常會跟隨批量歸一化(BN)和 ReLU 激活函數,確保特征分布穩定并引入非線性。
五、與 ResNet 中對應組件的對比

在 ResNet 中,連接不同殘差塊的下采樣通常通過 “stride=2 的 3×3 卷積” 或 “單獨的池化層 + 卷積” 實現,目的是縮減尺寸但不刻意壓縮通道數。而過渡層的核心差異在于:

  • 主動降維:通過 1×1 卷積和壓縮因子主動減少通道數,更注重控制模型參數。
  • 與稠密塊的配合:由于稠密塊會累計大量特征,過渡層的降維是 DenseNet 控制復雜度的關鍵,而 ResNet 的殘差塊不會累計特征,因此無需專門的壓縮機制。

DenseNet 的作用

  1. 緩解梯度消失問題 稠密連接讓每個層都能直接接收前面所有層的梯度(反向傳播時,梯度無需經過多層累積),確保深層網絡的梯度能有效傳遞到淺層,解決了深層網絡訓練困難的問題。

  2. 促進特征復用 每個層的輸入包含前面所有層的特征(而非僅前一層),特征在網絡中被多次復用,減少了冗余特征的學習,提升了特征利用效率。例如,淺層的邊緣特征和深層的語義特征可直接融合,增強模型表達能力。

  3. 減少參數數量 由于特征復用充分,DenseNet 無需像 ResNet 那樣通過增加通道數來提升性能(通道數通常遠小于 ResNet),因此參數總量更少(例如 DenseNet-121 的參數約 800 萬,僅為 ResNet-50 的 1/3)。

  4. 抑制過擬合 特征的多次復用相當于給網絡引入了 “正則化” 效果,尤其在小數據集上,過擬合風險更低,泛化能力更強。

DenseNet 與 ResNet 的核心區別

對比維度ResNet(殘差網絡)DenseNet(稠密連接網絡)
連接方式每個層僅與前一層連接(“鏈式”):\(x_l = H_l(x_{l-1}) + x_{l-1}\)每個層與前面所有層連接(“稠密”):\(x_l = H_l([x_0, ..., x_{l-1}])\)
特征融合方式殘差相加(元素級加法,要求通道數相同)特征拼接(通道級拼接,通道數隨層數累積)
通道數變化隨深度翻倍(如 64→128→256→512),通過升維提升能力單一層通道數固定(如 32),通過拼接累積總通道數(復用特征)
參數效率較低(通道數大,參數多)較高(通道數小,特征復用減少冗余參數)
計算復雜度中等(加法操作輕量,但通道數大)較高(拼接導致總通道數大,需通過過渡層控制)
梯度傳播梯度通過殘差連接間接傳遞(需經過前一層)梯度直接傳遞到所有淺層(無中間層阻礙)
適用場景超深網絡(如 ResNet-152)、大數據集(需強表達能力)中小數據集(泛化能力強)、對參數敏感的場景

ResNet和DenseNet的結構示意圖

為啥卷積塊中采用?“批量歸一化(BN)→ 激活函數 → 卷積層”?的順序?

1. 批量歸一化(BN)放在最前:從根源穩定輸入分布

BN 的核心功能是標準化輸入數據的分布(將每個通道的輸入調整為均值 0、方差 1 的標準分布),從而解決 “內部協變量偏移”。

如果將 BN 放在卷積層之后(即 “卷積→BN→激活”),則 BN 只能標準化卷積層的輸出;而放在卷積層之前(即 “BN→激活→卷積”),BN 可以直接標準化進入卷積層的原始輸入,從更早期穩定數據分布,效果更徹底:

  • 卷積層的輸入分布更穩定,參數更新時輸出變化更平緩,訓練更穩定;
  • 避免卷積層因輸入分布劇烈波動而陷入 “參數震蕩”(例如卷積核反復調整以適應突變的輸入)。
2. 激活函數放在 BN 之后:讓激活更 “有效”

激活函數(如 ReLU)的作用是引入非線性,但其效果高度依賴輸入分布:

  • ReLU 對負數輸入會 “截斷”(輸出 0),若輸入分布不穩定(例如均值偏移到負數區域),會導致大量神經元 “死亡”(輸出恒為 0);
  • BN 將輸入標準化為 “均值 0、方差 1” 的分布后,ReLU 的輸入會均勻分布在正負區間,既能保留足夠多的正輸入(激活有效神經元),又能通過負輸入的截斷引入非線性,避免激活函數失效。
3. 卷積層放在最后:利用穩定輸入提升參數學習效率

卷積層是特征提取的核心,其參數學習(通過梯度下降更新?W?和?b)需要穩定的輸入分布:

  • 經過 BN 標準化和激活函數非線性變換后,輸入到卷積層的數據分布已非常穩定,卷積核可以更高效地學習 “有意義的特征模式”(例如邊緣、紋理);
  • 若卷積層放在最前,其輸出分布會因參數更新而劇烈變化,后續的 BN 和激活函數需要不斷 “適配” 這種變化,降低訓練效率。

先穩定分布,再引入非線性,最后高效提取特征

?完整代碼

"""
文件名: 7.7  稠密連接網絡(DenseNet)
作者: 墨塵
日期: 2025/7/14
項目名: dl_env
備注: 實現完整的DenseNet網絡,包含稠密塊、過渡層及端到端訓練流程,用于Fashion-MNIST分類
"""import torch
from torch import nn
from d2l import torch as d2l
# 手動顯示圖像相關庫
import matplotlib.pyplot as plt  # 繪圖庫
import matplotlib.text as text  # 用于修改文本繪制(解決符號顯示問題)# -------------------------- 核心解決方案:解決文本顯示問題 --------------------------
# 定義替換函數:將Unicode減號(U+2212,可能導致顯示異常)替換為普通減號(-)
def replace_minus(s):"""解決Matplotlib中Unicode減號顯示異常的問題參數:s: 待處理的字符串或其他類型對象返回:處理后的字符串或原始對象(非字符串類型)"""if isinstance(s, str):  # 判斷輸入是否為字符串return s.replace('\u2212', '-')  # 替換特殊減號為普通減號return s  # 非字符串直接返回# 重寫matplotlib的Text類的set_text方法,解決減號顯示異常
original_set_text = text.Text.set_text  # 保存原始的set_text方法
def new_set_text(self, s):"""重寫后的文本設置方法,在設置文本前先處理減號顯示問題"""s = replace_minus(s)  # 調用替換函數處理文本中的減號return original_set_text(self, s)  # 調用原始方法設置文本
text.Text.set_text = new_set_text  # 應用重寫后的方法# -------------------------- 字體配置(確保中文和數學符號正常顯示)--------------------------
plt.rcParams["font.family"] = ["SimHei"]  # 設置中文字體(支持中文顯示)
plt.rcParams["text.usetex"] = True  # 使用LaTeX渲染文本(提升數學符號顯示效果)
plt.rcParams["axes.unicode_minus"] = True  # 確保負號正確顯示(避免顯示為方塊)
plt.rcParams["mathtext.fontset"] = "cm"  # 設置數學符號字體為Computer Modern(更美觀)
d2l.plt.rcParams.update(plt.rcParams)  # 讓d2l庫的繪圖工具繼承上述字體配置# 定義卷積塊:BN + ReLU + 3x3卷積(DenseNet的基礎單元)
def conv_block(input_channels, num_channels):"""構建DenseNet中的基礎卷積單元,實現特征提取參數:input_channels: 輸入特征圖的通道數num_channels: 輸出特征圖的通道數(即增長率的一部分)返回:nn.Sequential: 包含批量歸一化、激活函數和卷積層的序列模塊"""return nn.Sequential(nn.BatchNorm2d(input_channels),  # 批量歸一化:穩定輸入分布,加速訓練nn.ReLU(),  # ReLU激活:引入非線性,增強特征表達能力# 3x3卷積:提取局部空間特征,padding=1確保輸出尺寸與輸入相同nn.Conv2d(input_channels, num_channels, kernel_size=3, padding=1))class DenseBlock(nn.Module):"""稠密塊(DenseBlock):DenseNet的核心組件,通過密集連接實現特征復用參數:num_convs: 塊內包含的卷積塊數量input_channels: 初始輸入通道數num_channels: 每個卷積塊的輸出通道數(即"增長率",控制特征增長速度)"""def __init__(self, num_convs, input_channels, num_channels):super(DenseBlock, self).__init__()layer = []# 逐個添加卷積塊,每個卷積塊的輸入通道數隨層數遞增for i in range(num_convs):# 第i個卷積塊的輸入通道數 = 初始通道數 + i×增長率# 例如:第0個卷積塊輸入=input_channels,第1個=input_channels+num_channels,以此類推layer.append(conv_block(input_channels + i * num_channels,  # 動態計算輸入通道數num_channels  # 固定輸出通道數(增長率)))self.net = nn.Sequential(*layer)  # 將所有卷積塊組合成序列def forward(self, X):"""前向傳播:通過密集連接拼接所有卷積塊的輸出參數:X: 輸入特征圖,形狀為(batch_size, input_channels, height, width)返回:拼接后的特征圖,形狀為(batch_size, final_channels, height, width)其中final_channels = input_channels + num_convs×num_channels"""for blk in self.net:Y = blk(X)  # 當前卷積塊的輸出# 在通道維度(dim=1)上拼接原始輸入X和當前輸出Y(密集連接的核心)X = torch.cat((X, Y), dim=1)return X# 過渡層:連接兩個稠密塊,實現特征降維和尺寸縮減
def transition_block(input_channels, num_channels):"""過渡層:壓縮特征通道數并減小空間尺寸,避免網絡參數爆炸參數:input_channels: 輸入特征圖的通道數(前一個稠密塊的輸出)num_channels: 輸出特征圖的通道數(通常為輸入的1/2,即壓縮因子0.5)返回:nn.Sequential: 包含批量歸一化、激活、卷積和池化的序列模塊"""return nn.Sequential(nn.BatchNorm2d(input_channels),  # 批量歸一化:穩定過渡層輸入分布nn.ReLU(),  # 激活函數:引入非線性# 1x1卷積:減少通道數(核心降維操作,參數少且計算高效)nn.Conv2d(input_channels, num_channels, kernel_size=1),# 2x2平均池化:將空間尺寸減半(height和width各除以2)nn.AvgPool2d(kernel_size=2, stride=2))if __name__ == '__main__':# -------------------------- 測試核心組件功能 --------------------------# 測試1:稠密塊(2個卷積塊,輸入3通道,增長率10)dense_blk = DenseBlock(num_convs=2, input_channels=3, num_channels=10)X = torch.randn(4, 3, 8, 8)  # 隨機輸入:4個樣本,3通道,8x8尺寸Y = dense_blk(X)print(f"稠密塊輸出形狀: {Y.shape}")  # 預期:(4, 3+2×10=23, 8, 8)# 測試2:過渡層(輸入23通道,輸出10通道)trans_blk = transition_block(input_channels=23, num_channels=10)Z = trans_blk(Y)print(f"過渡層輸出形狀: {Z.shape}")  # 預期:(4, 10, 4, 4)(尺寸減半)# -------------------------- 構建完整DenseNet網絡 --------------------------# 第一個模塊:初始卷積+池化(預處理輸入圖像)b1 = nn.Sequential(# 7x7大卷積:初步提取全局特征,步長2壓縮尺寸nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),nn.BatchNorm2d(64),  # 批量歸一化nn.ReLU(),  # 激活# 3x3最大池化:進一步將尺寸減半(為后續稠密塊做準備)nn.MaxPool2d(kernel_size=3, stride=2, padding=1))# 配置稠密塊參數num_channels = 64  # 初始通道數(與b1輸出通道一致)growth_rate = 32  # 增長率:每個卷積塊的輸出通道數(控制特征增長速度)num_convs_in_dense_blocks = [4, 4, 4, 4]  # 每個稠密塊包含的卷積塊數量(總4個稠密塊)# 構建后續模塊(稠密塊+過渡層)blks = []for i, num_convs in enumerate(num_convs_in_dense_blocks):# 添加稠密塊blks.append(DenseBlock(num_convs, num_channels, growth_rate))# 更新當前通道數:稠密塊輸出通道 = 輸入通道 + 卷積塊數量×增長率num_channels += num_convs * growth_rate# 除最后一個稠密塊外,添加過渡層(通道數減半)if i != len(num_convs_in_dense_blocks) - 1:blks.append(transition_block(num_channels, num_channels // 2))num_channels = num_channels // 2  # 更新通道數為過渡層輸出# 組裝完整網絡net = nn.Sequential(b1,  # 初始模塊*blks,  # 所有稠密塊和過渡層nn.BatchNorm2d(num_channels),  # 最終批量歸一化nn.ReLU(),  # 激活nn.AdaptiveAvgPool2d((1, 1)),  # 全局平均池化:將特征圖壓縮為1x1nn.Flatten(),  # 展平為一維向量nn.Linear(num_channels, 10)  # 全連接層:輸出10類(Fashion-MNIST))# -------------------------- 訓練DenseNet模型 --------------------------# 訓練參數lr = 0.1  # 學習率(DenseNet對學習率較魯棒)num_epochs = 10  # 訓練輪數batch_size = 256  # 批量大小# 加載Fashion-MNIST數據集(調整圖像大小為96x96適配網絡)train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size, resize=96)# 啟動訓練(使用d2l庫的訓練函數,自動支持GPU)print("\n開始訓練DenseNet模型...")d2l.train_ch6(net, train_iter, test_iter,num_epochs, lr,device=d2l.try_gpu()  # 自動選擇GPU(如有))# 顯示訓練曲線(損失+準確率)plt.show(block=True)

實驗結果

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88933.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88933.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88933.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關于僵尸進程

深入理解僵尸進程&#xff1a;成因、危害與解決方案 進程終止的條件 我們先了解一下進程銷毀的條件&#xff1a; 調用了exit函數在main函數中執行了return語句 無論采用哪種方式&#xff0c;都會有一個返回值&#xff0c;這個返回值由操作系統傳遞給該進程的父進程。操作系統不…

深入解析進程、線程與協程:現代并發編程的三大支柱

深入解析進程、線程與協程&#xff1a;現代并發編程的三大支柱在計算資源日益豐富的時代&#xff0c;理解并發執行機制已成為每位開發者的必修課。本文將帶你深入探索操作系統中的三大并發模型&#xff1a;進程、線程與協程&#xff0c;揭開它們的神秘面紗。引言&#xff1a;并…

奇安信下一代防火墻SecGate3600

一、實驗拓撲&#xff1a;二、實驗目的&#xff08;1&#xff09;讓內網可以訪問外網。&#xff08;2&#xff09;讓外網能夠訪問dmz區域的web服務器。&#xff08;3&#xff09;測試防火墻的防毒功能&#xff0c;并進行檢測。三、實驗步驟&#xff08;1&#xff09;防火墻配置…

基于STM32的智能抽水灌溉系統設計(藍牙版)

????大家好&#xff0c;這里是5132單片機畢設設計項目分享&#xff0c;今天給大家分享的是基于《基于STM32的智能抽水灌溉系統設計》。 目錄 1、系統功能 2.1、硬件清單 2.2、功能介紹 2.3、控制模式 2、演示視頻和實物 3、系統設計框圖 4、軟件設計流程圖 5、原理…

CISSP知識點匯總- 通信與網絡安全

CISSP知識點匯總 域1---安全與風險管理域2---資產安全域3---安全工程域4---通信與網絡安全域5---訪問控制域6---安全評估與測試域7---安全運營域8---應用安全開發一、安全網絡架構和保護網絡組件 1、OSI 7層協議模型 應用層:SMTP、HTTP、SNMP 、TELNET、 FTP、SFTP、POP3、IM…

C++怎么將可變參數傳遞給第三方可變參數接口

文章目錄&#x1f527; 1. 使用 va_list 轉發&#xff08;兼容C/C的傳統方案&#xff09;?? 2. 模板參數包轉發&#xff08;C11 類型安全方案&#xff09;&#x1f9e9; 3. 替代方案&#xff1a;參數封裝與適配**方案A&#xff1a;使用 std::initializer_list (同類型參數)**…

服務端實現阿里云OSS直傳

介紹 阿里云上傳 OSS 有兩種方式&#xff0c;一種是普通上傳&#xff0c;一種是客戶端直傳。 普通上傳&#xff0c;就是需要先將文件上傳到服務端&#xff0c;然后調用接口將文件上傳到阿里云。 當然這種方案經常出現不合理的使用方式&#xff0c;即客戶端充當服務端的角色&…

on-policy和offpolicy算法

一句話總結On-policy&#xff08;同策略&#xff09;&#xff1a;邊學邊用&#xff0c;用當前策略生成的數據更新當前策略。例子&#xff1a;演員自己演完一場戲后&#xff0c;根據觀眾反饋改進演技。Off-policy&#xff08;異策略&#xff09;&#xff1a;學用分離&#xff0c…

CA-IS3082W 隔離485 收發器芯片可能存在硬件BUG

RT&#xff0c;這個RS485 隔離收發器芯片基本上不可用。本來要買CA-IS3082WX&#xff0c;不小心在某寶買到了沒有X 的CA-IS3082W。立創上說沒有X 的版本已經停產&#xff0c;連對應的數據手冊都找不到&#xff0c;全換成WX 了。 這類半雙工485 收發器芯片電路一般都直接把DE 和…

dockerfile 筆記

# 設置JAVA版本 FROM openjdk:20-ea-17-jdk MAINTAINER aaa # 指定存儲卷, 任何向/tmp寫入的信息都不會記錄到容器存儲層 VOLUME /tmp # 拷貝運行JAR包 ARG JAR_FILE COPY app.jar /app.jar RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime RUN echo "Asia/…

高德開放平臺攜手阿里云,面向開發者推出地圖服務產品MCP Server

高德開放平臺攜手阿里云&#xff0c;面向開發者推出地圖服務產品MCP Server&#xff0c;通過技術能力與生態資源的深度協同&#xff0c;助力開發者高效構建標準化地圖服務&#xff0c;加速智能化場景落地。 高德開放平臺攜手阿里云&#xff0c;面向開發者推出MCP Server技術融合…

【論文閱讀】AdaptThink: Reasoning Models Can Learn When to Think

AdaptThink: Reasoning Models Can Learn When to Think3 Motivation3.1 理論基礎3.2 NoThinking在簡單問題中的優勢3.3 動機總結4. AdaptThink4.1 約束優化目標數學建模基本定義原始優化問題懲罰項轉換歸一化處理策略梯度實現優勢函數定義PPO風格損失函數4.2 重要性采樣策略問…

Redis高可用集群一主從復制概述

一、環境概述在分布式集群系統中為了解決服務單點故障問題&#xff0c;通常會把數據復制出多個副本部署到不同的機器中&#xff0c;滿足故障恢復和負載均衡等需求。Redis也是如此&#xff0c;它為我們提供了復制功能&#xff0c;實現了相同數據的多個Redis副本。復制功能是高可…

Java 樹形結構、層級結構數據構建

目錄前言一、樹狀結構數據庫存儲二、工具類三、測試四、自定義樹節點返回類型&#xff08;只保留部分字段&#xff09;1. 新增 TreeNodeDTO 類2.修改TreeUtil 類3.測試4.輸出前言 有時候&#xff0c;開發過程中我們會遇到一些樹狀層級結構。 比如&#xff0c;公司部門組織架構…

求解線性規劃模型最優解

歸納編程學習的感悟&#xff0c; 記錄奮斗路上的點滴&#xff0c; 希望能幫到一樣刻苦的你&#xff01; 如有不足歡迎指正&#xff01; 共同學習交流&#xff01; &#x1f30e;歡迎各位→點贊 &#x1f44d; 收藏? 留言?&#x1f4dd; 既然選擇了遠方&#xff0c;當不負青春…

達夢國產數據庫安裝

打開ISO 、文件點擊運行接受選擇安裝路徑數據初始化 新數據庫要創建數據庫實例 選擇一般用途數據庫位置 選擇所以系統用戶&#xff0c;設置初始密碼創建示例庫可以選可以不選查找最近添加文件登錄

互斥鎖與同步鎖

1. 鎖的本質&#xff1a;解決并發問題的基石在多線程/多進程環境中&#xff0c;臨界區&#xff08;Critical Section&#xff09; 是訪問共享資源的代碼段。鎖的核心目標是確保互斥訪問——任意時刻僅有一個執行單元能進入臨界區。// 典型臨界區示例 pthread_mutex_lock(&m…

高密度PCB板生產廠商深度解析

在電子制造領域&#xff0c;高密度PCB&#xff08;印制電路板&#xff09;作為核心基礎元件&#xff0c;其技術精度與生產穩定性直接影響終端產品性能。本文精選五家具備核心技術優勢的國內廠商&#xff0c;通過實地調研與行業數據驗證&#xff0c;為讀者呈現真實可信的供應商選…

力扣 hot100 Day44

98. 驗證二叉搜索樹 給你一個二叉樹的根節點 root &#xff0c;判斷其是否是一個有效的二叉搜索樹。 有效 二叉搜索樹定義如下&#xff1a; 節點的左子樹只包含 小于 當前節點的數。 節點的右子樹只包含 大于 當前節點的數。 所有左子樹和右子樹自身必須也是二叉搜索樹 //自…

【基礎架構】——軟件系統復雜度的來源(低成本、安全、規模)

目錄 一、軟件系統復雜度的來源之低成本二、軟件系統復雜度的來源之安全2.1、功能安全2.2、架構安全2.3、規模2.3.1、功能越來越多,導致系統復雜度指數級上升2.3.2、數據越來越多,系統復雜度發生質變本文來源:極客時間vip課程筆記 一、軟件系統復雜度的來源之低成本 當我們設…