You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从AI神经网络层(输入、隐藏、输出)理论到C++代码实现

实现C++神经网络层的核心思路与代码示例

神经网络的层核心要完成**前向传播(输入x转输出y)和反向传播(更新参数)**两大功能,通常先定义抽象基类统一接口,再针对不同层类型实现具体子类。

核心函数与结构

所有层必备的核心要素:

  • forward(const Eigen::VectorXd& x):输入张量转输出的核心函数,是你需要的x到y的计算逻辑载体。
  • backward(const Eigen::VectorXd& dy):接收上层传来的梯度,计算当前层参数梯度和输入梯度,用于反向更新参数。
  • 成员变量:存储可训练参数(如权重、偏置)和前向传播的中间输入(用于反向计算)。

基础Layer抽象类实现

#include <Eigen/Dense>

class Layer {
public:
    // 纯虚前向传播函数,子类必须实现
    virtual Eigen::VectorXd forward(const Eigen::VectorXd& x) = 0;
    // 纯虚反向传播函数
    virtual Eigen::VectorXd backward(const Eigen::VectorXd& dy) = 0;
    // 虚析构函数,确保子类正确析构
    virtual ~Layer() = default;
};

具体层示例:全连接层(Dense Layer)

全连接层的前向公式为 y = W*x + b,其中W是权重矩阵,b是偏置向量。

class DenseLayer : public Layer {
private:
    Eigen::MatrixXd weights; // 权重矩阵,形状[输出维度, 输入维度]
    Eigen::VectorXd bias;    // 偏置向量,形状[输出维度]
    Eigen::VectorXd input;   // 存储前向输入,用于反向计算

public:
    // 构造函数:初始化维度并随机初始化参数
    DenseLayer(int input_dim, int output_dim) {
        // He初始化权重,缓解梯度消失
        weights = Eigen::MatrixXd::Random(output_dim, input_dim) * sqrt(2.0 / input_dim);
        bias = Eigen::VectorXd::Zero(output_dim);
    }

    Eigen::VectorXd forward(const Eigen::VectorXd& x) override {
        input = x;
        return weights * x + bias;
    }

    Eigen::VectorXd backward(const Eigen::VectorXd& dy) override {
        // 计算权重和偏置的梯度
        Eigen::MatrixXd d_weights = dy * input.transpose();
        Eigen::VectorXd d_bias = dy;

        // 计算输入梯度,传给上一层(反向传播的上游)
        Eigen::VectorXd dx = weights.transpose() * dy;

        // 简单SGD更新参数,学习率0.01
        weights -= 0.01 * d_weights;
        bias -= 0.01 * d_bias;

        return dx;
    }
};

具体层示例:ReLU激活层

激活层无训练参数,前向逻辑为y = max(0, x),反向逻辑为dy * (x > 0 ? 1 : 0)。

class ReLULayer : public Layer {
private:
    Eigen::VectorXd input; // 保存输入用于反向计算

public:
    Eigen::VectorXd forward(const Eigen::VectorXd& x) override {
        input = x;
        return x.unaryExpr([](double val) { return std::max(0.0, val); });
    }

    Eigen::VectorXd backward(const Eigen::VectorXd& dy) override {
        Eigen::VectorXd dx = dy;
        for (int i = 0; i < input.size(); ++i) {
            if (input(i) <= 0) {
                dx(i) = 0;
            }
        }
        return dx;
    }
};

使用示例

#include <iostream>

int main() {
    // 创建输入维度2、输出维度3的全连接层
    DenseLayer dense(2, 3);
    // 创建ReLU激活层
    ReLULayer relu;

    Eigen::VectorXd input(2);
    input << 1.0, 2.0;

    // 前向传播
    Eigen::VectorXd dense_output = dense.forward(input);
    Eigen::VectorXd relu_output = relu.forward(dense_output);

    std::cout << "输入: " << input.transpose() << std::endl;
    std::cout << "全连接层输出: " << dense_output.transpose() << std::endl;
    std::cout << "ReLU输出: " << relu_output.transpose() << std::endl;

    // 模拟反向传播(假设上层传来的梯度为全1)
    Eigen::VectorXd dy(3);
    dy << 1.0, 1.0, 1.0;
    Eigen::VectorXd relu_dx = relu.backward(dy);
    Eigen::VectorXd dense_dx = dense.backward(relu_dx);

    std::cout << "输入的梯度: " << dense_dx.transpose() << std::endl;

    return 0;
}

关键说明

  • 用Eigen库简化矩阵向量运算,避免手动实现复杂线性代数逻辑。
  • 抽象基类保证所有层可统一调用,新增层只需继承基类并实现forward和backward。
  • 若仅做推理(不训练),可只保留forward函数。

更新:感谢各位的指导,我已记录并回复了几乎所有建议,今晚晚些时候会展示相关进展。

内容的提问来源于stack exchange,提问作者Wasthisit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 16:54:53