神經網絡與深度學習
- 1. 神經網絡基礎
- 1.1 神經元模型與激活函數
- 1.2 神經網絡結構與前向傳播
- 2.1 損失函數與優化算法
- 均方誤差損失函數
- 交叉熵損失函數
- 梯度下降優化算法
- 2.2 反向傳播與梯度計算
- 神經元的反向傳播
- 3.1 神經元類設計與實現
- 神經元類代碼實現
- 代碼思路
- 3.2 神經網絡類構建
- 神經網絡類代碼實現
- 代碼思路
- 4.1 神經元模型與激活函數
- 4.2 神經網絡結構與前向傳播
- 4.3 深度學習框架中的關鍵組件
- 4.4 反向傳播與梯度計算
- 4.5 神經網絡類的構建與實現
- 4.6 神經網絡的訓練過程
- 代碼思路
1. 神經網絡基礎
1.1 神經元模型與激活函數
神經元是神經網絡的基本單元,其模型可以類比為生物神經元。一個神經元接收多個輸入信號,對這些信號進行加權求和,然后通過一個激活函數進行非線性變換,最終輸出一個信號。以下是用 C++ 實現一個簡單神經元的代碼示例:
#include <iostream>
#include <vector>
#include <cmath>// 定義激活函數
double sigmoid(double x) {return 1.0 / (1.0 + exp(-x));
}// 神經元類
class Neuron {
private:std::vector<double> weights; // 權重double bias; // 偏置public:// 構造函數Neuron(int input_size) {weights.resize(input_size, 0.0); // 初始化權重為0bias = 0.0; // 初始化偏置為0}// 設置權重和偏置void set_weights(const std::vector<double>& w, double b) {weights = w;bias = b;}// 前向傳播,計算輸出double forward(const std::vector<double>& inputs) {double sum = bias;for (size_t i = 0; i < inputs.size(); ++i) {sum += inputs[i] * weights[i];}return sigmoid(sum); // 使用Sigmoid激活函數}
};int main() {// 創建一個輸入大小為2的神經元Neuron neuron(2);// 設置權重和偏置std::vector<double> weights = {0.5, -0.3};double bias = 0.1;neuron.set_weights(weights, bias);// 輸入信號std::vector<double> inputs = {1.0, -2.0};// 計算輸出double output = neuron.forward(inputs);std::cout << "Neuron output: " << output << std::endl;return 0;
}
代碼思路:
- 激活函數:Sigmoid 函數是一個常用的激活函數,它將輸入映射到 (0, 1) 區間,具有平滑的梯度,適用于神經元的非線性變換。
- 神經元類:
- 成員變量:
weights
存儲輸入信號的權重,bias
是偏置項。 - 構造函數:根據輸入信號的數量初始化權重和偏置。
- 設置權重和偏置:通過
set_weights
函數設置權重和偏置。 - 前向傳播:
forward
函數計算輸入信號的加權和,加上偏置后通過激活函數輸出結果。
- 成員變量:
- 主函數:
- 創建一個神經元實例,設置權重和偏置。
- 提供輸入信號,調用
forward
函數計算輸出。
1.2 神經網絡結構與前向傳播
神經網絡由多個神經元組成,通常分為輸入層、隱藏層和輸出層。前向傳播是指從輸入層到輸出層逐層計算的過程。以下是一個簡單的兩層神經網絡的 C++ 實現:
#include <iostream>
#include <vector>
#include <cmath>// 激活函數
double sigmoid(double x) {return 1.0 / (1.0 + exp(-x));
}// 神經元類
class Neuron {
private:std::vector<double> weights;double bias;public:Neuron(int input_size) {weights.resize(input_size, 0.0);bias = 0.0;}void set_weights(const std::vector<double>& w, double b) {weights = w;bias = b;}double forward(const std::vector<double>& inputs) {double sum = bias;for (size_t i = 0; i < inputs.size(); ++i) {sum += inputs[i] * weights[i];}return sigmoid(sum);}
};// 神經網絡類
class NeuralNetwork {
private:std::vector<Neuron> hidden_layer; // 隱藏層Neuron output_neuron; // 輸出層public:NeuralNetwork(int input_size, int hidden_size) {hidden_layer.resize(hidden_size, Neuron(input_size));output_neuron = Neuron(hidden_size);}void set_weights(const std::vector<std::vector<double>>& hidden_weights,const std::vector<double>& hidden_biases,const std::vector<double>& output_weights,double output_bias) {for (size_t i = 0; i < hidden_layer.size(); ++i) {hidden_layer[i].set_weights(hidden_weights[i], hidden_biases[i]);}output_neuron.set_weights(output_weights, output_bias);}double forward(const std::vector<double>& inputs) {std::vector<double> hidden_outputs(hidden_layer.size());for (size_t i = 0; i < hidden_layer.size(); ++i) {hidden_outputs[i] = hidden_layer[i].forward(inputs);}return output_neuron.forward(hidden_outputs);}
};int main() {// 創建一個輸入大小為2,隱藏層大小為2的神經網絡NeuralNetwork nn(2, 2);// 設置權重和偏置std::vector<std::vector<double>> hidden_weights = {{0.5, -0.3}, {0.2, 0.1}};std::vector<double> hidden_biases = {0.1, -0.2};std::vector<double> output_weights = {0.4, -0.5};double output_bias = 0.3;nn.set_weights(hidden_weights, hidden_biases, output_weights, output_bias);// 輸入信號std::vector<double> inputs = {1.0, -2.0};// 計算輸出double output = nn.forward(inputs);std::cout << "Neural Network output: " << output << std::endl;return 0;
}
代碼思路:
- 神經網絡類:
- 成員變量:
hidden_layer
存儲隱藏層的神經元,output_neuron
是輸出層的神經元。 - 構造函數:根據輸入層大小和隱藏層大小初始化神經網絡。
- 設置權重和偏置:通過
set_weights
函數設置隱藏層和輸出層的權重和偏置。 - 前向傳播:
- 隱藏層的每個神經元對輸入信號進行前向傳播,計算隱藏層的輸出。
- 將隱藏層的輸出作為輸出層神經元的輸入,計算最終輸出。
- 成員變量:
- 主函數:
- 創建一個神經網絡實例,設置權重和偏置。
- 提供輸入信號,調用
forward
函數計算輸出。# 2. 深度學習框架
2.1 損失函數與優化算法
在深度學習中,損失函數用于衡量模型的預測值與真實值之間的差異,優化算法則用于調整模型的參數以最小化損失函數。以下是幾種常見的損失函數和優化算法的實現及講解。
均方誤差損失函數
均方誤差(MSE)損失函數是回歸任務中常用的損失函數,它計算預測值與真實值之間差的平方的均值。
#include <iostream>
#include <vector>
#include <cmath>// 均方誤差損失函數
double mse_loss(const std::vector<double>& predictions, const std::vector<double>& targets) {double loss = 0.0;for (size_t i = 0; i < predictions.size(); ++i) {loss += std::pow(predictions[i] - targets[i], 2);}return loss / predictions.size();
}int main() {// 示例:預測值和真實值std::vector<double> predictions = {0.5, 1.2, -0.3};std::vector<double> targets = {0.4, 1.0, -0.5};// 計算損失double loss = mse_loss(predictions, targets);std::cout << "MSE Loss: " << loss << std::endl;return 0;
}
代碼思路:
- 損失計算:遍歷預測值和真實值,計算每個樣本的預測值與真實值之差的平方。將所有樣本的損失值求和后除以樣本總數,得到均方誤差損失。
交叉熵損失函數
交叉熵損失函數常用于分類任務,它衡量模型輸出的概率分布與真實標簽的概率分布之間的差異。
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>// Softmax函數
std::vector<double> softmax(const std::vector<double>& logits) {double max_logit = *std::max_element(logits.begin(), logits.end());double sum = 0.0;std::vector<double> probabilities(logits.size());for (size_t i = 0; i < logits.size(); ++i) {probabilities[i] = std::exp(logits[i] - max_logit);sum += probabilities[i];}for (size_t i = 0; i < logits.size(); ++i) {probabilities[i] /= sum;}return probabilities;
}// 交叉熵損失函數
double cross_entropy_loss(const std::vector<double>& logits, int target_class) {std::vector<double> probabilities = softmax(logits);return -std::log(probabilities[target_class]);
}int main() {// 示例:模型輸出的logits和目標類別std::vector<double> logits = {2.0, 1.0