Предотвратить переполнение в матричном умножении?(Numpy) - PullRequest
0 голосов
/ 24 октября 2018

Я работаю над некоторыми многомерными целочисленными данными, и по соображениям памяти мы должны использовать 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

Для пояснения, я не просто ищу лишние пробелы без знака, которые можно себе позволить - значения в b иногда могут быть отрицательными.(Я только что сделал все положительные, чтобы проиллюстрировать мою точку зрения.)

Есть ли алгоритм или трюк Numpy, которые позволили бы мне ограничить эти операции, а не переполнять их?Я просмотрел документацию Numpy и спросил некоторых моих друзей в отделе CS, но мне еще предстоит найти какие-либо рекомендации по этому вопросу.

Наконец, я знаю, что мог бы сделать кое-что в C снемного сложновато, но остальная часть нашего проекта неизбежно в Python с небольшим шансом расширения (и учитывая Python, я бы предпочел использовать Numpy для умножения матриц, если это вообще возможно).

Спасибо, всем!

1 Ответ

0 голосов
/ 25 октября 2018

Может быть, что-то вроде этого будет работать для вас.Это выполняет операцию строка за строкой, поэтому вам нужно удерживать только одну строку за раз в типе данных 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, как объяснено здесь ,Затем вы можете выполнить вычисление row @ col для разработки одного элемента c[i,j] в нужном диапазоне данных.

...