数学表达式#

DALI 允许您在 pipeline 定义中使用常规 Python 算术运算 和其他 数学函数 (通过 @pipeline_def 或在 define_graph() 中),对从调用其他操作符返回的值进行操作。

所使用的表达式将被整合到 pipeline 中,而无需显式实例化操作符,并将描述张量上的元素级操作

@pipeline_def
def my_pipeline():
    """Create a pipeline which reads and decodes the images, scales channels by
    broadcasting and clamps the result to [128, 255) range."""
    img_files, _ = fn.readers.file(file_root="image_dir")
    images = fn.decoders.image(img_files, device="mixed")
    red_highlight = images * nvidia.dali.types.Constant(np.float32([1.25, 0.75, 0.75]))
    result = nvidia.dali.math.clamp(red_highlight, 128, 255)
    return result

算术表达式的至少一个输入必须由其他 DALI 操作符返回 - 也就是表示一批张量的 nvidia.dali.pipeline.DataNode 值。另一个输入可以是 nvidia.dali.types.Constant() 或类型为 boolintfloat 的常规 Python 值。由于执行的操作是元素级的,因此所有操作数的形状必须兼容 - 要么完全匹配,要么是 可广播的

有关详细信息和示例,请参阅 表达式教程

注意

请记住将数学表达式中使用的张量常量(如 NumPy 数组)用 nvidia.dali.types.Constant() 包裹起来。如果直接使用,则可能会选取该张量库中的操作符实现,并且结果可能未定义。使用前面示例中的行,前两个变体是等效的,而第三个变体将是错误的

# Correct approach:
red_highlight_0 = images *
                  nvidia.dali.types.Constant(np.float32([1.25, 0.75, 0.75]))
red_highlight_1 = nvidia.dali.types.Constant(np.float32([1.25, 0.75, 0.75])) *
                  images
# Wrong approach:
# red_highlight_2 = np.float32([1.25, 0.75, 0.75]) * images

类型提升规则#

对于接受两个(或更多)参数的操作,将应用类型提升。结果类型将根据下表计算。

操作数类型

操作数类型

结果类型

附加条件

T

T

T

floatX

T

floatX

where T is not a float

floatX

floatY

floatZ

where Z = max(X, Y)

intX

intY

intZ

where Z = max(X, Y)

uintX

uintY

uintZ

where Z = max(X, Y)

intX

uintY

int2Y

if X <= Y

intX

uintY

intX

if X > Y

T 代表任何一种受支持的数值类型:boolint8int16int32int64uint8uint16uint32uint64float32float64

bool 类型被认为是最⼩的⽆符号整数类型,并且相对于上表被视为 uint1

注意

类型提升是可交换的。

对于两个以上的参数,结果类型将计算为从左到右的归约 - 首先计算对前两个参数进行操作的结果,然后在该中间结果和第三个参数之间进行计算,依此类推,直到只剩下结果类型。

支持的算术运算#

目前,DALI 支持以下操作

一元 算术 运算符: +, -

实现 __pos__(self)__neg__(self) 的一元运算符。一元算术运算的结果始终保留输入类型。一元运算符仅接受来自其他操作符的 TensorList 输入。

返回类型:

相同类型的 TensorList

二元 算术 运算: +, -, *, /, //, **

分别实现 __add__, __sub__, __mul__, __truediv__, __floordiv____pow__ 的二元运算符。

两个操作数之间算术运算的结果在 上面 进行了描述,但 /,即 __truediv__ 运算除外,它始终返回 float32float64 类型。

注意

两个 bool 值之间唯一允许的算术运算是乘法 (*)

返回类型:

基于类型提升规则计算出的类型的 TensorList。

比较 运算: ==, !=, <, <=, >, >=

比较运算。

返回类型:

bool 类型的 TensorList。

按位 二元 运算: &, |, ^

按位二元运算遵循与算术二元运算相同的类型提升规则,但它们的输入仅限于整数类型(包括 bool)。

注意

按位运算可以应用于两个布尔输入。这些运算可用于模拟张量上的元素级逻辑运算。

返回类型:

基于类型提升规则计算出的类型的 TensorList。

广播#

术语“广播”指的是在数学表达式中如何处理具有不同形状的张量。来自较小张量的值被“广播”,因此它有助于多个输出值。最简单的情况是,标量值被广播到所有输出值。在更复杂的情况下,如果其中一个操作数的大小为 1 而另一个操作数更大,则可以沿某些维度广播值

            [[D, E],       [[ A+D,  B+E ],
[[A, B]] +   [F, G],   ==   [ A+F,  B+G ],
             [H, J]]        [ A+H,  B+J ]]

在上面的示例中,操作数的形状为 (1, 2) 和 (3, 2)。来自数组 [[A, B]] 的值沿轴 0 广播。两个操作数都可能沿不同的维度进行广播

            [[D],      [[ A+D,  B+D ],
[[A, B ]] +  [E],  ==   [ A+E,  B+E ],
             [F]]       [ A+F,  B+F ]]

在本示例中,形状为 (1, 2) 和 (3, 1) - 第一个操作数沿轴 0 广播,第二个操作数沿轴 1 广播。

形状扩展#

为了方便起见,如果数组具有不同数量的维度,则形状将使用外部单位维度进行填充

shape of A == (480, 640, 3)
shape of B == (3)
shape of A + B == (480, 640, 3)   # b is treated as if it was shaped (1, 1, 3)

