티스토리 뷰
1. Introduction to Deep Learning / L5. Matrix Math and NumPy Refresher - Data in NumPy
chrisysl 2018. 6. 22. 13:15Introducing NumPy
- 파이썬은 편리하지만 느리다는 단점이 있다.
- 그러나, 파이썬은 C로 쓰인 코드보다 빠르게 실행될 수 있는 라이브러리를 사용할 수 있다.
- NumPy가 그런 라이브러리 중 하나이다
- NumPy는 파이썬에서 매우 빠르게 수학적 연산이 가능하게 하고, 행렬과 같은 집합적 연산에 효율적이다.
- 여기서 언급할 부분들은 극히 일부에 불과하므로,
- 파이썬 NumPy라이브러리를 통한 수학적 연산에 대해 더 알아보려면 여기를 참고하도록.
Importing NumPy
- NumPy 라이브러리를 import할 땐, 일종의 규칙으로 np로 지정하여 임포트 한다.
#> import numpy as np 와 같이 np로 임포트 할 것을 규칙으로 한다.
- 이제 np를 이용하여 np. 과 같은 방식으로 NumPy 라이브러리를 사용할 수 있게된다.
Data Types and Shapes
- 넘파이를 이용하여 수를 다룰때 가장 일반적인 방법은 ndarray 객체를 이용하는것이다.
- 파이썬 list의 개념과 비슷하지만, ndarray는 다차원의 개념을 적용시킬 수 있다.
- 또한, ndarray 객체는 빠른 수학적 연산을 지원한다.
- 그러므로 전에 언급하였던 스칼라값, 벡터, 행렬, 텐서 등을 모두 ndarray 객체로 표현 가능하다.
Scalars
- NumPy에서의 스칼라는 파이썬에서의 스칼라보다 좀 더 복잡하다.
- int, float 등 과 같은 Python의 기본 타입 대신에, NumPy를 사용하면
- 기본 타입을 이용한 크기 지정 뿐 아니라 signed 또는 unsigned 를 따로 명시하여 지정할 수 있다.
- 파이썬의 int대신 넘파이를 이용하여 타입을 지정할땐 uint8, int8, uint16, int16과 같이 명시해준다.
- 앞으로 만들 모든 객체(벡터, 행렬, 텐서)들은 결국 스칼라 값을 저장하기 때문에,
- 이러한 타입 지정은 매우 중요하다.
- 그러나 넘파이 배열을 생성하고 타입을 명시할때 이 넘파이 배열의 모든 항목들은 같은 타입이어야만 한다.
- 이런 관점에서 볼때 NumPy배열은 파이썬의 배열보단 C의 배열과 유사하다 볼 수 있겠다.
- NumPy 배열을 생성하여 스칼라값을 넘겨주려면
- 이렇게 해주면 됨
- shape 를 이용하여 배열의 모양을 확인 할 수 있다.
- 따라서 이 코드를 실행하면 빈 괄호() 의 형태로 출력하게 된다. 이것은 0차원임을 의미한다.
- 비록 스칼라값이 행렬안에 들어있다 하더라도, 여전히 일반 스칼라값처럼 사용할 수 있다. 예를들어
- 이렇게 입력하면 x는 8이 된다.
- 이때, x의 타입을 확인해보면 numpy.int64 라고 나오게 된다(넘파이를 사용중이므로).
Vectors
- 벡터를 생성하려면 파이썬 list를 array함수에 넘겨줘야한다.
- 벡터의 shape를 확인해보면, 벡터의 일차원 길이를 리턴해준다.
- 위의 예시에서 v.shape는 (3,)을 리턴한다.
- 또한, shape는 ndarray의 차원의 크기를 튜플로 갖는것을 알 수 있다.
- 스칼라는 0차원이므로 빈 튜플이고, 벡터는 1차원이므로 shape에서 (1,)과 같이 표현될 것이다.
- 파이썬은 예를들어 (3) 과같이 하나의 요소만 가지고 있는것은 튜플로 인지하지 않는다.
- 그러므로 콤마가 필요한 것임
- 또한 벡터를 인덱스를 이용하여 해당 요소에 접근 할 수 있다.
- x 는 2가 될 것임.
- 위와같은 인덱스 형태로도 접근이 가능하다. 이 결과 [2, 3]을 리턴함.
- 넘파이의 슬라이싱은 꽤 강력한 편인데, ndarray의 요소간 어떠한 조합이건 접근 가능하도록 해준다.
- 근데 이러한 연산은 점점 더 복잡해지기 마련이므로 자세한 이해 이후에 진행하도록 하자. 여기
Matrices
- 넘파이의 array 함수를 이용해서 행렬을 생성 할 수 있다
- 대신 리스트를 그냥 넘겨주는게 아니라 각각 하나의 행으로 넘어간다.
- 예를들어 이는 3 by 3 행렬이 된다.
- m.shape로 확인해보면 (3, 3)이라는 튜플을 리턴한다.
- 2차원이기 때문에 각각의 행과 열의 길이를 리턴하는 것임
- m[1][2]와 같이 인덱스를 통해 요소에 접근할 수 있다. 6이 리턴됨
Tensors
- 텐서는 벡터와 행렬처럼 이해할 수 있지만 다차원이다.
- 예를들어 3x3x2x1 텐서를 생성한다면
- 이렇게 넘겨주면 된다.
- t.shape 의 결과는 (3, 3, 2, 1)을 리턴함
- 마찬가지로 인덱스를 통해 요소에 접근이 가능하다. t[2][1][1][0]은 16을 리턴한다.
Changing Shapes
- 떄떄로 안의 요소의 값을 변경하지 않고 shape를 변경시켜야 할 때가 있다.
- 예로, 하나의 벡터가 있는데 이를 행렬로 표현해야만 한다면, 두가지 방법이 있다.
- 이런 벡터가 있다고 가정하면, v.shape 는 (4,) 를 리턴할 것이다.
- 근데 1x4 행렬이 필요하다면? reshape를 통해 해결 할 수 있다.
- 위와같이 입력해준 뒤 x.shape를 해보면 (1, 4)를 리턴한다.
- reshape는 단순하게 차원을 하나 올리는것 이상의 역할을 한다. 그 예시로는 여기 참고
- NumPy 배열에서의 reshape에 대해서 한가지 더 짚고넘어가야할 부분은,
- 만약 NumPy 고수로부터 코드를 넘겨받게되면, reshape를 사용하는 것 대신에
- 독특한 슬라이싱 문법을 사용하는것을 확인 할 수 있을것이다.
- 그러한 문법을 사용해서 위의 예제 x = v.reshape(1,4)를 다시 작성한다면
- 이렇게 나타낼 수 있다.
- 이 코드를 보면 인덱스 슬라이싱에서 모든 v의 요소들을 확인하지만,
- 해당 축을 기준으로 넘파이에게 차원 하나를 더할 것인지를 물어본다.
- 막상 지금보면 이해가 안될수있지만, 익숙해져야한다.