防止矩阵乘法溢出? (麻木的)

Prevent Overflow in Matrix Multiplication? (Numpy)

我正在处理一些基于整数的高维数据,出于内存原因,我们必须对所有内容都使用 int8。我 运行 遇到的问题是我需要用这个 int8 数据做矩阵乘法,但如果结果高于 127,我只需要 return 127 而不是溢出是什么.

例如:

import numpy as np

a = np.random.choice([0,1], size=[128,2000]).astype(np.int8)
b = np.random.randint(0,128, size=[2000,2000]).astype(np.int8)

c = np.matmul(a, b)

# c returns values between -128 and 127, instead of the desired 0 to 127

澄清一下,我不只是在寻找额外的 space 无符号整数 - b 中的值有时可能是负数。 (为了进一步说明我的观点,我只是将 b 全部设为正面。)

是否有算法或 Numpy 技巧可以让我限制这些操作而不是让它们溢出?我仔细阅读了 Numpy 文档并询问了我在 CS 部门的一些朋友,但我还没有找到任何线索。

最后,我知道我可以在 C 中用位旋转来完成其中的一些,但是我们项目的其余部分不可避免地在 Python 中,几乎没有扩展的机会(并且给定 Python ,如果可能的话,我更愿意使用 Numpy 进行矩阵乘法。

谢谢大家!

也许这样的事情对你有用。这是逐行执行操作,因此您一次只需要在 int32 数据类型中保存一行。这是@user2357112 描述的分块方法。

def matmul(a, b):
    """chunked matmul which converts datatypes and filters values too large to 127"""
    c = np.empty((a.shape[0], b.shape[1]), dtype = np.int8) # output
    for i in range(a.shape[0]): # iterate over rows in a 
        aa = a[i].astype(np.int32) # convert one row to extended datatype
        cc = aa @ b # broadcasting means cc is the dtype of aa 
        cc[cc > 127] = 127 # set all future overflows to 127
        c[i] = cc.astype(np.int8) # convert dtype back 
    return c

c  = matmul(a, b) # your computation of interest 

这会慢很多,但可能不会使您的内存过载。

如果这不起作用,您可以根据需要使用 np.loadmmap_mode 关键字将 ab 的行和列加载到内存中,如前所述。然后您可以执行计算 row @ col 以在所需数据范围内开发单个元素 c[i,j]