欢迎光临
我们一直在努力

C++:多层神经网络(附带源码)

项目背景详细介绍

随着人工智能与机器学习的快速发展,神经网络(Neural Network) 已经成为现代计算机科学中不可或缺的核心技术之一。

在工业级项目中,人们往往直接使用:

  • TensorFlow

  • PyTorch

  • ONNX Runtime

  • 各类推理框架

但对于 C++ 学习者和算法初学者 来说,如果一开始就依赖这些“黑盒框架”,往往会产生几个严重问题:

  • 不清楚神经网络内部到底做了什么

  • 不了解前向传播与反向传播的本质

  • 无法将数学公式与代码建立对应关系

  • 难以在底层系统、嵌入式、游戏引擎中灵活应用

而在很多真实工程场景中,例如:

  • 游戏 AI

  • 智能决策系统

  • 嵌入式设备推理

  • 算法教学与科研验证

  • 面试与基础能力考察

从零手写一个多层神经网络,反而是一项极具价值的能力。

因此,本项目将以教学与理解为第一目标,在 不使用任何第三方机器学习库 的前提下,完整实现一个:

支持多层结构、前向传播、反向传播、梯度下降训练的 C++ 神经网络

该项目非常适合作为博客长文、人工智能课程、算法与 C++ 综合训练项目。


项目需求详细介绍

本项目的目标需求如下:

