2014-05-15 3 views
4

내가 꽤 큰 NumPy와 배열을 가지고 ...NumPy와 다차원 색인 및 대각선 대칭

power = ... 
print power.shape 
>>> (3, 10, 10, 19, 75, 10, 10) 

다음과 같은 2 차원 행렬 즉 10 × 부품, I이 인자 4 게인을 이용할 수 m

, I, J, K, L의 모든 값

power[i, :, :, j, k, l, m] 
power[i, j, k, l, m, :, :] 

대칭? 예 : 매트릭스가 (savez_compressed 50 메가 바이트) 파일로 저장할 때

내 시도 :

size = 10 
row_idx, col_idx = np.tril_indices(size) 
zip_idx = zip(row_idx, col_idx) 
print len(zip_idx), zip_idx[:5] 
>>> 55 [(0, 0), (1, 0), (1, 1), (2, 0), (2, 1)] 
all_idx = [(r0, c0, r1, c1) for (r0, c0) in zip_idx for (r1, c1) in zip_idx] 
print len(all_idx), all_idx[:5] 
>>> 3025 [(0, 0, 0, 0), (0, 0, 1, 0), (0, 0, 1, 1), (0, 0, 2, 0), (0, 0, 2, 1)] 
a, b, c, d = zip(*all_idx) 
tril_part = np.transpose(s.power, (0, 3, 4, 1, 2, 5, 6))[:,:,:, a, b, c, d] 
print tril_part.shape 
>>> (3, 19, 75, 3025) 

이 추한 것,하지만 "작품"... 나는 또한 tril_part에서 다시 힘을 얻을 수 있습니다 일단 ... tril_part 전원에서가는

  1. 더 나은 방법 :

    나는이 두 qurestions를 얻을 것 같아요?
  2. tril_part에서 전원으로 이동하는 방법은 무엇입니까?

편집 : "size"주석은 분명히 유효하지만 무시하십시오 :-) 질문의 색인 부분은 혼자입니다. 나는 더 작은 행렬에 대해 비슷한 색인을 만들고 싶었다.

+1

모든 상단 삼각형을 설정 다시 비교하기 위해 에

비교, 당신은 확실히 35메가바이트 절약 정말 가치가 있습니까? – Daniel

+0

@Ophion : 실제로는 "있습니다". 3 * 10 * 10 * 19 시뮬레이션 결과로 75 개의 10x10 행렬이 생성됩니다. 나는 이것을 이렇게 저장하는 것이 편리하고 자연 스럽다는 것을 안다. 그리고 "조각 내기"를 위해 접근 자 함수를 사용한다. –

+0

'파워'의 dtype은 무엇입니까? – gg349

답변

1

올바른 경로에 있습니다. np.tril_indices을 사용하면 이러한 하위 삼각형을 실제로 멋지게 색인 할 수 있습니다. 개선해야 할 부분은 데이터의 실제 인덱싱/슬라이싱입니다.

이 (복사 및 pasteable)를 시도하십시오 :

import numpy as np 
shape = (3, 10, 10, 19, 75, 10, 10) 
p = np.arange(np.prod(shape)).reshape(shape) # this is not symmetric, but not important 

ix, iy = np.tril_indices(10) 
# In order to index properly, we need to add axes. This can be done by hand or with this 
ix1, ix2 = np.ix_(ix, ix) 
iy1, iy2 = np.ix_(iy, iy) 

p_ltriag = p[:, ix1, iy1, :, :, ix2, iy2] 
print p_ltriag.shape # yields (55, 55, 3, 19, 75), axis order can be changed if needed 

q = np.zeros_like(p) 
q[:, ix1, iy1, :, :, ix2, iy2] = p_ltriag # fills the lower triangles on both sides 
q[:, ix1, iy1, :, :, iy2, ix2] = p_ltriag # fills the lower on left, upper on right 
q[:, iy1, ix1, :, :, ix2, iy2] = p_ltriag # fills the upper on left, lower on right 
q[:, iy1, ix1, :, :, iy2, ix2] = p_ltriag # fills the upper triangles on both sides 

배열 q 이제 (위쪽 삼각형이 아래 삼각형의 내용으로 대체되었다) p의 대칭 된 버전이 포함되어 있습니다. 마지막 행은 역순으로 iyix 색인을 포함하며, 본질적으로 하위 삼각 행렬의 전치를 작성합니다. 낮은 삼각형, 우리가 배열이 현실적으로 그렇게 큰되지 않습니다 0

ux, uy = np.triu_indices(10) 
p[:, ux, uy] = 0 
q[:, ux, uy] = 0 
p[:, :, :, :, :, ux, uy] = 0 
q[:, :, :, :, :, ux, uy] = 0 

print ((p - q) ** 2).sum() # euclidean distance is 0, so p and q are equal 

print ((p ** 2).sum(), (q ** 2).sum()) # prove that not all entries are 0 ;) - This has a negative result due to an overflow 
+0

나중에 다시 압축해야하는 경우이 압축을 수행하는 것이 합리적인지 여부는 확실하지 않습니다. – eickenberg

+0

np.ix_ 확실히가는 길 같습니다. 내 도구 상자에 추가. 그러나 원래 (p)와 결과 (q)에서 np.allclose를 수행하면 False가됩니다. 또한 인덱스 1과 2를 사용하는 이유와 ix와 iy를 재사용하지 않는 이유를 왜 이해하지 못합니까? 가독성? 4 개의 인덱스가 아닌 2 개의 인덱스 만 사용하면 충분합니까? 예 : 55 * 55 조합 모두?나는 후자의 접근 방식을 가지고 놀았지만, '차원 높은 색인'ValueError를 너무 많이 가져 왔습니다. –

+0

'np.ix_'는 참으로 유용한 명령입니다. 'p'와'q'는 아래 삼각형의 반쪽에서만 일치하고'q'는'p'의 대칭 버전입니다 (''p''를 생성하는 코드에서 내 주석을보십시오. 대칭). 가독성과 일반화를 위해'ix1'과'ix2'를 만들었습니다. 귀하의 경우에는'ix1'에는'ix [:, np.newaxis]','ix2'에는'ix [np.newaxis, :]'라고 쓸 수 있습니다. 다른 축을 추가하는 것은 매우 중요합니다.이 방법은 numpy가 인덱스의 데카르트 곱을 생성하므로 매우 중요합니다. 출력 배열의 치수를 확인하십시오 (크기 55의 축이 두 개 있음). – eickenberg