numpy의 기본이 아닌 기술

11782 단어 파이썬numpy
numpy의 빠른 시작 자습서 에 Less basic(별로 기본적이지 않은) 테크닉이 있어 재미있을 것이라고 생각했으므로, 이해 드디어 소개.

배열을 사용한 배열 인덱스



배열의 인덱스(a[i]에 있어서의 i의 부분)에는 스칼라치를 가지는 것이 일반적입니다만, 여기에 배열을 넣을 수도 있습니다.
import numpy as np

a = np.arange(12)**2                       
i = np.array([1, 1, 3, 8, 5])             
a[i] #array([ 1,  1,  9, 64, 25], dtype=int32)

무슨 일이 일어나고 있는지, 그림처럼 보입니다.



배열 i의 요소가 인덱스가 되어 그것을 사용하여 a의 배열에서 추출해 오는 이미지일까요?

인덱스가 2차원 배열에도 적용될 수 있습니다. 이 경우 출력도 2차원이 됩니다.
j = np.array([[3, 6, 7], [5, 9, 7]])      
a[j]                                       
#array([[ 9, 36, 49],
#       [25, 81, 49]], dtype=int32)

튜토리얼 쪽에서는 RGB를 응용예로서 내고 있습니다만, 기계 학습으로 사용되는 one-hot 표현시에도 사용할 수 있을 것 같네요.
one_hot = np.array([[0, 0, 0], 
                    [1, 0, 0], 
                    [0, 1, 0],      
                    [0, 0, 1]])
number = np.array([[0, 1, 2, 0], 
                  [0, 3, 2, 0]])
one_hot[number]
#array([[[0, 0, 0],
#        [1, 0, 0],
#        [0, 1, 0],
#        [0, 0, 0]],
#
#       [[0, 0, 0],
#        [0, 0, 1],
#        [0, 1, 0],
#        [0, 0, 0]]])

덧붙여서 number[one_hot[number]] 라고 해도 원래대로 돌아가는 것은 아니기 때문에 주의.

또, 인덱스에는 복수의 배열을 지정할 수도 있습니다.
a = np.arange(12).reshape(3,4)
#array([[ 0,  1,  2,  3],
#       [ 4,  5,  6,  7],
#       [ 8,  9, 10, 11]])
i = np.array([[0, 1],                     
              [1, 2]])
j = np.array([[2, 1],                     
              [3, 3]])
a[i, j] 
#array([[ 2,  5],
#      [ 7, 11]])

이것 또 어떻게 처리하고 있는지 해석이 어려운 곳입니다만, 다음과 같이 되어 있습니다.



배열의 인덱스에는, 리스트를 지정할 수도 있습니다.
a = np.arange(3,8)
a
#array([3, 4, 5, 6, 7])
a[[1,3,4]] = 0
a
#array([3, 0, 5, 0, 0])

이 때도 목록의 각 요소가 a의 인덱스로 처리됩니다.

리스트를 사용해 단번에 할당(대입)할 수도 있습니다만, 리스트내에 같은 수치가 있는 경우, 할당은 반복되어 마지막의 값이 대입됩니다.
a = np.arange(3,8)
a
#array([3, 4, 5, 6, 7])
a[[1,1,4]] = [1,2,3]
a
#array([3, 2, 5, 6, 3])

부울 배열을 사용한 인덱싱



배열에 논리 연산자를 주면 부울 배열을 만들 수 있습니다.

부울 배열을 인덱스로 하는 것으로, False가 되는 요소를 제거한 1차원 배열을 출력합니다(배열의 형태에 주의).
a = np.arange(-3,9).reshape(3,4)
a
#array([[-3, -2, -1,  0],
#       [ 1,  2,  3,  4],
#       [ 5,  6,  7,  8]])
b = a > 0
b                                   
#array([[False, False, False, False],
#       [ True,  True,  True,  True],
#       [ True,  True,  True,  True]])
a[b]                                       
#array([1, 2, 3, 4, 5, 6, 7, 8])

부울 배열을 인덱스로 하는 배열에 할당하는 것으로, 조건에 맞는 요소에 한 번에 대입할 수가 있습니다.
a[a<0] = 0                                  
a
#array([[0, 0, 0, 0],
#       [1, 2, 3, 4],
#       [5, 6, 7, 8]])

차원(축)과 같은 부울 배열을 사용하면 보다 복잡한 추출도 가능합니다.
a = np.arange(12).reshape(3,4)
b1 = np.array([False,True,True])             
b2 = np.array([True,False,True,False])     

a[b1,:] #a[b1]でも可                                 
#array([[ 4,  5,  6,  7],
#       [ 8,  9, 10, 11]])

a[:,b2] #a[b2]でも可                             
#array([[ 0,  2],
#       [ 4,  6],
#       [ 8, 10]])

a[b1,b2]                                 
#array([ 4, 10])

그림으로 보면 이런 간지.



이것, 왜 a[b1,b2]가[[4,6],[8,10]]가 아니고[4,10]이지요. 문서에도 a weird thing to do(이상한 것)라고 쓰고 있으므로, 그렇게 기억할 수밖에 없는 것일까요.

요약



이상, 배열을 이용한 배열의 인덱스와, 부울 배열을 사용한 인덱싱에 대해 소개했습니다. 취급이 어려운 기술이지만, 잘 다루면 분명 도움이 될 것입니다.

서두에 링크를 붙인 튜토리얼에는, 그 밖에도 테크닉이 실려 있다(잘 이해할 수 없었기 때문에 할애) 때문에, 여유가 있는 사람은 꼭 읽어 봐 주세요.

좋은 웹페이지 즐겨찾기