* 이 글은 <밑바닥부터 시작하는 딥러닝2 (저자: 사이토 고키)> 책을 읽으며 정리한 글입니다.
* 나중에라도 제가 참고하기 위해 정리해 두었으며, 모든 내용을 적은 것이 아닌,
필요하다고 생각되는 부분만 추려서 정리한 것임을 미리 밝힙니다.
목차
- 넘파이(numpy)의 정의
- 넘파이(numpy)의 연산
- 넘파이(numpy)의 N차원 배열
- 브로드캐스트(broadcast)
- 원소 접근
1. 넘파이(numpy)의 정의
넘파이(numpy)는 벡터나 행렬 연산을 빠르게 하는 도구다. 다르게 말하자면, 배열을 다루는 도구이다.
넘파이는 한 개 이상의 원소를 가진 배열 형태라면 모두 "넘파이"라는 그릇에 담아버린다.
앞으로 과학적인 분석이나 딥러닝을 할 때 심심찮게 볼 수 있을 것이다. numpy는 다들 풀네임 쓰기 귀찮아해서 관용적으로 np라고 쓴다.
외부 라이브러리이기 때문에 다음 코드를 이용해서 불러온다.
import numpy as np
배열의 형태를 가진 모든 것들은 넘파이(numpy)가 될 수 있다.
a = [1, 2, 3]
aa = np.array(a)
b = (1, 2, 3)
bb = np.array(b)
aa == bb
리스트 형태이든, 튜플 형태이든 상관 없이 '1'과 '2'와 '3'의 원소를 지닌 배열을 "넘파이(numpy)"라는 그릇 안에 담기 때문에 마지막 줄의 aa==bb
검사를 실행했을 때에 array([True, True, True])
와 같은 결과가 나온다.
2. 넘파이(numpy)의 연산
많은 이들이 넘파이(numpy)를 사용하는 이유는 넘파이(numpy)의 강력한 연산 기능 때문이다.[1, 2, 3]
과 같은 리스트가 있을 때, 이 각각의 원소를 모두 -1 하는 코드를 생각해보자. 다음과 같이 작성할 수 있을 것이다.
a = [1, 2, 3]
result = []
for i in a:
result.append(i-1)
혹은 리스트 컴프리핸션을 이용해 다음과 같이 작성할 수도 있을 것이다.
a = [1, 2, 3]
[ i-1 for i in a ]
하지만 넘파이(numpy)를 이용하면 간단해진다.
a = np.array([1, 2, 3])
a -= 1
a
라는 넘파이(numpy) 개체 선언 이후에 -1만 해주면 일일이 a
안의 원소를 다 찾아가며 -1을 해줄 필요 없이 모든 원소에 적용되어 한번에 연산이 된다.
이러한 간편함은 넘파이(numpy) 개체끼리의 연산에서도 돋보인다. 길이가 같은 두 넘파이(numpy)배열 x
와 y
를 생각해보자.
x = np.array([1, 2, 3])
y = np.array([2, 4, 6])
x + y
위와 같은 코드가 실행되었을 때, 넘파이는 똑똑하게도 array([3, 6, 9])
라는 결과를 내놓는다. x
의 첫번째 요소와 y
의 첫번째 요소, x
의 두번째 요소와 y
의 두번째 요소를 각각 매칭시켜 주는 것이다.
반면, 그냥 리스트 형태일 경우를 생각해보자.
# wrong case
x = [1, 2, 3]
y = [2, 4, 6]
x + y
리스트 자료형을 완벽하게 학습한 사용자라면, 위의 결과는 [1, 2, 3, 2, 4, 6]
로 나옴을 금방 알 수 있다. 사실 덧셈 연산이어서 그나마 결과라도 나오지, -
나 *
, /
등의 리스트끼리의 연산은 계산 결과도 나오지 않고 에러가 뜬다.
3. 넘파이(numpy)의 N차원 배열
앞서 정의에서 언급했듯이, 넘파이(numpy)는 행렬을 손쉽게 다룰 수 있는 도구다.
호기심 많은 독자는 궁금증이 생길 것이다. '우리는 지금까지 숫자만 넘파이(numpy)에 담고 있는데, 다른 것도 담을 수 있나요? 이를테면 문자나 리스트 같은 것도요.'
당연히 가능하다. 앞서 정의한 바를 상기해 보면, 한 개 이상의 원소를 가진 배열 형태는 모두 넘파이(numpy) 형태로 표현할 수 있다.
문자는 각자 실험해 보시고, 이번 시간에는 배열을 담은 배열에 초점을 맞춰 설명하겠다. 리스트를 다뤄본 사용자라면, 리스트 안에 리스트를 담는 게 이상하지는 않을 것이다.
A = [[1, 2], [2, 3]]
혹은
a = [1, 2]
b = [2, 3]
A = [a, b]
와 같은 형태들이 이상하지 않다.
넘파이(numpy)도 마찬가지다.
a = [1, 2]
b = [2, 3]
A = np.array([a, b])
일 때, print(A)
하면 다음과 같은 결과가 나온다.
[[1 2]
[2 3]]
4. 브로드캐스트(broadcast)
넘파이(numpy)에서는 형상이 다른 배열끼리라도 계산할 수 있고, 이것을 브로드캐스트(broadcast)라고 한다.
다음의 예제를 보자.
A = np.array([[1, 2], [3, 4]])
B = np.array([10, 20])
A * B
위의 코드를 수행하면 다음과 같은 결과가 나온다.
array([[10, 40],
[30, 80]])
즉, B의 np.array([10, 20])
가 A의 첫번째 원소인 np.array([1, 2])
와 연산을 하고, A의 두번째 원소인 np.array([3, 4])
와도 연산을 한다. 전역에 퍼지는 방송처럼, 모든 원소에 영향을 주는 것이다. 이것을 넘파이(numpy)에서의 브로드캐스트(broadcast)라고 한다.
앞서 소개한, 모든 원소를 -1하는 연산도 사실 브로드캐스트(broadcast)에 의한 것이다.
5. 원소 접근
넘파이(numpy)도 리스트와 동일하게, 슬라이싱(slicing), 인덱스 지정 등으로 원소에 접근할 수 있다.
하지만 리스트 자료형과 다른 점이 있는데, 여러 개의 원소를 한번에 인덱스 지정할 수 있다는 것이다.
a = np.array([10, 20, 30, 40, 50])
a[np.array([0, 2, 4])]
위와 같은 코드를 실행하면 다음과 같은 결과가 나온다. array([10, 30, 50])
즉, 0번째, 2번째, 4번째 원소가 호출되는 것이다.
이러한 성격 때문인지 다음과 같은 코드도 실행이 가능하다.
a = np.array([10, 20, 30, 40, 50])
a[a>25]
array([30, 40, 50])
의 결과가 나온다.
두번째 다른 점은 다차원 배열에서 도드라진다.
다음과 같은 행렬 A를 생각해보자. A = np.array([[1,2],[10,20],[50,100]])
이것을 보기 쉽게 기입하면 다음과 같은 형태가 나올 것이다.
array([[ 1, 2],
[ 10, 20],
[ 50, 100]])
첫번째 컬럼, 즉 [[1],[10],[50]]
을 얻고 싶을 때 다음과 같이 실행하면 된다.
A[:,:1]
그럼 다음과 같은 결과를 볼 수 있다.
array([[ 1],
[10],
[50]])
정리
지금까지 넘파이(numpy)의 기본적 속성들과 간단한 규칙에 대해 알아보았다.
이외에도 넘파이(numpy)로 행할 수 있는 수많은 매서드가 있지만, 후에 시간이 될 때 다른 포스트로 기술하도록 하겠다.
'IT Anthology > encyclopedia' 카테고리의 다른 글
[밑러닝] 손글씨 숫자 인식으로 해보는 간단한 인공신경망 예측(feat. MNIST 데이터셋) (0) | 2020.03.17 |
---|---|
[밑러닝] 인공신경망 구현을 위해 알아야할 것들 (활성화 함수와 소프트맥스) (0) | 2020.03.11 |
[밑러닝] XOR 문제의 해결, 층 쌓기 (0) | 2020.03.11 |
[밑러닝] 퍼셉트론(perceptron), 인공신경망의 기원 (0) | 2020.03.11 |
[밑러닝] 1.6 matplotlib, 파이썬의 시각화 툴 (0) | 2020.02.28 |