2017-10-15 1 views
-1

itertools.product의 결과로 numpy 배열을 만들고 싶습니다.itertools.product에서 큰 숫자 배열 만들기

from itertools import product 
import numpy as np 

max_init = 6 
init_values = range(1, max_init + 1) 
repetitions = 12 

result = np.array(list(product(init_values, repeat=repetitions))) 

이 코드는 "작은"repetitions이 (같은 < = 4), 그러나 "큰"값 (> = 12)와 완전히 메모리와 충돌을 독차지 잘 작동 : 내 첫 번째 방법은 간단했다. 목록을 작성하는 것이 모든 RAM을 먹는 것이라고 가정 했으므로 배열로 직접 만드는 방법을 모색했습니다. 나는 Numpy equivalent of itertools.productUsing numpy to build an array of all combinations of two arrays을 발견했다.

대안 # 1 :

results = np.empty((max_init**repetitions, repetitions)) 
for i, row in enumerate(product(init_values, repeat=repetitions)): 
    result[:][i] = row 

대안 # 2 :

init_values_args = [init_values] * repetitions 
results = np.array(np.meshgrid(*init_values_args)).T.reshape(-1, repetitions) 

대안 3 :

,536

그래서, 나는 다음과 같은 대안을 테스트

results = np.indices([sides] * num_dice).reshape(num_dice, -1).T + 1 

# 1은 매우 느립니다. 나는 그것을 끝내기에 충분한 인내심을 가지고 있지 않았다. (2017 년 맥북 프로에서 몇 분간 처리 한 후). # 2# 3은 초기 접근 방식과 마찬가지로 파이썬 인터프리터가 충돌 할 때까지 모든 메모리를 사용합니다.

그 후, 나는 여전히 유용했던 다른 방법으로 같은 정보를 표현할 수 있다고 생각했다 : dict 키는 가능한 모든 (정렬 된) 조합이 될 것이고 그 값은 이러한 조합. 그래서 시도 :

대체 # 4 :

from collections import Counter 

def sorted_product(iterable, repeat=1): 
    for el in product(iterable, repeat=repeat): 
     yield tuple(sorted(el)) 

def count_product(repetitions=1, max_init=6): 
    init_values = range(1, max_init + 1) 
    sp = sorted_product(init_values, repeat=repetitions) 
    counted_sp = Counter(sp) 
    return np.array(list(counted_sp.values())), \ 
     np.array(list(counted_sp.keys())) 

cnt, values = count(repetitions=repetitions, max_init=max_init) 

그러나 발전기의 모든 값을 받고 트리거 라인 counted_sp = Counter(sp)을, 또한 내 요구에 너무 느립니다 (그것은 또한 전에 몇 분이 걸렸다 나는 그것을 취소했다).

너무 느리거나 너무 많은 메모리를 사용하는 것과 같은 단점이없는 같은 데이터 (또는 동일한 정보를 포함하는 다른 데이터 구조)를 생성하는 또 다른 방법이 있습니까?

추신 : 위의 모든 구현을 작은 테스트 repetitions으로 테스트 한 결과 모든 테스트가 통과되어 일관된 결과를 얻을 수있었습니다.


질문을 편집하는 것이 최선의 방법이라고 생각합니다. 그렇지 않으면 알려주세요. 내가해야하는 곳에서 게시물을 편집합니다.

아래의 첫 번째 두 가지 대답을 읽고 그것에 대해 생각한 후에 잘못된 각도에서 문제에 접근하고 있음에 동의합니다. "무차별 공격"접근 방식 대신에 나는 확률을 사용하고 그걸로 작업해야했습니다.

다음은 각 조합에 대한 내용입니다. - 얼마나 많은 값이 임계 값 X 미만인지 계산합니다. - 얼마나 많은 값이 임계 값 X 이상이고 임계 값 Y 미만인지 계산합니다. - 임계 값 Y를 초과하는 값의 수를 계산합니다. 동일한 개수의 조합을 그룹화합니다. 예시적인 예로서

은 : I 6 변의 12 개 주사위 경우 는 값을 갖는 값으로 값> = 3 < 4, P 주사위 < 3 N 주사위 M 주사위를 갖는 확률 무엇 > 5, M, N 및 P의 가능한 모든 조합에 대해?

이렇게 새로운 접근 방식을 사용하는 동안 며칠 내에이 질문을 마무리하겠습니다. 모든 피드백과 시간을 내 주셔서 감사합니다!

+0

이 부분을보고 싶을 수도 있습니다. https://stackoverflow.com/a/11146645/4909087 –

+2

왜이 작업을 수행 하시겠습니까? 당신이 성공적으로 그것을 만들 수 있다고 가정하면 np.array로 무엇을 할 것입니까? –

답변

2

list(product(range(1,7), repeats=12))이 만드는 번호 튜플은 6 ** 12, 2,176,782,336입니다. 대부분의 컴퓨터에서 너무 큰 목록 또는 배열.

