Zen of Numpy 정리

Numpy 코딩 꿀팁들 모음인 Zen of numpy 발표 정리

결론은 : 넘파이 짱짱.

아래 발표 내용을 정리.

  • 배열을 활용한 효율적 계산을 위한 라이브러리

  • scipy, matplotlib, pandas, scikit-learn, statsmodels 같은 라이브러리 간의 공통 인터페이스

  • Tensorflow 는 numpy의 ndarray 기능에 약간의 추가적인 기능 + 자동미분 + GPU지원 추가

Numpy의 효율성은

  1. 데이터 저장 방식
  2. 데이터 접근 방식
  3. 벡터화된 연산의 결과물이다.

 

파이썬의 리스트는 포인트를 담고 있는 것이다. (C++ 코드를 까보면)
포인터의 배열 (객체가 메모리 여기저기 흩어져 있음) -> 캐시활용이 어려움

 

Numpy ndarray 구현

 

 

Numpy ndarray가 빠른 이유

  • ndarray는 타입을 명시하여 원소의 배열로 데이터를 유지 (여기저기 흩어져 있지 않음)

  • 다차원 데이터도 연속된 공간이 할당됨

  • 많은 연산이  strides를 잘 활용하면 효율적으로 가능

(가령 transpose는 strides를 바꾸는 것이 거의 공짜: 얼마만큼 보폭으로 비트를 건너 뛰느냐만 바꿔주면 바로 됨.)

  • ndarray의 구현 방식을 떠올리면 어떻게 성능을 내는 지 상상 가능

 

 

파이쎤 리스트 인덱싱

 

 

Numpy에서의 인덱싱

 

 

파이썬 슬라이싱

포인터 별로 따라가면서 원하는 원소 가져오고 새로 배열을 만듬.

 

 

 

Numpy  슬라이싱

추가적인 복사가 생기지 않음. (새로운 뷰를 들고 있는 것.)

 

 

 

연속된 접근과 등간격 접근

 

  • 인덱싱 혹은 슬라이싱 시 데이터의 복사가 없음

임의의 타입을 다뤘다면 불가능

원하는 것을 설명하는 편이 명령을 내리는 것보다 낫다. (데이터 타입 활용하자)

배열 지향이 대체로 객체 지향보다 낫다.

 

  • 등간격 접근과 연속된 데이터 접근 모두 캐시를 활용

  • 하지만 연속된 데이터를 가져오는 것이 더 효율적

(연속된 것이 등간격보다 낫다.)

 

 

인덱싱 / 슬라이싱 예제

 

 

 

파이썬 마스킹

 

Numpy fancy indexing

여기서는 사실 복사가 일어날 수 밖에 없다.

 

 

 

파이썬 인덱스 배열 사용

mask : 리스트 l 중에서 내가 원하는 것들의 배열을 들고 있는 리스트

 

 

Numpy Fancy Indexing

(mask는 위 코드에서 가져옴)

 

이 경우에도 복사는 일어날 수 밖에 없음. 하지만 코드가 훨씬 간결해짐.

 

 

 

흩어진 접근 / Fancy indexing

 

  • Fancy indexing 사용시 데이터의 복사가 필연적

어떤 규칙으로 메모리를 건너 뛰어야 하는지 모르기 때문

  • 캐시의 활용도 떨어짐

(결국 등간격으로 접근하지 않고 임의의 데이터를 접근하기 때문에 생기는 문제)

등간격이 흩어진 것보다 낫다.

  • 하지만 표현 방식이 간결하고 자연스러움 (루프는 왠만하면 안도는 게 나음)

원하는 것을 설명하는 편이 명령을 내리는 것보다 낫다. (데이터 타입을 사용하자.)

 

 

 

Fancy indexing 예제

 

a[0,1] : [0,1]의 원소를 가져옴

a[[0,1]] : 0번과 1번 배열들을 가져옴.

 

-> 인자로 넘어가는 게 tuple이냐 list냐에 따른 차이. (전자는 tuple, 후자는 list)

 

 

 

 

벡터화된 연산

 

  • 파이썬은 컴파일된 언어에 비해 느린 언어

타입정보를 활용할 수 없음.

  • 특정 종류의 연산을 미리 컴파일된 언어로 구현하였다면 추가적인 성능 확보 가능

벡터화된 연산을 사용

 

 

 

 

루프를 사용한 연산 vs 벡터화된 연산

