我正在处理一些基于高维整数的数据,由于内存原因,我们必须对所有内容使用int8s。我遇到的问题是我需要对此int8数据进行矩阵乘法,但是如果结果超过127,则需要它仅返回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
为了澄清,我不只是在寻找unsigned int会提供的额外空间-b中的值有时可能为负。 (我只是将b表示肯定,以进一步说明我的观点。)
是否有一种算法或Numpy技巧可以让我限制这些操作而不是使它们溢出?我仔细阅读了Numpy文档,并问了CS部门的一些朋友,但是我还没有找到任何线索。
最后,我知道我可以在C中通过位旋转来完成其中的一些操作,但是我们项目的其余部分不可避免地是在Python中进行扩展的机会很小(鉴于Python,我宁愿使用Numpy作为矩阵乘法)。
谢谢!
答案 0 :(得分:1)
也许这样的事情对您有用。这是逐行进行的操作,因此您一次只需要在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
这会慢很多,但可能不会使您的内存超载。
如果这不起作用,您可以根据需要使用a
和b
关键字将np.load
和mmap_mode
的行和列加载到内存中,如{{ 3}}。然后,您可以执行计算row @ col
,以在所需数据范围内开发单个元素c[i,j]
。