Vectorization
Vectorization으로 for loop를 없애기!
- Logistic Regression 에서는 $z = w^{T}x + b$ 를 계산해야 함
$$ w = \begin{bmatrix} : \\ : \\ : \end{bmatrix} ,\ x =\begin{bmatrix} : \\ : \\ :\end{bmatrix} $$
- $w \in R^{n_{x}}$, $x \in R^{n_{x}}$
- non-vectorized implementation
z = 0
for i in range(n_x):
z += w[i] * x[i]
z += b
- vectorized implementation --> 훨씬 빠름
z = np.dot(w, x) + b
- GPU, CPU 모두 SIMD라는 병렬처리가 가능 (GPU가 훨씬 좋을 뿐)
More Vectorization Examples
[Neural Network programming guideline]
Whenever possible, avoid explicit for-loops
예를 들어 벡터 $u = Av$ 내적을 for-loop으로 구하고자 하면 $i$, $j$ 에서 두 개의 for-loop을 겹쳐야 함
u = np.dot(A, v)
로 vectorization 하는 것이 효율적이다
say you need to apply the exponential operation (지수 연산) on every element of a matrix/vector
$$w = \begin{bmatrix} v_{1} \\ \vdots \\ v_{n} \end{bmatrix}\ u = \begin{bmatrix} e^{v_{1}} \\ e^{v_{2}} \\ \vdots \\ e^{v_{n}} \end{bmatrix}$$
- non-vectorized implementation
u = np.zeros((n, 1)) # initialize
for i in range(n):
u[i]= math.exp(v[i])
- vectorized implementation
import numpy as np
u = np.exp(v)
그 외에 np.log(v)
, np.abs(v)
, np.maximum(v, 0)
... 다양하게 있음
[Logistic Regression Derivatives]
vector dw
를 생성하여 feature 개수만큼 도는 for-loop를 제거
Vectorizing Logistic Regression
logistic regression을 vectorize 하기
- logistic regression 의 forward propagation을 먼저 살펴본다
$$ z^{(1)} = w^{T}x^{(1)} + b$$
$$ a^{(1)} = \sigma (z^{(1)}) $$
$$ z^{(2)} = w^{T}x^{(2)} + b$$
$$ a^{(2)} = \sigma (z^{(2)}) $$
$$ z^{(3)} = w^{T}x^{(3)} + b$$
$$ a^{(3)} = \sigma (z^{(3)}) $$
...
$m$번 반복
$$X = \begin {bmatrix}| & | & & | \\ x^{(1)} & x^{(2)} & ... & x^{(m)}\\ | & | & & |\end{bmatrix} $$
$X$는 $(n_{x}, m)$의 vector
- 우선 $1 \times M$의 row vector 를 구성한다
$$\begin{bmatrix} z^{(1)} & z^{(2)} & \ldots & z^{(m)} \end{bmatrix} = w^{T}X + \begin{bmatrix}b & b & \ldots &b \end{bmatrix} $$
- $ \begin{bmatrix}b & b & \ldots &b \end{bmatrix}$은 $1 \times m$ 의 row vector
$$ w^{T} \begin{bmatrix}| & | & & | \\ x^{(1)} & x^{(2)} & ... & x^{(m)}\\ | & | & & |\end{bmatrix} $$
- $w^{T}$는 row vector
$$\begin{bmatrix} w^{T}x^{(1)}+b & w^{T}x^{(2)}+b & \ldots & w^{T}x^{(n)}+b \end{bmatrix}$$
- $1 \times m$의 row vector 가 생성됨
- 즉, $\begin{bmatrix} z^{(1)} & z^{(2)} & \ldots & z^{(m)} \end{bmatrix}$
- 즉 학습셋을 수평으로 쌓는다면, $X$를 구할 수 있고
- $Z$도 수평으로 쌓을 수 있음
- $ w^{T}X + \begin{bmatrix}b & b & \ldots &b \end{bmatrix} $ 는 z=np.dot(w.T, x) + b
로 나타낼 수 있음
- 만약 b
가 real number(실수)라면, 자동으로 $1 \times m$의 row vector 로 확장해서 계산됨
-----> "broadcasting"
- $z$들로 이루어진 $Z$를 구한다고 하면, $a$는?
- $\begin{bmatrix} a^{(1)} & a^{(2)} & \ldots & a^{(m)} \end{bmatrix}$, 즉 $A$ 를 한번에 구하기
- $Z$를 입력으로 받아 효율적으로 $A$를 출력하는 sigmoid function 을 프로그래밍할 것임
Vectorizing Logistic Regression's Gradient Output
[Vectorizing Logistic Regression]
$dz^{(1)} = a^{(1)} - y^{(1)}$, $dz^{(2)} = a^{(2)} - y^{(2)}$ ...
- 새로운 variable 을 지정 : 가로로 쌓은 모습 ($m$차원의 row vector)
$dZ = \begin{bmatrix} dz^{(1)} & dz^{(2)} & \ldots & dz^{(m)} \end{bmatrix}$
- $ A = \begin{bmatrix} a^{(1)} & \ldots & a^{(m)} \end{bmatrix} $,\ $ Y = \begin{bmatrix} y^{(1)} & \ldots \end{bmatrix} y^{(m)}$ 이므로
$$dZ = A - Y = \begin{bmatrix} a^{(1)} - y^{(1)} & a^{(2)} - y^{(2)} & \ldots \end{bmatrix} $$
- 앞서 $dw^{(1)}$, $dw^{(2)}$ 를 없애는 대신에 $dw = 0$ 를 세팅해 for-loop을 제거했다
- 그러나 여전히 이를 이용한 for-loop 가 존재하는데, training set $m$에서 loop 하는 부분임
$$dw = 0$$
$$dw += x^{(1)}dz^{(1)}$$
$$dw += x^{(2)}dz^{(2)}$$
$$ \vdots $$
$$dw /= m$$
$$db = 0$$
$$db += dz^{(1)}$$
$$db += dz^{(2)}$$
$$ \vdots $$
$$db += dz^{(m)}$$
$$db /= m$$
이를 vectorize 해보자
- $db$의 경우, $dz^{(i)}$들을 단순히 모두 더한 다음 $m$으로 나눈다
$$db = \frac{1}{m} \sum_{i=1}^m dz^{(i)}$$
- 파이썬에서는 $\frac{1}{m} np.sum(dz)$
- $dw$의 경우,
$$dw = \frac{1}{m} X dz^{T} = \frac{1}{m} \begin{bmatrix}| & | & & | \\ x^{(1)} & x^{(2)} & ... & x^{(m)}\\ | & | & & |\end{bmatrix} \begin{bmatrix} dz^{(1)} \\ \vdots \\ dz^{(m)} \end{bmatrix} $$
$$ = \frac{1}{m} \begin{bmatrix} x^{(1)}dz^{(1)} + \cdots + x^{(m)}dz^{(m)} \end{bmatrix}$$
[정리]
- 위 과정을 iteration 수 만큼 for-loop 해야 함 (이거는 없애기 어려움!)
Broadcasting in Python
[Broadcasting example]
- 음식별로(칼럼별로) 어떤 영양소가 얼마나 많은 칼로리를 차지하고 있는지 계산하고자 함
- 예를 들어, 사과에서 탄수화물이 차지하는 양 $ = \frac{56.0}{56.0+1.2+1.8} \times 100$
- 이 과정을 for-loop 없이 수행할 수 있는가?
- 위 표를 $3\times4$의 matrix $A$로 본다
import numpy as np
A = np.array(
[56.0, 0.0, 4.4, 68.0],
[1.2, 104.0, 52.0, 8.0],
[1.8, 135.0, 99.0, 0.9]
)
cal = A.sum(axis=0) # sum vertically
percentage = 100 * A/cal.reshape(1, 4)
- 사실 cal
이 이미 $1 \times 4$ 행렬이므로 reshape
는 안 해줘도 됨
- $3 \times 4$ 행렬을 $1 \times 4$ 행렬로 나눴다. 이게 어떻게 가능한 걸까?
파이썬에서 자동으로 broadcasting을 해주기 때문
$m \times n$ 행렬과 $1 \times n$ 행렬을 더하고자 한다면
파이썬은 $1 \times n$ 행렬을 $m$번 곱해서 $m \times n$ 행렬로 만든다
A Note on Python/Numpy Vectors
broadcasting 은 편리하지만 때로는 이상한 버그를 던지기도 함
import numpy as np
a = np.random.randn(5)
print(a)
print(a.shape)
>> [숫자, 숫자, 숫자, 숫자, 숫자]
>> (5, )
이는 파이썬에서 rank 1 array 라고 불리며, 행 벡터도 열 벡터도 아니다
rank 1 array 를 사용하지 마시오
a = np.random.randn(5, 1)
print(a)
>>[[숫자],
[숫자],
[숫자],
[숫자],
[숫자]]
이렇게 했을 때 열벡터가 생성된다 (대괄호가 두 번 겹쳐져 있는 것에 주목!)
팁1. assert(a.shape == (5, 1))
와 같은 assertion을 활용하기
팁2. rank 1 array를 만들어버렸을 때 a = a.reshape((5, 1))
로 reshape 해버리기
- reshape를 사용하는 데 주저하지 마세요
Explanation of Logistic Regression Cost Function (Optional)
[Logistic regression cost function]
[Cost on m examples]
QUIZ
퀴즈 통과 못해서 한번 더 치렀다.. 나는 왜이렇게 행렬이 헷갈릴까
역시 선형대수학을 안 해서겠지
'인공지능 > DLS' 카테고리의 다른 글
[1.3.] Shallow Neural Networks(2) (0) | 2022.06.27 |
---|---|
[1.3.] Shallow Neural Networks(1) (0) | 2022.06.26 |
[1.2.] Neural Networks Basics - Logistic Regression as a neural network(3) (0) | 2022.06.26 |
[1.2.] Neural Networks Basics - Logistic Regression as a neural network(2) (0) | 2022.06.25 |
[1.2.] Neural Networks Basics - Logistic Regression as a neural network(1) (0) | 2022.06.24 |