防止矩阵乘法溢出? (脾气暴躁)

时间:2018-10-24 19:40:14

标签: python numpy integer overflow

我正在处理一些基于高维整数的数据,由于内存原因,我们必须对所有内容使用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作为矩阵乘法)。

谢谢!

1 个答案:

答案 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 

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

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