【自制C++深度学习推理框架】ReLU层的设计思路

ReLU层的设计思路

ReLU的定义

由于ReLU是不带参数的,因此可通过继承Layer类,定义ReluLayer类来实现ReLU激活函数的神经网络层。

具体来说,该类包括以下几个成员函数:

  1. 构造函数 ReluLayer() : Layer("Relu"),用于创建一个ReluLayer对象,并设置该层的名称为"Relu"。

  2. InferStatus Forward(const std::vector<std::shared_ptr<Tensor<float>>> &inputs, std::vector<std::shared_ptr<Tensor<float>>> &outputs) override,重载虚函数Forward(),实现输入tensor的元素作用ReLU函数后输出tensor的功能。

  3. static ParseParameterAttrStatus GetInstance(const std::shared_ptr<RuntimeOperator> &op, std::shared_ptr<Layer> &relu_layer),该静态函数为工厂方法,用于生成一个ReluLayer对象,并保存在relu_layer中。

在这个ReluLayer类中,采取了静态的GetInstance函数生成对象的方式,这样能够允许在不创建对象实例的情况下调用对象的静态方法,提高了代码框架的灵活性和可拓展性。

同时,为了保证神经网络框架内部部分的较强的理解和优化能力,通常在类实现的前后端分离中(RuntimeOperator),会根据前端输入的描述来实例化对应类型的后端运算符,从而构建出对应的Layer对象,提高了系统可靠性和效率。

ReLU的前向传播实现

Forward函数首先检查输入是否为空,以及输入tensor和输出tensor向量的尺寸是否匹配。

然后,对于每个输入tensor,使用OpenMP多线程并行处理,并对每个元素应用ReLU激活函数。

需要注意的是,ReLU函数的实现是通过lambda表达式实现的,即Transform([](float val) { return val > 0. ? val : 0.; }),它将输入tensor中每个小于等于0的数据点都设置为0,而大于0的数据点保持不变。

算法的实现性能也有所保证,因为OpenMP多线程能够充分利用CPU多核心心性能进行计算。

最后,将每个输出tensor存储到相应的输出tensor向量中,并返回一个InferStatus类型的结果表示函数执行的状态。

ReLU的注册

ReLU的注册是通过ReluLayer类中的一个静态函数GetInstance以及定义一个全局变量kReluGetInstance来实现的,即LayerRegistererWrapper kReluGetInstance("nn.ReLU", ReluLayer::GetInstance);

GetInstance函数是ReluLayer类的一个工厂方法,用于创建一个ReluLayer对象,并将指针保存在参数relu_layer中。

  • 在该函数中,首先检查输入的op对象是否为nullptr。
  • 然后,使用std::make_shared函数创建一个新的ReluLayer对象,并将其保存到relu_layer指针中。
  • 最后返回一个枚举类型ParseParameterAttrStatus,表明该函数执行成功。

而变量kReluGetInstance是一个全局变量,类型为LayerRegistererWrapper。

  • 该变量的作用是将ReluLayer::GetInstance函数注册到神经网络框架的层注册表(registry)中。
  • 在程序运行时,当需要实例化一个名为"nn.ReLU"的ReLU层时,就会调用ReluLayer::GetInstance函数来创建相应的层对象。

阅读的代码

  • source
    • layer
      • details
        • relu.hpp
        • relu.cpp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值