2016-05-03 4 views
1

Я использую tyring, чтобы сделать мой код быстрее, удалив некоторые из циклов и используя массивы. Самый медленный шаг прямо сейчас - генерация случайных списков.создать двумерный массив numpy.random.choice без замены

контексте: У меня есть ряд мутаций в хромосоме, я хочу выполнить 1000 случайных «хромосом» с одинаковой длиной и одинаковым числом мутаций, но их положения рандомизированы.

вот что я в настоящее время работает, чтобы генерировать эти рандомизированные позиции мутации:

iterations=1000 
Chr_size=1000000 
num_mut=500 
randbps=[] 
for k in range(iterations): 
listed=np.random.choice(range(Chr_size),num_mut,replace=False) 
randbps.append(listed) 

Я хочу сделать что-то подобное тому, что они охватывают в this question

np.random.choice(range(Chr_size),size=(num_mut,iterations),replace=False) 

однако без замены применяется к массив в целом.

далее контекст: в сценарии я пройти через каждый рандомизированного хромосоме и подсчета числа мутаций в данном окне:

for l in range(len(randbps)): 

    arr=np.asarray(randbps[l]) 

    for i in range(chr_last_window[f])[::step]: 

     counter=((i < arr) & (arr < i+window)).sum() 
+0

Вы не хотите какой-либо из 'listed's быть тем же самым, что означает' элементы randbps' должен быть уникальным ? – ayhan

+0

Это вызвано долгой проблемой производительности: https://github.com/numpy/numpy/issues/2764 –

ответ

1

Я не знаю, как реализуется np.random.choice, но я предполагаю, что он оптимизирован для общего случая. С другой стороны, ваши номера вряд ли будут воспроизводить одни и те же последовательности. Наборы могут быть более эффективными в этом случае, строительство с нуля:

import random 

def gen_2d(iterations, Chr_size, num_mut): 
    randbps = set() 
    while len(randbps) < iterations: 
     listed = set() 
     while len(listed) < num_mut: 
      listed.add(random.choice(range(Chr_size))) 
     randbps.add(tuple(sorted(listed))) 
    return np.array(list(randbps)) 

Эта функция начинается с пустого множества, генерирует одно число в диапазоне (Chr_size) и добавляет, что число в наборе. Из-за свойств наборов он не может снова добавить одно и то же число. Он делает то же самое и для рандбпс, поэтому каждый элемент randbps также уникален.

Только для одной итерации np.random.choice против gen_2d:

iterations=1000 
Chr_size=1000000 
num_mut=500 

%timeit np.random.choice(range(Chr_size),num_mut,replace=False) 
10 loops, best of 3: 141 ms per loop 

%timeit gen_2d(1, Chr_size, num_mut) 
1000 loops, best of 3: 647 µs per loop 
+0

этот работает быстрее, чем другой ответ, а также не занимает столько памяти. Намного лучше! –

+0

Я не мог полностью понять идею ответа Дивакара, но на самом деле речь идет о скорости мутации. Если бы частота мутаций составляла 50%, ответ был бы в 100 раз быстрее, чем у меня. У обоих есть свои сильные и слабые стороны. – ayhan

+1

Существует также ['random.sample'] (https://docs.python.org/2/library/random.html#random.sample), который может работать непосредственно с' xrange' (в Python 2.x). –

1

на основе трюк используется в this solution, вот такой подход, который использует argsort/argpartition на массив случайных элементов для моделирования numpy.random.choice without replacement дать нам randbps как 2D массив -

np.random.rand(iterations,Chr_size).argpartition(num_mut)[:,:num_mut] 

выполнения тест -

In [2]: def original_app(iterations,Chr_size,num_mut): 
    ...:  randbps=[] 
    ...:  for k in range(iterations): 
    ...:   listed=np.random.choice(range(Chr_size),num_mut,replace=False) 
    ...:   randbps.append(listed) 
    ...:  return randbps 
    ...: 

In [3]: # Input params (scaled down version of params listed in question) 
    ...: iterations=100 
    ...: Chr_size=100000 
    ...: num=50 
    ...: 

In [4]: %timeit original_app(iterations,Chr_size,num) 
1 loops, best of 3: 1.53 s per loop 

In [5]: %timeit np.random.rand(iterations,Chr_size).argpartition(num)[:,:num] 
1 loops, best of 3: 424 ms per loop 
+0

этот код отлично работает в моем скрипте. Спасибо за отличный совет. –

+0

, когда я увеличиваю число итераций в моем скрипте до 1000, мой компьютер сильно сработает. Я думаю, это может быть потому, что весь массив хранится в памяти. ~ 46 ГБ требований к памяти не подходит для моего ноутбука 16 Гб. –

+0

@ LukeAnderson-Trocme Да, действительно огромные массивы были бы проблемой, я думаю. – Divakar

Смежные вопросы