KNN classifiers two_loops , one_loops , no_loops distances
정답코드는 많은데, X_train과 X_test 간의 distance를 구할 때 각각의 행렬의 배열이 어떻게 변하는지 초보인 나로서는 이해가 잘 가지 않았다.
쉬운 배열을 임의로 만들어서 정답코드의 distance를 구하는공식이 X_train과 X_test간의 원소들간의 계산에 어떻게 적용되는지 눈으로 확인해보았다.
two_loops distances
>>실제코드
>>쉽게 이해해보자
1. 먼저 가상의 train, test 샘플을 만든다.
실제 CIFAR10의 train 샘플은 (50000, 32, 32, 3) 차원으로 [50000장의 사진x (32x32 픽셀) x3개의 RGB채널] 로 이루어져있고, 이를 (50000, 32x32x3) 으로 샘플마다 벡터화하여 행마다 서로 다른 사진의 샘플이 되도록 했다. 아래 예시에서는 train은 4개의 사진(행)이 각각 5개의 pixel값(열)을 가진다는 식으로 간단하게 구성해보았다.
one_loop distances
two_loops distances는 train샘플과 test샘플간의 L2 distance를 구할 때 , for 문이 2번 쓰인다.
이를 더 효율적으로 for문을 1번만 써서 KNN classifier를 정의해본다.
>>실제정답코드
>> 쉽게 이해해보자
**np.sum(array, axis= )에서 axis=1 이면 같은행, 모든열의 값을 더한다는걸 반대로 생각해서 헤맴 ;;
헷갈려서 정리하자면,
sub 은 하나의 test벡터인 test[i]와 4개(모든)의 train벡터 ([0]~[3]) 간의 모든차원(픽셀값들)을 빼주는것이므로
two-loop distance에서 for i 문 안에서 for j문을 0~3까지 모두 실행한 경우의 sub을 한번에 한 것이다.
square는 sub의 각 원소를 제곱한 것이고, shape은 (4, 5) 로 4개의 각 행들은 test[i]와 각 train 샘플들간의 연산의 결과이고 열 5는 샘플 안의 픽셀들이 연산된 값을 의미한다.
dists[i, :] 에는 i번째 행에 test[i]와 각 train들 간의 최종 L2 distance값을 열에 배치하여 넣겠다는 것으로
np.sum(square, axis=1) 을 통해 square 행렬에서 각 행에서 모든 열의 값, 즉 sub/square를 거친 픽셀연산값들을
더해서 (4, 5) 배열에서 (4, ) 배열로 변환된다. 아래그림에서 시그마부분까지 해주는것이고, p와 q는 test와 train 샘플(벡터), 아래첨자 i=1~n 은 각 샘플의 픽셀(차원)이라고 보면된다.
no_loops distances
for문을 아예 없애고 벡터화시켜서 distance를 구해보자.
이 때는 일종의 트릭이 작용한다.
X_test의 행을 N개 (test샘플수), X_train을 M개라고 했을때, 최종 dists 행렬의 (N, M) 자리에는 각 N번째, M번째 test, train 샘플간의 distance가 오게 된다. 해당 l2 distance를 구하는 식은 위와 같고, 각 샘플의 d차원 (열) 원소들간에 연산이 일어나게 된다.
loop를 돌지 않기 위해서 L2 distance안의 기본식을 전개하면 원의방정식처럼 X2-2XY-Y2 형태가 나온다.
그래서 각각 (X_test)**2 - 2(X_train * X_test) + (X_train)**2 의 각 항을 구해서
행렬간 broadcasting이 일어날 수 있도록, 차원을 조정해주어 최종 dists 행렬을 만드는 것이다.
test_square_sum : X_test의 각 원소를 제곱해서 axis=1끼리 더해야 하나의 test샘플 (같은행)의 모든d차원의 픽셀 제곱값을 더한게 된다. 이 결과 (2, 1)행렬이 나오고, [1,1]은 test 1번, [2,1]은 test2번의 X2값이기 때문에, 하나의 test당 M개의 train 샘플과 distance를 구해야 하기 때문에 [:, np.newaxis]를 통해서 (2, 1) 차원을 (2, 4)차원으로 확장시킨다.
minus_2XY : test와 train 샘플들간의 원소끼리의 곱을 구하기 위해 train.T 하여 행렬곱
train_square_sum : X_train의 각 원소를 제곱해서 axis=1끼리 더함. (4, ) 행렬이 나오므로, dists = (2, 4)에서 broadcasting으로 더할 수 있으니 차원변환은 안 해도 된다.
'코딩 독학 > CS231n' 카테고리의 다른 글
[cs231n] 5강. Convolutional neural networks (0) | 2020.11.08 |
---|---|
[cs231n] 4강. Backpropagation and Neural network (0) | 2020.10.31 |
[cs231n] 3강. Loss function, optimization (0) | 2020.10.23 |
[CS231n] 2강. L1 & L2 distance (0) | 2020.10.18 |
[CS231n] 2강. Image classification (0) | 2020.10.16 |
댓글