2016-08-19 2 views
2

У меня есть список python, который является огромным (16 ГБ), и я хочу преобразовать его в массив numpy, inplace. Я не могу позволить себе это утверждениеПреобразование списка Python в Numpy Array InPlace

huge_array = np.array(huge_list).astype(np.float16) 

Я ищу для некоторых эффективных способов преобразования этого huge_list в numpy array без его копирования.

Может ли кто-нибудь предложить эффективный метод для этого? что может потребоваться сначала сохранить список на диск, а затем загрузить его как массив numpy, я в порядке с этим.

Я буду очень признателен за любую помощь.

EDIT 1: huge_list - это список python в памяти, который создается во время выполнения, поэтому он уже принимает 16 ГБ. Мне нужно преобразовать его в массив numpy float16.

+0

вы исключили np.save и np.load? –

+0

Использует ли этот метод 'np.array' слишком длинный или создает ошибку памяти? – hpaulj

+0

Меня беспокоит память, а не скорость. Таким образом, np.array скорее всего вызовет ошибку памяти. @DanPatterson огромный_list еще не на диске. Это память, которая создается во время выполнения, тогда мне нужно преобразовать ее в массив numpy float16. – Ahmed

ответ

2

np.array(huge_list, dtype=np.float16) будет быстрее, так как он только копирует список один раз, а не дважды


Вы, наверное, не нужно беспокоиться о том, чтобы эту копию, потому что копия является намного меньше, чем оригинал:

>>> x = [float(i) for i in range(10000)] 
>>> sys.getsizeof(x) 
83112 
>>> y = np.array(x, dtype=np.float16) 
>>> sys.getsizeof(y) 
20096 

Но это даже не самое худшее - со списком питона, каждый номер в списке занимает память о его собственный:

>>> sum(sys.getsizeof(i) for i in x) 
240000 

Таким образом, массив numpy ~ 15x меньше!

+0

Память здесь важна, скорость - второстепенная проблема. – Ahmed

+0

Использует 1/5 память 'np.array (huge_list) .view (np.float16)', также, предполагая, что 'огромный_list' содержит поплавки – Eric

+0

спасибо за указание, что я уже исправил это, но точка есть, моя машина имеет 32 ГБ памяти. Список имеет размер 16 ГБ (float16), я не хочу переполнять свою память, создавая еще одну копию размером 16 ГБ. – Ahmed

2

Как я уже упоминал ранее, самым простым было бы просто выгрузить массив в файл, а затем загрузить этот файл в виде массива numpy.

Сначала нужно размер огромного списка:

huge_list_size = len(huge_list) 

Далее мы дамп на диск

dumpfile = open('huge_array.txt', 'w') 

for item in huge_list: 
    dumpfile.write(str(item)+"\n") 
dumpfile.close() 

Убедитесь, мы очищаем память, если все это происходит в той же среде

del huge_list 

Далее мы определяем простой генератор чтения

def read_file_generator(filename): 
    with open(filename) as infile: 
     for i, line in enumerate(infile): 
      yield [i, line] 

И тогда мы создаем Numpy массив нулей, которые мы заполняем с генератором мы только что создали

huge_array = np.zeros(huge_list_size, dtype='float16') 

for i, item in read_file_generator('huge_array.txt'): 
    huge_array[i] = item 

Мой предыдущий ответ был неверным. Я предложил следующее быть решение, которое он не так Ответил hpaulj

Вы можете сделать это в несколько способов, самый простой будет просто сбросить массива в файл, а затем загрузить файл как Numpy массива:

dumpfile = open('huge_array.txt', 'w') 

for item in huge_array: 
    print>>dumpfile, item 

Затем загрузите его в качестве Numpy массива

huge_array = numpy.loadtxt('huge_array.txt') 

Если вы хотите, чтобы выполнить дальнейшие вычисления по этим данным вы можете также используйте библиотеку joblib для memmapping, которая чрезвычайно полезна в , обрабатывая массивы с большими числами.Доступен в https://pypi.python.org/pypi/joblib

+2

Но 'loadtxt' загружает значения в список и выполняет' np.array (alist) 'как только они будут загружены. – hpaulj

+0

Я проверил источник np.loadtxt в numpy 1.10.4, чтобы убедиться. На строке 808 в npyio в методе loadtxt список действительно указан и вскоре считывается, а в строке 936 список преобразуется в массив numpy через вызов np.array (X, dtype). Спасибо, я этого не знал. Я отрегулирую свой ответ как можно скорее – Laurens

+0

Обновлен ответ, как и было обещано. Я должен согласиться с hpaulj, что chunking может быть лучшим решением, но это нужно было бы сделать во время генерации данных и не ответило бы на вопрос. – Laurens

0

Вы можете использовать save и load функции numpy «s:

Вы можете использовать обычный список питона в качестве аргумента np.save и np.load будет загружаться непосредственно в Numpy массив.

Пример:

from tempfile import TemporaryFile 
outfile = TemporaryFile() 
x = [1, 2, 3] 
np.save(outfile, x) 

outfile.seek(0) 
np.load(outfile)