Chapter4 Vectorization: Notebook5 2-dim Vectorization Example2
우리가 실제 프로그램을 만들 때 Vectorization의 이득을 가장 많이 보는 부분은 행렬의 곱셈이 아닐까 싶다. 전의 Notebook에서 하나의 matrix에 대한 연산을 진행했다면 이번 시간에는 두 행렬의 곱셈에 대하여 Vectorization이 얼마나 효과적일지 살펴보기 전에 먼저 Matrix와 Vector의 Multiplication을 살펴보고 다음 notebook에서 두 행렬의 곱셈을 다뤄보도록 하자.
먼저 Matrix와 Vector의 Multiplication은 다음과 같이 연산된다.
행렬 A가 (m,n)이고 B가 (n,1)일 때 A*B를 C라 하면 C의 i-th entry는 다음과 같이 구한다.
$c_{i} = a_{i1}b_{1} + a_{i2}b_{2} + ... + a_{in}b_{n} = \sum_{k=1}^{n} a_{ik}b_{k}$
먼저 다음과 같이 matrix와 vector를 만들어보자.
import numpy as np
import time
m, n = 2000, 1000
A = np.random.rand(m,n)
B = np.random.rand(n,1)
C = np.zeros(shape = (m,1))
print(A.shape, B.shape, C.shape)
위와 같이 (2000,1000)의 행렬 A와 1000차원의 vector B을 만들었다. 물론 이 matrix와 vector가 크다고 느껴질 수 있지만, 실제 data를 다루게 된다면 절대 큰 data가 아닌 것을 알게 될 것이다. 2천명이 각각 1000개의 data를 가지고 있는 것은 오히려 적은 경우이다. 이 matrix와 vector에 대해서 multiplication을 이용하면 얼마나 빨라질지 살펴보도록 하자.
tic = time.time()
for row_idx in range(m):
for col_idx in range(n):
C[row_idx] += A[row_idx, col_idx]*B[col_idx]
toc = time.time()
for_time = toc - tic
print("Elapsed Time:", for_time, 'sec')
tic = time.time()
C = np.dot(A,B)
toc = time.time()
vec_time = toc - tic
print("Elapsed Time:", vec_time, 'sec')
print("Elapsed Time Ratio:", for_time/vec_time)
솔직히 위의 결과를 보고 저자도 놀랬다. 평소에 vectorization을 쓰다가 이 강의자료를 만들기 위해 for loop을 써봤는데, 고작 천 단위의 data에서도 500배 차이가 나는 것을 보고 더욱 vectorization을 잘 사용해야겠다는 생각이 들었다. 그러면 연산이 오래걸리겠지만 data를 조금 늘렸을 때도 살펴보고 가도록 하자.
다음은 2천명이 아니라 조금 더 키워서 10만명이 천개의 data를 가지고 있을 때이다. 솔직히 10만명이라고해도, 실제 data에 비하면 많이 작은편이지만 Matrix가 조금 더 커졌을 때 얼마나 영향을 미치는지 살펴보자.
m, n = 100000, 1000
A = np.random.rand(m,n)
B = np.random.rand(n,1)
C = np.zeros(shape = (m,1))
print(A.shape, B.shape, C.shape)
tic = time.time()
for row_idx in range(m):
for col_idx in range(n):
C[row_idx] += A[row_idx, col_idx]*B[col_idx]
toc = time.time()
for_time = toc - tic
print("Elapsed Time:", for_time, 'sec')
tic = time.time()
C = np.dot(A,B)
toc = time.time()
vec_time = toc - tic
print("Elapsed Time:", vec_time, 'sec')
print("Elapsed Time Ratio:", for_time/vec_time)
위의 결과에서 볼 수 있듯이, 약 10000배의 차이가 난다. 이 결과를 보고 많은 독자들이 vectorization을 배우지 않고 data science와 같이 큰 data에 접근하는 것이 얼마나 위험한 생각인지 깨달았으면 좋겠다. 2중 for loop을 썼을 땐 2분 19초가 걸렸지만 vectorization을 썼을 땐 0.027초로 27ms가 걸린다. 독자들도 꼭 차원이 높아지면 for loop을 최대한 피하면 좋겠다.