In [129]: A = np.ones((6**12,12),int) 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-129-e833a9e859e0> in <module>() 
----> 1 A = np.ones((6**12,12),int) 

/usr/local/lib/python3.5/dist-packages/numpy/core/numeric.py in ones(shape, dtype, order) 
    190 
    191  """ 
--> 192  a = empty(shape, dtype, order) 
    193  multiarray.copyto(a, 1, casting='unsafe') 
    194  return a 

ValueError: Maximum allowed dimension exceeded 

배열 메모리 크기,

In [130]: 4*12*6**12 
Out[130]: 104,485,552,128 

1백기가바이트

항목 당 4 바이트 :

In [119]: len(list(product(range(1,7),repeat=12))) 
.... 
MemoryError: 

직접적 크기의 어레이를 만들려고?

왜 7 자리 숫자의 2B 조합을 생성해야합니까?


그래서 당신의 카운터에 당신은 21 (2 회 반복) 36에서 항목

의 수
In [138]: sp = sorted_product(range(1,7), 2) 
In [139]: counter=Counter(sp) 
In [140]: counter 
Out[140]: 
Counter({(1, 1): 1, 
     (1, 2): 2, 
     (1, 3): 2, 
     (1, 4): 2, 
     (1, 5): 2, 
     (1, 6): 2, 
     (2, 2): 1, 
     (2, 3): 2, 
     (2, 4): 2, 
     (2, 5): 2, 
     (2, 6): 2, 
     (3, 3): 1, 
     (3, 4): 2, 
     (3, 5): 2, 
     (3, 6): 2, 
     (4, 4): 1, 
     (4, 5): 2, 
     (4, 6): 2, 
     (5, 5): 1, 
     (5, 6): 2, 
     (6, 6): 1}) 

을 줄일 수 있습니다. 더 많은 반복 (조합? 순열?)으로 이것을 일반화하는 것이 어렵지 않아야합니다. 여전히 시간 및/또는 메모리 경계를 밀어냅니다. mgrid 사용 meshgrid


변종 :

In [182]: timeit B=np.array(list(product(range(1,7),repeat=7))) 
317 ms ± 3.58 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 
In [183]: timeit A=np.mgrid[[slice(1,7)]*n].reshape(n,-1).T 
13.9 ms ± 242 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 

하지만, 그래, 그것은 동일한 전체 메모리 사용 및 제한이됩니다

In [175]: n=7; A=np.mgrid[[slice(1,7)]*n].reshape(n,-1).T 
In [176]: A.shape 
Out[176]: (279936, 7) 
In [177]: B=np.array(list(product(range(1,7),repeat=7))) 
In [178]: B.shape 
Out[178]: (279936, 7) 
In [179]: A[:10] 
Out[179]: 
array([[1, 1, 1, 1, 1, 1, 1], 
     [1, 1, 1, 1, 1, 1, 2], 
     [1, 1, 1, 1, 1, 1, 3], 
     [1, 1, 1, 1, 1, 1, 4], 
     [1, 1, 1, 1, 1, 1, 5], 
     [1, 1, 1, 1, 1, 1, 6], 
     [1, 1, 1, 1, 1, 2, 1], 
     [1, 1, 1, 1, 1, 2, 2], 
     [1, 1, 1, 1, 1, 2, 3], 
     [1, 1, 1, 1, 1, 2, 4]]) 
In [180]: B[:10] 
Out[180]: 
array([[1, 1, 1, 1, 1, 1, 1], 
     [1, 1, 1, 1, 1, 1, 2], 
     [1, 1, 1, 1, 1, 1, 3], 
     [1, 1, 1, 1, 1, 1, 4], 
     [1, 1, 1, 1, 1, 1, 5], 
     [1, 1, 1, 1, 1, 1, 6], 
     [1, 1, 1, 1, 1, 2, 1], 
     [1, 1, 1, 1, 1, 2, 2], 
     [1, 1, 1, 1, 1, 2, 3], 
     [1, 1, 1, 1, 1, 2, 4]]) 
In [181]: np.allclose(A,B) 

mgrid는 꽤 빠르다. N = 10

,

ValueError: array is too big; `arr.size * arr.dtype.itemsize` is larger than the maximum possible size. 
0

올바른 답은하지 마십시오. 이러한 모든 조합으로 무엇을하고 싶든 한 번에 하나씩 생성하여 저장하지 않고 즉시 사용하거나 더 나은 방법으로 모든 조합을 검사하지 않고 작업을 수행 할 수있는 방법을 찾으십시오. 현재의 솔루션은 장난감 문제에 대해 작동하지만 더 큰 매개 변수에는 적합하지 않습니다. 자신이 무엇을하고 있는지, 그리고 누군가가 도움을 줄 수 있다고 설명하십시오.