神经网络与深度学习
- 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