numpy array타입이 더하기 operator를 오버라이드해서 구현이 되어 있을 것이다. (컴파일된 언어로 작성된 루틴이 돌 것이다.)

 

하지만 이런 연산에 있어서 성능 차이를 많이 가져옴

 

 

 

  • Numpy는 이미 다양한 벡터화된 연산을 컴파일된 코드로 제공

이런 연산을 ufunc라고 함

더 간결하고 효율적

원하는 것을 설명하는 편이 명령을 내리는 것보다 낫다

컴파일된 언어의 성능을 끌어다 쓸 수 있다.

벡터화 한 것이 명시적 루프보다 낫다.

(루프를 돌리는 것보다, 난 이런 연산을 하고 싶어 하고 명시해주는 것이 (컴파일된 연산을 사용하는 편이) 성능에 이득을 가져다 준다.)

  • 모든 연산은 기본적으로 개별 원소마다 일어난다. (elementwise)

  • 단, 파이썬에서 기본적으로 제공하는 함수와 섞어 쓰지 않을 것 (형변환이 일어날 수 있음)

 

 

벡터화된 연산 예제

 

브로드캐스팅 예제 (두개의 np array의 사이즈가 다를 경우)

-> 이렇든 기본적으로는 모양이 다른 배열간의 연산이 불가능 (elementwise 이기 때문에)

 

하지만 특정 조건이 만족되면 배열 변한이 자동으로 일어나서 연산 가능

(이를 브로드캐스팅이라고 함.)

 

 

<브로드캐스팅 규칙>

 

 

-> 이 때 내부적으로 구현되어 있는 걸 보면, 복사가 일어나지는 않는다.

 

  • 잡아당기는 연산은 명시적인 메모리 복사가 일어나지 않음

속도/메모리 이득

따라서 브로드캐스팅은 좋은 아이디어이다. (가능하면 사용하자.)

  • 브로드캐스팅과 꼴(shape) 변환을 활용하면 루프를 피할 수 있다.

뒤의 최단 거리 이웃 예제 참조

고차원에서 생각하라.

 

 

 

Reduction

 

개별 원소를 다 더하고 싶다거나, 각 축마다의 원소들을 더하고 싶다거나 다양한 요구사항에 대응.

 

파이썬으로 코드를 짜면 다음과 같다.

  • 같은 합연산이지만 매번 다른 방식으로 처리해야 한다.

  • 파이썬 루프이므로 느리다.

  • 이런 종류의 연산은 주어진 배열의 특정 축을 제거한다고 생각할 수 있다.

 

ndarray를 사용하면,

  • 같은 인터페이스를 통해 원하는 연산을 적용

원하는 것을 설명하는 편이 명령을 내리는 편보다 낫다.

  • 벡터화된 연산이므로 빠름

  • 여러차원의 reduction은 tuple을 인자로.

 

 

 

Example

 

Nearest Neighbor

 

  • 데이터의 이웃을 찾는 알고리즘

  • 비슷한 연신아 k-means, vector quantization에서도 사용됨.

 

-> 이것을 루프 없이 짜보면 다음과 같다.

 

 
코드를 자세히 살펴보면 다음과 같다.

 

import numpy as np

n = 1000

dim = 3

data = np.random.random(size = dim * n).reshape(n, dim)

데이터 준비

 

diff = data.reshape(n, 1, dim) – data

10003 행렬을 10001*3의 고차원 ndarray로 변환

브로드캐스팅에 의해 100010003의 결과가 나옴

벡터화된 빼기 연산

 

distance = np.sum(diff ** 2, axis = 2)

벡터화된 승수 연산

Reduction 더하기 연산 (마지막의 3차 축은 없애고 싶기 때문에)

 

oneself = np.arange(n)

distance[oneself, oneself] = np.inf

인덱싱

자기 자신과의 거리를 무한대로 설정

 

neighbors = np.argmin(distance, axis = 1)

최소값의 위치를 찾는 reduction

 

 

  • 앞서 다룬 아이디어를 사용해서 루프 없이 계산함

인덱싱

고차원 변환

벡터화된 연산 (ufunc)

Reduction

브로드캐스팅

  • 단, 고차원으로 변환한 뒤 수행하는 브로드캐스팅은 메모리를 많이 사용할 수 없음

문제에 따라서는 바깥 루프는 직접 도는 것이 효율적일 수도 있음.

 

 

_참고 자료

 

 

 

_다시한번 결론

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Advertisements
Posted in Dev

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s