Celu算子
【免费下载链接】cann-ops-competitions本仓库用于 CANN 开源社区各类竞赛、开源课题、社区任务等课题发布、开发者作品提交和展示。项目地址: https://gitcode.com/cann/cann-ops-competitions
难度系数:1.0
一、赛题背景
Celu(Continuously-differentiable Exponential Linear Unit)是深度学习中一种连续可微的激活函数,是ELU的改进变体。相比ELU在零点处的不可导性,Celu在整个定义域上保持连续可导,梯度更加平滑,有利于优化过程的稳定性,广泛应用于对梯度连续性有严格要求的深度学习模型训练场景。
本题要求基于PyTorch原生torch.nn.functional.celu算子的核心业务逻辑,采用Ascend C编程语言进行算子原生开发,在昇腾NPU硬件上实现一款高性能、高兼容性、高适配性的Celu算子。
相似类型算子的实现可参考开源仓:
https://gitcode.com/cann/ops-math
https://gitcode.com/cann/ops-nn
https://gitcode.com/cann/ops-cv
https://gitcode.com/cann/ops-transformer
https://gitcode.com/cann/cann-samples
二、算子功能描述
实现的Celu算子需对输入多维张量的每个元素执行连续可微指数线性单元激活操作,返回与输入形状相同的结果张量。
算子支持通过alpha参数控制负值区间的饱和程度,为逐元素计算,输出形状与输入形状完全一致,且需兼容非32整倍数的维度非对齐场景。
三、核心定义与约束
3.1 参考算子
PyTorch原生算子:torch.nn.functional.celu(算子行为、计算结果需与该算子完全对齐)
3.2 数学公式
$$ \text{celu}(x) = \max(0, x) + \min(0, \alpha \times (\exp(x / \alpha) - 1)) $$
其中 α(alpha)为可配置参数,默认值为1.0。
3.3 输入输出与属性总览
| 类型 | 参数名 | 类型 | 维度形状 | 支持数据类型 | 数据格式 | 备注 |
|---|---|---|---|---|---|---|
| INPUT(必选) | self | tensor | (..., N4, N3, N2, N) | float32 | ND | 输入张量 |
| ATTR(属性) | alpha | float | - | - | ND | 控制负值区间饱和程度的参数,默认值为1.0 |
| OUTPUT(输出) | out | tensor | (..., N4, N3, N2, N) | float32 | ND | 激活后的结果张量,形状与输入一致 |
3.4 关键输入约束
维度取值范围(均为正整数):
- N ∈ [1, 10000]
- N2 ∈ [1, 10000]
- N3 ∈ [1, 1000]
- N4 ∈ [1, 1000]
输入为任意多维张量,最终维度可拆解为(..., N4, N3, N2, N),前序...为任意合法批次维度,shape支持0-8维
非对齐场景兼容: N、N2、N3、N4 均可能为非32的整倍数,算子需适配内存/数据非32字节对齐的场景
数值取值约束: 输入张量的数值取值范围不超出float32数据类型的原生表达范围
3.5 核心属性说明
- alpha(float,默认1.0): 控制负值区间的指数饱和速率。alpha值越大,负值区间的过渡越平缓;alpha值越小,负值区间的过渡越陡峭。alpha必须为正数。
3.6 输出严格要求
形状约束: 输出形状与输入形状完全一致
类型约束: 输出数据类型为float32
数值含义: 输出张量中每个位置的值为输入张量对应位置元素经Celu激活函数计算后的结果
精度要求: 要求与torch.nn.functional.celu标杆精度误差满足浮点数精度要求(相对误差不超过1e-5或绝对误差不超过1e-6)
3.7 特殊值处理规则
NaN处理: 如果输入包含NaN,输出对应位置为NaN
Inf处理:
- 输入为+Inf时,输出为+Inf(正值区域直接输出)
- 输入为-Inf时,输出为 α × (exp(-Inf/α) - 1) = α × (0 - 1) = -α
零值处理:
- 输入为0时,输出为 max(0, 0) + min(0, α × (exp(0) - 1)) = 0 + 0 = 0
alpha为0的处理: alpha必须为正数,不应出现alpha=0的情况;若alpha趋近于0,需保证数值稳定性
四、规则要求
逐元素计算规则: 对输入张量的每个元素独立执行Celu激活函数计算,元素之间无依赖关系
形状不变规则: 输出张量形状与输入张量形状完全一致,不改变维度信息
alpha参数规则: alpha为正浮点数,计算公式中需使用x/α作为指数函数的输入,α控制负值区间的缩放比例
指数函数精度规则: 对exp(x/α)的计算需保证数值稳定性,当x/α为较大负数时exp(x/α)趋近于0,不应产生数值异常
连续可微规则: Celu在x=0处必须保持连续且可微,即celu(0)=0,左导数与右导数在零点连续
五、示例说明
示例1: 一维张量基础计算(alpha=1.0)
- 输入self: tensor([-1.0, 0.0, 1.0, 2.0]), dtype=float32, shape=[4] (N=4)
- 属性配置: alpha=1.0
- 输出out: tensor([-0.6321, 0.0, 1.0, 2.0]), dtype=float32, shape=[4]
- 结果解释:
- celu(-1.0) = 0 + 1.0 × (exp(-1.0) - 1) ≈ 0 + (0.3679 - 1) ≈ -0.6321
- celu(0.0) = 0 + 0 = 0.0
- celu(1.0) = 1.0 + 0 = 1.0
- celu(2.0) = 2.0 + 0 = 2.0
示例2: 二维张量计算(alpha=2.0)
- 输入self: tensor([[0.5, -0.5], [1.5, -1.5]]), dtype=float32, shape=[2, 2] (N2=2, N=2)
- 属性配置: alpha=2.0
- 输出out: tensor([[0.5, -0.3935], [1.5, -0.7769]]), dtype=float32, shape=[2, 2]
- 结果解释:
- celu(-0.5, α=2.0) = 0 + 2.0 × (exp(-0.5/2.0) - 1) = 2.0 × (exp(-0.25) - 1) ≈ -0.3935
- celu(-1.5, α=2.0) = 0 + 2.0 × (exp(-1.5/2.0) - 1) = 2.0 × (exp(-0.75) - 1) ≈ -0.7769
示例3: 不同alpha值对比
- 输入self: tensor([-2.0]), dtype=float32, shape=[1] (N=1)
- 属性配置: alpha=0.5
- 输出out: tensor([-0.4323]), dtype=float32, shape=[1]
- 结果解释: celu(-2.0, α=0.5) = 0 + 0.5 × (exp(-2.0/0.5) - 1) = 0.5 × (exp(-4.0) - 1) ≈ -0.4323
示例4: 特殊值处理
- 输入self: tensor([inf, -inf, nan]), dtype=float32, shape=[3] (N=3)
- 属性配置: alpha=1.0
- 输出out: tensor([inf, -1.0, nan]), dtype=float32, shape=[3]
- 结果解释: +Inf输出+Inf,-Inf输出α×(0-1)=-1.0,NaN输出NaN
六、测试用例覆盖范围
数据类型覆盖: float32
维度场景覆盖:
- 0维(标量)场景
- 1维、2维、3维、4维(N4,N3,N2,N)、含批次维度的多维场景(..., N4,N3,N2,N)
- N~N4 为非32整倍数的非对齐场景
数值场景覆盖:
- 正数区间(x > 0):线性区域
- 负数区间(x < 0):指数区域
- 零点附近(x ≈ 0):连续性验证
- 极大正值、极小负值
属性组合覆盖:
- alpha=1.0(默认值)
- alpha < 1.0(如0.5、0.1)
- alpha > 1.0(如2.0、5.0)
特殊值场景覆盖:
- NaN值
- +Inf、-Inf
- 零值
【免费下载链接】cann-ops-competitions本仓库用于 CANN 开源社区各类竞赛、开源课题、社区任务等课题发布、开发者作品提交和展示。项目地址: https://gitcode.com/cann/cann-ops-competitions
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考