1. 功能需求

  • 使用 C++ 实现多层前馈神经网络

  • 支持输入层、隐藏层、输出层

  • 支持 Sigmoid 激活函数

  • 支持前向传播(Forward Propagation)

  • 支持反向传播(Backpropagation)

  • 支持基于梯度下降的权重更新

  • 能够完成简单监督学习任务

  • 2. 网络结构要求

    • 全连接网络(Fully Connected)

    • 任意层数(示例使用 1 个隐藏层)

    • 使用矩阵 / 向量计算(手动实现)

    3. 教学与工程要求

  • 数学概念与代码一一对应

  • 代码结构清晰,便于逐层理解

  • 不追求极致性能,追求可读性

  • 可扩展为更复杂网络结构


  • 相关技术详细介绍

    1. 神经网络基本组成

    一个典型的前馈神经网络由以下部分组成:

  • 神经元(Neuron)

  • 权重(Weight)

  • 偏置(Bias)

  • 激活函数(Activation Function)

  • 数学表达式为:

    y = f( Σ(wi * xi) + b )


    2. 前向传播(Forward Propagation)

    前向传播是指:

    从输入层开始,逐层计算,直到输出层得到预测结果

    这是**推理(Inference)**的核心过程。


    3. 反向传播(Backpropagation)

    反向传播是神经网络学习的核心算法,其本质是:

    • 利用链式法则

    • 从输出层向前逐层计算误差

    • 更新权重和偏置


    4. 梯度下降(Gradient Descent)

    权重更新公式为:

    weight = weight – learning_rate * gradient

    这是神经网络“学习”的本质。


    实现思路详细介绍

    整体实现思路如下:

  • 封装神经网络类

    • 保存权重矩阵与偏置

    • 管理网络层结构

  • 实现前向传播

    • 输入 → 隐藏层 → 输出层

  • 实现反向传播

    • 输出层误差

    • 隐藏层误差

    • 权重与偏置更新

  • 训练循环

    • 输入样本

    • 前向计算

    • 反向更新

    • 多轮迭代收敛

  • 该结构与所有深度学习框架的底层原理完全一致。


    完整实现代码

    /****************************************************
    * File: NeuralNetwork.h
    ****************************************************/
    #pragma once
    #include <vector>

    class NeuralNetwork
    {
    public:
    NeuralNetwork(int input, int hidden, int output, double lr);
    std::vector<double> predict(const std::vector<double>& input);
    void train(const std::vector<double>& input,
    const std::vector<double>& target);

    private:
    double learningRate;

    std::vector<std::vector<double>> weightsIH;
    std::vector<std::vector<double>> weightsHO;

    std::vector<double> biasH;
    std::vector<double> biasO;

    static double sigmoid(double x);
    static double dsigmoid(double y);
    };

    /****************************************************
    * File: NeuralNetwork.cpp
    ****************************************************/
    #include "NeuralNetwork.h"
    #include <cmath>
    #include <cstdlib>

    static double randomWeight()
    {
    return ((double)rand() / RAND_MAX) * 2.0 – 1.0;
    }

    NeuralNetwork::NeuralNetwork(int input, int hidden, int output, double lr)
    : learningRate(lr)
    {
    weightsIH.resize(hidden, std::vector<double>(input));
    weightsHO.resize(output, std::vector<double>(hidden));
    biasH.resize(hidden);
    biasO.resize(output);

    for (auto& row : weightsIH)
    for (auto& w : row) w = randomWeight();

    for (auto& row : weightsHO)
    for (auto& w : row) w = randomWeight();

    for (auto& b : biasH) b = randomWeight();
    for (auto& b : biasO) b = randomWeight();
    }

    double NeuralNetwork::sigmoid(double x)
    {
    return 1.0 / (1.0 + exp(-x));
    }

    double NeuralNetwork::dsigmoid(double y)
    {
    return y * (1.0 – y);
    }

    std::vector<double> NeuralNetwork::predict(const std::vector<double>& input)
    {
    std::vector<double> hidden(biasH);
    for (size_t i = 0; i < hidden.size(); i++)
    for (size_t j = 0; j < input.size(); j++)
    hidden[i] += weightsIH[i][j] * input[j];

    for (auto& h : hidden) h = sigmoid(h);

    std::vector<double> output(biasO);
    for (size_t i = 0; i < output.size(); i++)
    for (size_t j = 0; j < hidden.size(); j++)
    output[i] += weightsHO[i][j] * hidden[j];

    for (auto& o : output) o = sigmoid(o);

    return output;
    }

    void NeuralNetwork::train(const std::vector<double>& input,
    const std::vector<double>& target)
    {
    // 前向传播
    std::vector<double> hidden(biasH);
    for (size_t i = 0; i < hidden.size(); i++)
    for (size_t j = 0; j < input.size(); j++)
    hidden[i] += weightsIH[i][j] * input[j];

    for (auto& h : hidden) h = sigmoid(h);

    std::vector<double> output(biasO);
    for (size_t i = 0; i < output.size(); i++)
    for (size_t j = 0; j < hidden.size(); j++)
    output[i] += weightsHO[i][j] * hidden[j];

    for (auto& o : output) o = sigmoid(o);

    // 输出层误差
    std::vector<double> outputErrors(output.size());
    for (size_t i = 0; i < output.size(); i++)
    outputErrors[i] = target[i] – output[i];

    // 隐藏层误差
    std::vector<double> hiddenErrors(hidden.size(), 0.0);
    for (size_t i = 0; i < hidden.size(); i++)
    for (size_t j = 0; j < output.size(); j++)
    hiddenErrors[i] += weightsHO[j][i] * outputErrors[j];

    // 更新权重 HO
    for (size_t i = 0; i < weightsHO.size(); i++)
    for (size_t j = 0; j < weightsHO[i].size(); j++)
    weightsHO[i][j] += learningRate *
    outputErrors[i] * dsigmoid(output[i]) * hidden[j];

    // 更新偏置 O
    for (size_t i = 0; i < biasO.size(); i++)
    biasO[i] += learningRate *
    outputErrors[i] * dsigmoid(output[i]);

    // 更新权重 IH
    for (size_t i = 0; i < weightsIH.size(); i++)
    for (size_t j = 0; j < weightsIH[i].size(); j++)
    weightsIH[i][j] += learningRate *
    hiddenErrors[i] * dsigmoid(hidden[i]) * input[j];

    // 更新偏置 H
    for (size_t i = 0; i < biasH.size(); i++)
    biasH[i] += learningRate *
    hiddenErrors[i] * dsigmoid(hidden[i]);
    }

    /****************************************************
    * File: main.cpp
    ****************************************************/
    #include "NeuralNetwork.h"
    #include <iostream>

    int main()
    {
    NeuralNetwork nn(2, 4, 1, 0.1);

    // 训练 XOR
    for (int i = 0; i < 5000; i++)
    {
    nn.train({0, 0}, {0});
    nn.train({0, 1}, {1});
    nn.train({1, 0}, {1});
    nn.train({1, 1}, {0});
    }

    std::cout << "0 XOR 0 = " << nn.predict({0, 0})[0] << std::endl;
    std::cout << "0 XOR 1 = " << nn.predict({0, 1})[0] << std::endl;
    std::cout << "1 XOR 0 = " << nn.predict({1, 0})[0] << std::endl;
    std::cout << "1 XOR 1 = " << nn.predict({1, 1})[0] << std::endl;

    return 0;
    }

    赞(0)
    未经允许不得转载:171主机测评 » C++:多层神经网络(附带源码)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址