限制#

DALI 中的广播操作只能具有有限的复杂性。在广播时,需要或不需要广播的相邻轴被分组。最多可以有六个交替的广播/非广播组。分组示例

shape of A == a, b, 1, c, d
shape of B == a, b, e, 1, 1
grouping dimensions (0..1) and (3..4)
grouped shapes:
a*b, 1, c*d
a*b, e, 1

数学函数#

与算术表达式类似,可以在 Pipeline 图定义中使用选定的数学函数。它们也接受 nvidia.dali.pipeline.DataNodenvidia.dali.types.Constant() 或类型为 boolintfloat 的常规 Python 值作为参数。输入中至少有一个必须是其他 DALI 操作符的输出。

nvidia.dali.math.abs(input)#

计算 input 中值的绝对值。

返回类型:

abs(input) 的 TensorList。类型被保留。

nvidia.dali.math.fabs(input)#

计算 input 中值的浮点绝对值。

返回类型:

fabs(input) 的 TensorList。如果输入是整数,则结果将为浮点数,否则类型将被保留。

nvidia.dali.math.floor(input)#

计算 input 中值的向下取整。

返回类型:

floor(input) 的 TensorList。如果输入是整数,则结果将为浮点数,否则类型将被保留。

nvidia.dali.math.ceil(input)#

计算 input 中值的向上取整。

返回类型:

ceil(input) 的 TensorList。如果输入是整数,则结果将为浮点数,否则类型将被保留。

nvidia.dali.math.pow(base, exponent)#

计算底数的指数次幂,即 base ** exponent。

返回类型:

pow(base, exponent) 的 TensorList。类型根据类型提升规则计算。

nvidia.dali.math.fpow(base, exponent)#

将底数的指数次幂计算为浮点数。

返回类型:

pow(base, exponent) 的 TensorList。如果所有输入都是整数,则结果将为浮点数,否则类型将被保留。

nvidia.dali.math.min(left, right)#

计算 leftright 中对应值的最小值。

返回类型:

基于类型提升规则计算出的类型的 TensorList。

nvidia.dali.math.max(left, right)#

计算 leftright 中对应值的最大值。

返回类型:

基于类型提升规则计算出的类型的 TensorList。

nvidia.dali.math.clamp(value, lo, hi)#

生成一个张量,其值来自 value,并被钳制在范围 [lo, hi] 内。

返回类型:

基于类型提升规则计算出的类型的 TensorList。

指数和对数#

nvidia.dali.math.sqrt(input)#

计算 input 中值的平方根。

返回类型:

sqrt(input) 的 TensorList。如果输入是整数,则结果将为浮点数,否则类型将被保留。

nvidia.dali.math.rsqrt(input)#

计算 input 中值的平方根的倒数。

返回类型:

rsqrt(input) 的 TensorList。如果输入是整数,则结果将为浮点数,否则类型将被保留。

nvidia.dali.math.cbrt(input)#

计算 input 中值的立方根。

返回类型:

cbrt(input) 的 TensorList。如果输入是整数,则结果将为浮点数,否则类型将被保留。

nvidia.dali.math.exp(input)#

计算 input 中值的指数。

返回类型:

exp(input) 的 TensorList。如果输入是整数,则结果将为浮点数,否则类型将被保留。

nvidia.dali.math.log(input)#

计算 input 中值的自然对数(底为 e)。

返回类型:

log(input) 的 TensorList。如果输入是整数,则结果将为浮点数,否则类型将被保留。

nvidia.dali.math.log2(input)#

计算 input 中值的对数(底为 2)。

返回类型:

log2(input) 的 TensorList。如果输入是整数,则结果将为浮点数,否则类型将被保留。

nvidia.dali.math.log10(input)#

计算 input 中值的对数(底为 10)。

返回类型:

log10(input) 的 TensorList。如果输入是整数,则结果将为浮点数,否则类型将被保留。

三角函数#

nvidia.dali.math.sin(input)#

计算 input 中值的正弦值。

返回类型:

sin(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.cos(input)#

计算 input 中值的余弦值。

返回类型:

cos(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.tan(input)#

计算 input 中值的正切值。

返回类型:

tan(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.asin(input)#

计算 input 中值的反正弦值。

返回类型:

asin(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.acos(input)#

计算 input 中值的反余弦值。

返回类型:

acos(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.atan(input)#

计算 input 中值的反正切值。

返回类型:

atan(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.atan2(x, y)#

计算 x / y 中对应值的反正切值。

返回类型:

atan2(x, y) 的 TensorList。如果所有输入都是整数,结果将为浮点数,否则类型将保留。

双曲函数#

nvidia.dali.math.sinh(input)#

计算 input 中值的双曲正弦值。

返回类型:

sinh(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.cosh(input)#

计算 input 中值的双曲余弦值。

返回类型:

cosh(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.tanh(input)#

计算 input 中值的双曲正切值。

返回类型:

tanh(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.asinh(input)#

计算 input 中值的反双曲正弦值。

返回类型:

asinh(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.acosh(input)#

计算 input 中值的反双曲余弦值。

返回类型:

acosh(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。

nvidia.dali.math.atanh(input)#

计算 input 中值的反双曲正切值。

返回类型:

atanh(input) 的 TensorList。如果 input 是整数,结果将为浮点数,否则类型将保留。