本wiki页面介绍了 Keras 3 中的 NumPy 兼容操作系统,它提供了一个后端无关的 API,用于在所有支持的后端(TensorFlow、JAX、PyTorch、NumPy 和 OpenVINO)上执行类 NumPy 操作。这些操作通过 keras.ops.numpy 命名空间(通常导入为 knp)提供。
有关神经网络特定操作,请参阅神经网络操作。
NumPy 兼容操作系统允许开发者编写在所有后端上一致运行的代码,从而实现可移植的模型定义。这些操作模仿 NumPy 的行为和 API,同时支持符号张量(模型构建期间)和具体张量(即时执行期间)。
来源
NumPy 兼容操作系统由三个主要组件组成
Operation 的子类,实现 call() 和 compute_output_spec() 方法。@keras_export 装饰器进行装饰。numpy.py 模块中实现具体功能。来源
当调用 NumPy 操作时,它遵循以下执行流程
keras.ops.numpy.add(x1, x2) 的函数KerasTensor)Operation.symbolic_call(),它会调用 compute_output_spec() 来确定输出形状和数据类型backend.numpy.add(x1, x2) 调用后端特定实现让我们以 add 操作为例,看看它是如何工作的
来源
NumPy 兼容操作系统提供了广泛的操作,分类如下
array:创建数组ones:创建全一数组zeros:创建全零数组eye:创建单位矩阵arange:在给定区间内创建等间隔值linspace:在指定范围内创建等间隔值full:创建指定形状和值的常量数组meshgrid:从坐标向量创建坐标矩阵reshape:在不改变数据的情况下为数组赋予新形状transpose:对数组维度进行转置squeeze:从数组形状中移除单维度条目expand_dims:用新轴扩展数组的形状concatenate:沿着现有轴连接数组stack:沿着新轴堆叠数组split:将数组拆分为多个子数组tile:通过重复输入数组来构造数组pad:填充数组add, subtract, multiply, divide:基本算术运算matmul:矩阵乘法power:将元素提升到指定幂exp, log, sqrt:常见数学函数sin, cos, tan:三角函数mean, sum, max, min:约简操作clip:将数组值剪辑到指定范围abs, absolute:计算绝对值equal, not_equal:元素级相等比较greater, greater_equal:元素级大于/大于等于比较less, less_equal:元素级小于/小于等于比较logical_and, logical_or, logical_not:逻辑运算dot:两个数组的点积tensordot:指定轴上的张量收缩einsum:爱因斯坦求和约定inner:数组的内积outer:计算两个向量的外积trace:沿着数组对角线求和下面是一些常用操作及其签名的表格
| 操作 | 签名 | 描述 |
|---|---|---|
add | add(x1, x2) | 逐元素加法 |
subtract | subtract(x1, x2) | 元素级减法 |
multiply | multiply(x1, x2) | 元素级乘法 |
divide | divide(x1, x2) | 元素级除法 |
matmul | matmul(x1, x2) | 矩阵乘法 |
mean | mean(x, axis=None, keepdims=False) | 沿着指定轴的平均值 |
sum | sum(x, axis=None, keepdims=False) | 沿着指定轴求和 |
max | max(x, axis=None, keepdims=False, initial=None) | 沿着轴的最大值 |
reshape | reshape(x, newshape) | 不改变数据的情况下重塑数组 |
transpose | transpose(x, axes=None) | 置换数组维度 |
来源
NumPy 兼容操作可以按如下方式导入和使用
NumPy 兼容操作的关键特性之一是它们能够与符号张量(由 KerasTensor 表示)一起工作。每个操作的 compute_output_spec 方法根据输入张量确定输出形状和数据类型。
例如,Add 操作通过广播输入形状来确定输出形状
该系统智能地处理动态形状,即使某些维度未知(表示为 None),也能使用广播规则确定结果形状。
来源
虽然 API 在不同后端之间保持一致,但实现细节有所不同
TensorFlow 后端:
einsum,通过自定义实现获得更好的性能JAX 后端:
PyTorch 后端:
NumPy 后端:
OpenVINO 后端:
来源
NumPy 兼容操作系统的实现架构包括
每个操作遵循以下模式
定义一个 Operation 子类,包含
__init__ 用于存储任何参数(可选)call() 用于实现操作逻辑compute_output_spec() 用于确定输出形状和数据类型定义一个 API 函数,该函数
any_symbolic_tensors() 检查是否有任何输入是符号张量symbolic_call() 方法这是 Add 操作的示例
来源
NumPy 兼容操作系统实现了 NumPy 的广播规则,以处理不同形状的张量。这通过诸如 broadcast_shapes() 的实用函数进行管理,该函数在组合不同维度的张量时确定输出形状。
来源
该系统支持动态形状,其中某些维度在图构建时可能未知
来源
操作通过使用 dtypes.result_type() 来根据输入数据类型确定输出数据类型,从而处理不同的数据类型。这确保了不同后端之间的一致行为,并遵循 NumPy 的数据类型提升规则。
来源
不同的后端实现了各种优化
TensorFlow:
tf.einsum 与硬件加速结合使用tf.nn.bias_addJAX:
PyTorch:
来源
NumPy 操作在可能的情况下会进行硬件加速
例如,当满足正确条件时,TensorFlow 会使用硬件加速实现
来源
NumPy 兼容操作系统经过广泛测试,以确保不同后端之间的一致行为。测试验证了
某些操作可能并非在所有后端都得到完全支持。例如,OpenVINO 有一个尚未实现的操作排除列表
NumPyOneInputOpsCorrectnessTest::test_flip
NumPyOneInputOpsCorrectnessTest::test_meshgrid
NumPyTwoInputOpsCorrectnessTest::test_cross
NumPyTwoInputOpsCorrectnessTest::test_digitize
来源
Keras 3 中的 NumPy 兼容操作系统提供了一个一致的、后端无关的 API,用于执行数组操作。它使开发者能够编写在多个后端上工作且支持符号执行和即时执行模式的可移植代码。该系统处理形状推断、数据类型提升和广播,同时利用每个后端的优化实现来提高性能。
通过模仿熟悉的 NumPy API,Keras 使数据科学家和机器学习从业者更容易从 NumPy 过渡到深度学习框架,而无需学习基本数组操作的新 API。