создать большой массив в сумерках - PullRequest
0 голосов
/ 09 марта 2020

Я хотел бы рассчитать SVD из большой матрицы на Dask . Тем не менее, я наивно пытался создать пустой 2D-массив и обновить его в al oop, но Dask не позволяет изменять массив. Итак, я ищу обходной путь. Я пытался сохранить большой (около 65 000 x 65 000 или даже больше) массив в HDF5 с помощью h5py, но обновление массива в al oop довольно неэффективно. Должен ли я использовать mmap с отображением памяти numpy вместо?

Ниже я поделился примером кода без какой-либо реализации dask. Должен ли я использовать dask.bag или dask.delayed для этой операции?

Пример кода принимает длинные строки и размер окна 8, генерирует комбинации из двухбуквенных слов. В реальных данных размер окна будет 20, а слова будут длиной 8 букв. И длина входной строки может составлять 3 Гб.

import itertools
import numpy as np
np.set_printoptions(threshold=np.Inf)

# generate all possible words of length 2 (AA, AC, AG, AT, CA, etc.) 
# then get numerical index (AA -> 0, AC -> 1, etc.)
bases=['A','C','G','T']
all_two = [''.join(p) for p in itertools.product(bases, repeat=2)]
two_index = {x: y for (x,y) in zip(all_two, range(len(all_two)))}

# final array to fill, size is [ 16 possible words x 16 possible words ]
counts = np.zeros(shape=(16,16))  # in actual sample we expect 65000x65000 array

# sample sequences (these will be gigabytes long in actual sample)
seq1 = "AAAAACCATCGACTACGACTAC"
seq2 = "ACGATCACGACTACGACTAGATGCATCACGACTAAAAA"

# accumulate results
all_pairs=[]

def generate_pairs(sequence):
    pairs=[]
    for i in range(len(sequence)-8+1):
        window=sequence[i:i+8]
        words= [window[i:i+2] for i in range(0, len(window), 2)]
        for pair in itertools.combinations(words,2):
            pairs.append(pair)
    return pairs

# use function for each sequence
all_pairs.extend(generate_pairs(seq1))
all_pairs.extend(generate_pairs(seq2))

# convert 1D array of pairs into 2D counts of pairs
# for each pair, lookup word index and increase corresponding cell
for j in all_pairs:
    counts[ two_index[j[0]], two_index[j[1]] ] += 1

print(counts) 

РЕДАКТИРОВАТЬ: Я мог бы задать вопрос немного сложнее, позвольте мне перефразировать его. Мне нужно построить один большой 2D-массив размером ~ 65000x65000. Массив должен быть заполнен подсчетом вхождений пар (word1,word2). Поскольку Dask не разрешает назначение / изменение элемента для массива Dask, я не могу заполнить массив, поскольку пары обрабатываются. Есть ли обходной путь для создания / заполнения большого 2D-массива с помощью Dask?

Вот более простой код для тестирования:

import itertools
import numpy as np
np.set_printoptions(threshold=np.Inf)

bases=['A','C','G','T']
all_two = [''.join(p) for p in itertools.product(bases, repeat=2)]
two_index = {x: y for (x,y) in zip(all_two, range(len(all_two)))}

seq = "AAAAACCATCGACTACGACTAC"

counts = np.zeros(shape=(16,16))

for i in range(len(seq)-8+1):
    window=seq[i:i+8]
    words= [window[i:i+2] for i in range(0, len(window), 2)]
    for pair in itertools.combinations(words,2):
        counts[two_index[pair[0]], two_index[pair[1]]] += 1  # problematic part!

print(counts)
...