可以做問卷賺錢的網(wǎng)站免費網(wǎng)站誰有靠譜的
文章目錄
- 權(quán)重初始化方法
- Xavier初始化(Xavier initialization)
- Kaiming初始化,也稱為He初始化
- LeCun 初始化
- 正態(tài)分布與均勻分布
- Orthogonal Initialization
- Sparse Initialization
- n_in和n_out
- 代碼實現(xiàn)
權(quán)重初始化方法
Xavier初始化(Xavier initialization)
是一種用于初始化神經(jīng)網(wǎng)絡(luò)權(quán)重的方法,也稱為Glorot初始化。更有效地傳播信號并減少梯度消失或梯度爆炸的問題。適用于激活函數(shù)為tanh或sigmoid的情況。
Xavier初始化的計算方法如下:
- Glorot(或 Xavier)初始化:
- 適用于激活函數(shù)如sigmoid和tanh。
- 初始化公式: σ = 2 n in + n out \sigma = \sqrt{\frac{2}{n_{\text{in}} + n_{\text{out}}}} σ=nin?+nout?2??
其中, n in n_{\text{in}} nin? 是輸入單元數(shù), n out n_{\text{out}} nout? 是輸出單元數(shù)。
對于單個神經(jīng)元的權(quán)重w
,從均勻分布
或正態(tài)分布
中隨機采樣,具體取決于所選擇的激活函數(shù):
- 如果使用
tanh激活函數(shù)
,從均勻分布
采樣:- 采樣范圍:
[-sqrt(6 / (n_in + n_out)), sqrt(6 / (n_in + n_out))]
- 其中
n_in
是上一層的輸入節(jié)點數(shù)量,n_out
是當前層的輸出節(jié)點數(shù)量。
- 采樣范圍:
- 如果使用
sigmoid激活函數(shù)
,從正態(tài)分布
采樣:- 均值:0
- 方差:
sqrt(2 / (n_in + n_out))
- 其中n_in是上一層的輸入節(jié)點數(shù)量,n_out是當前層的輸出節(jié)點數(shù)量。
Kaiming初始化,也稱為He初始化
- He 初始化:
- 適用于ReLU及其變種(如LeakyReLU)激活函數(shù)。
- 初始化公式: σ = 2 n in \sigma = \sqrt{\frac{2}{n_{\text{in}}}} σ=nin?2??
這種初始化方法主要用于修正線性單元(Rectified Linear Units,ReLU)激活函數(shù)的神經(jīng)網(wǎng)絡(luò)。
與Xavier初始化適用于tanh和sigmoid等S型激活函數(shù)不同,Kaiming初始化專門針對ReLU激活函數(shù)
的特性進行優(yōu)化。ReLU是一個常用的非線性激活函數(shù),它在輸入大于零時保持不變,在輸入小于等于零時輸出為零。
Kaiming初始化的計算方法如下:
對于單個神經(jīng)元的權(quán)重w,從均勻分布或正態(tài)分布中隨機采樣,具體取決于所選擇的激活函數(shù):
-
如果使用
ReLU激活函數(shù)
,從正態(tài)分布
采樣:- 均值:0
- 方差:
sqrt(2 / n_in)
- 其中n_in是上一層的輸入節(jié)點數(shù)量。
-
對于帶有ReLU激活的卷積層,可以使用相同的初始化方法,只是需要考慮卷積層的輸入通道數(shù)量(即n_in)。
LeCun 初始化
- 適用于Sigmoid激活函數(shù)。
- 初始化公式: σ = 1 n in \sigma = \sqrt{\frac{1}{n_{\text{in}}}} σ=nin?1??
正態(tài)分布與均勻分布
- 使用較小的標準差(如0.01)從正態(tài)分布中采樣權(quán)重。
- 使用較小的范圍(如-0.01到0.01)從均勻分布中采樣權(quán)重。
Orthogonal Initialization
- 使用正交矩陣初始化權(quán)重。這種初始化方法對于某些任務(wù)和模型架構(gòu)可能很有益。
Sparse Initialization
- 將大部分權(quán)重初始化為0,只初始化一小部分非零的權(quán)重。
n_in和n_out
n_in
和n_out
分別表示神經(jīng)網(wǎng)絡(luò)層的輸入節(jié)點數(shù)量和輸出節(jié)點數(shù)量。這些節(jié)點也稱為神經(jīng)元,它們是網(wǎng)絡(luò)的基本組成部分。
-
n_in:代表上一層(前一層)的節(jié)點數(shù)量,也就是當前層的輸入數(shù)量。在神經(jīng)網(wǎng)絡(luò)中,每個神經(jīng)元都會接收來自上一層所有節(jié)點的輸入,這些輸入被加權(quán)和后傳遞給當前神經(jīng)元的激活函數(shù)。因此,n_in指的是上一層與當前層之間的連接數(shù)量。
-
n_out:代表當前層的節(jié)點數(shù)量,也就是當前層的輸出數(shù)量。每個神經(jīng)元會將經(jīng)過激活函數(shù)處理后的結(jié)果傳遞給下一層所有節(jié)點,形成下一層的輸入。因此,n_out指的是當前層與下一層之間的連接數(shù)量。
代碼實現(xiàn)
#include <iostream>
#include <Eigen/Dense>
#include <random>
#include <cmath>Eigen::MatrixXd glorotInitialize(int rows, int cols);
Eigen::MatrixXd heInitialize(int rows, int cols);
Eigen::MatrixXd lecunInitialize(int rows, int cols);
Eigen::MatrixXd normalDistributionInitialize(int rows, int cols, double std_dev=0.01);
Eigen::MatrixXd uniformDistributionInitialize(int rows, int cols, double limit=0.01);
Eigen::MatrixXd orthogonalInitialize(int rows, int cols);
// Sparse Initialization需要額外參數(shù)來確定稀疏度,這里我們使用一個簡化版本,指定一個非零的權(quán)重數(shù)。
Eigen::MatrixXd sparseInitialize(int rows, int cols, int nonZeroCount);//1. **Glorot (Xavier) Initialization**:Eigen::MatrixXd glorotInitialize(int rows, int cols) {std::random_device rd;std::mt19937 gen(rd());double limit = sqrt(6.0 / (rows + cols));std::uniform_real_distribution<> dis(-limit, limit);Eigen::MatrixXd matrix(rows, cols);for(int i = 0; i < rows; i++) {for(int j = 0; j < cols; j++) {matrix(i, j) = dis(gen);}}return matrix;
}//**He Initialization**:Eigen::MatrixXd heInitialize(int rows, int cols) {std::random_device rd;std::mt19937 gen(rd());double std_dev = sqrt(2.0 / rows);std::normal_distribution<> dis(0, std_dev);Eigen::MatrixXd matrix(rows, cols);for(int i = 0; i < rows; i++) {for(int j = 0; j < cols; j++) {matrix(i, j) = dis(gen);}}return matrix;
}//3. **LeCun Initialization**:Eigen::MatrixXd lecunInitialize(int rows, int cols) {std::random_device rd;std::mt19937 gen(rd());double std_dev = sqrt(1.0 / rows);std::normal_distribution<> dis(0, std_dev);Eigen::MatrixXd matrix(rows, cols);for(int i = 0; i < rows; i++) {for(int j = 0; j < cols; j++) {matrix(i, j) = dis(gen);}}return matrix;
}//4. **Normal Distribution Initialization**:Eigen::MatrixXd normalDistributionInitialize(int rows, int cols, double std_dev) {std::random_device rd;std::mt19937 gen(rd());std::normal_distribution<> dis(0, std_dev);Eigen::MatrixXd matrix(rows, cols);for(int i = 0; i < rows; i++) {for(int j = 0; j < cols; j++) {matrix(i, j) = dis(gen);}}return matrix;
}//5. **Uniform Distribution Initialization**:Eigen::MatrixXd uniformDistributionInitialize(int rows, int cols, double limit) {std::random_device rd;std::mt19937 gen(rd());std::uniform_real_distribution<> dis(-limit, limit);Eigen::MatrixXd matrix(rows, cols);for(int i = 0; i < rows; i++) {for(int j = 0; j < cols; j++) {matrix(i, j) = dis(gen);}}return matrix;
}//6. **Orthogonal Initialization**:
Eigen::MatrixXd orthogonalInitialize(int rows, int cols) {// 創(chuàng)建一個隨機矩陣std::random_device rd;std::mt19937 gen(rd());std::normal_distribution<> dis(0, 1);Eigen::MatrixXd randomMatrix(rows, cols);for(int i = 0; i < rows; i++) {for(int j = 0; j < cols; j++) {randomMatrix(i, j) = dis(gen);}}// 使用QR分解獲得正交矩陣Eigen::HouseholderQR<Eigen::MatrixXd> qr(randomMatrix);Eigen::MatrixXd orthogonalMatrix = qr.householderQ();// 如果您需要一個具有特定維度的正交矩陣(例如rows != cols),您可以選擇一個子矩陣return orthogonalMatrix.block(0, 0, rows, cols);
}//7. **Sparse Initialization**:Eigen::MatrixXd sparseInitialize(int rows, int cols, int nonZeroCount) {Eigen::MatrixXd matrix = Eigen::MatrixXd::Zero(rows, cols);std::random_device rd;std::mt19937 gen(rd());std::uniform_real_distribution<> dis(-1, 1);for(int i = 0; i < nonZeroCount; i++) {int r = rand() % rows;int c = rand() % cols;matrix(r, c) = dis(gen);}return matrix;
}
int main() {int rows = 5;int cols = 5;// Glorot InitializationEigen::MatrixXd weights_glorot = glorotInitialize(rows, cols);std::cout << "Glorot Initialized Weights:" << std::endl << weights_glorot << std::endl << std::endl;// He InitializationEigen::MatrixXd weights_he = heInitialize(rows, cols);std::cout << "He Initialized Weights:" << std::endl << weights_he << std::endl << std::endl;// LeCun InitializationEigen::MatrixXd weights_lecun = lecunInitialize(rows, cols);std::cout << "LeCun Initialized Weights:" << std::endl << weights_lecun << std::endl << std::endl;// Normal Distribution InitializationEigen::MatrixXd weights_normal = normalDistributionInitialize(rows, cols);std::cout << "Normal Distribution Initialized Weights:" << std::endl << weights_normal << std::endl << std::endl;// Uniform Distribution InitializationEigen::MatrixXd weights_uniform = uniformDistributionInitialize(rows, cols);std::cout << "Uniform Distribution Initialized Weights:" << std::endl << weights_uniform << std::endl << std::endl;// Sparse Initializationint nonZeroCount = 10; // As an example, set 10 weights to non-zero valuesEigen::MatrixXd weights_sparse = sparseInitialize(rows, cols, nonZeroCount);std::cout << "Sparse Initialized Weights with " << nonZeroCount << " non-zero values:" << std::endl << weights_sparse << std::endl;return 0;
}