在python-numpy中定义一个自定义的float8并转换from/to float16?
Define a custom float8 in python-numpy and convert from/to float16?
我正在尝试定义自定义 8 位浮点格式,如下所示:
- 1 个符号位
- 2 位尾数
- 5 位指数
是否可以将其定义为 numpy 数据类型?
如果不是,将 dtype float16 的 numpy 数组转换为这种格式(用于存储)并将其转换回(用于 float16 中的计算)的最简单方法是什么,也许使用 numpy 的位操作?
为什么:
我正在尝试优化自定义硬件 (FPGA) 上的神经网络。为此,我正在尝试各种浮动表示形式。我已经用 numpy 为我的神经网络构建了一个前向传递框架,因此像上面这样的东西将通过将值存储在我的自定义数据类型中来帮助我检查准确性的降低。
我绝不是 numpy 专家,但我喜欢思考 FP 表示问题。数组的大小并不大,因此任何合理有效的方法都应该没问题。它看起来不像是 8 位 FP 表示,我猜是因为精度不太好。
要转换为字节数组,每个字节包含一个 8 位 FP 值,对于一维数组,您只需要
float16 = np.array([6.3, 2.557]) # Here's some data in an array
float8s = array.tobytes()[1::2]
print(float8s)
>>> b'FAAF'
这只是通过去掉低位部分从 16 位浮点数中取出 high-order 字节,给出 1 位符号、5 位指数和 2 位有效数。在 little-endian 机器上,高位字节始终是每对的第二个字节。我已经在 2D 阵列上试过了,它的工作原理是一样的。这会截断。小数点四舍五入是另外一回事。
回到 16 位只是插入零。我通过实验找到了这种方法,毫无疑问还有更好的方法,但这会将字节数组读取为 8 位整数,并将新的字节数组写入 16 位整数,然后将其转换回浮点数组。注意 big-endian 表示转换回字节,因为我们希望 8 位值是整数的高位字节。
float16 = np.frombuffer(np.array(np.frombuffer(float8s, dtype='u1'), dtype='>u2').tobytes(), dtype='f2')
print(float16)
>>> array([6. , 2.5, 2.5, 6. ], dtype=float16)
你绝对可以看到精度的损失!我希望这有帮助。如果这足够了,请告诉我。如果没有,我会更深入地研究它。
我正在尝试定义自定义 8 位浮点格式,如下所示:
- 1 个符号位
- 2 位尾数
- 5 位指数
是否可以将其定义为 numpy 数据类型? 如果不是,将 dtype float16 的 numpy 数组转换为这种格式(用于存储)并将其转换回(用于 float16 中的计算)的最简单方法是什么,也许使用 numpy 的位操作?
为什么:
我正在尝试优化自定义硬件 (FPGA) 上的神经网络。为此,我正在尝试各种浮动表示形式。我已经用 numpy 为我的神经网络构建了一个前向传递框架,因此像上面这样的东西将通过将值存储在我的自定义数据类型中来帮助我检查准确性的降低。
我绝不是 numpy 专家,但我喜欢思考 FP 表示问题。数组的大小并不大,因此任何合理有效的方法都应该没问题。它看起来不像是 8 位 FP 表示,我猜是因为精度不太好。
要转换为字节数组,每个字节包含一个 8 位 FP 值,对于一维数组,您只需要
float16 = np.array([6.3, 2.557]) # Here's some data in an array
float8s = array.tobytes()[1::2]
print(float8s)
>>> b'FAAF'
这只是通过去掉低位部分从 16 位浮点数中取出 high-order 字节,给出 1 位符号、5 位指数和 2 位有效数。在 little-endian 机器上,高位字节始终是每对的第二个字节。我已经在 2D 阵列上试过了,它的工作原理是一样的。这会截断。小数点四舍五入是另外一回事。
回到 16 位只是插入零。我通过实验找到了这种方法,毫无疑问还有更好的方法,但这会将字节数组读取为 8 位整数,并将新的字节数组写入 16 位整数,然后将其转换回浮点数组。注意 big-endian 表示转换回字节,因为我们希望 8 位值是整数的高位字节。
float16 = np.frombuffer(np.array(np.frombuffer(float8s, dtype='u1'), dtype='>u2').tobytes(), dtype='f2')
print(float16)
>>> array([6. , 2.5, 2.5, 6. ], dtype=float16)
你绝对可以看到精度的损失!我希望这有帮助。如果这足够了,请告诉我。如果没有,我会更深入地研究它。