티스토리 뷰
Introduction
CS231n 과제 1번의 두번째가 Linear SVM을 구현하는 것입니다.
편의상 Delta=1로 두고 구현을 하고 있고, 이거 감안해서 봐주시면 감사하겠습니다.
Forward Pass와 Backpropagation을 구현하는 것이 핵심 토픽인데, 반복문 버전이랑 벡터화 버전이 있습니다.
반복문 버전은 뭐... 쉽게 할 수 있으니 넘어가고, 벡터화버전에 대해서 알아보도록 하겠습니다.
Forward Pass (Using iteration)
먼저, 반복문 버전의 코드부터 봅시다.
일단 loss는 Margin들의 합임을 알 수가 있고, margin을 계산하기 위해서는 정답의 값이 필요함을 알 수 있습니다.
코드를 보면, class 개수만큼 반복문을 돌면서 margin을 계산하는 것을 알 수가 있죠.
반대로 말하면,
이걸 나중에 행렬곱으로 표현할 필요가 있습니다.
이렇게 loss들의 합을 구하고 나면, 마지막으로는 regularzation에 대한 것도 구해야합니다.
이건 앞의 Batch normalization backpropagation을 설명하며 사용한 방법을 재활용할 예정입니다.
결국 Loss도 Scalar로 반환되기 때문에, Trace-trick을 사용해도 문제가 없습니다.
Forward Pass (Using vectorization)
이제, 벡터화하여 최대한 행렬곱으로 표현할 시간입니다!
먼저, margin이 0보다 클 때만 loss를 더하는 이 부분부터 처리해보도록 하죠.
Activation function을 배우신 분들은 이 과정이 ReLU 함수를 통과하는 과정이랑 굉장히 유사함을 알 수 있습니다.
이러면 추후 Backpropagation할 때 ReLU를 미분해 줄 필요도 있는데,
다음 과정은 본격적으로 행렬 계산을 하는 부분입니다.
사실, score를 계산하는 과정은 굉장히 쉽습니다. 이건 그냥 Train set
하지만, 여기에서 정답 벡터만 추출하는 과정이 쉽지 않습니다. 앞의 Iteration 과정에서 말했듯이,
한 가지 묘수를 생각해봅시다.
우리는 현재 정답이 어디있는지를 알고 있습니다. 그러면, 정답을 표시하는 것 외에도 정답 인덱스에만 값을 할당하는 것이 가능합니다.
예를 들어, 정답을 표시한
그러면, 우리는 순수하게
이렇게 되면, 총
이제, 우리가 들고 있는 score 행렬에 이
하지만, 우리가 최종적으로 원하는 꼴은 이게 아니죠. 결국은 우리는 행렬의 각 행이 전부 정답으로만 도배가 되어 있어야 합니다.
예를 좀 들면, 현재 상황은
이걸 만들기 위해서,
이때,
즉, 우리는
이후,
이걸 코드로 구현한 것은 다음과 같습니다.
Implement of Forward Pass (Using vectorization)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
def ForwardPass(W, X, y, reg):
"""
Structured SVM loss function, naive implementation (with loops).
Inputs have dimension D, there are C classes, and we operate on minibatches
of N examples.
Inputs:
- W: A numpy array of shape (D, C) containing weights.
- X: A numpy array of shape (N, D) containing a minibatch of data.
- y: A numpy array of shape (N,) containing training labels; y[i] = c means
that X[i] has label c, where 0 <= c < C.
- reg: (float) regularization strength
Returns a tuple of:
- loss as single float
- gradient with respect to weights W; an array of same shape as W
"""
loss = 0.0
#############################################################################
# TODO: #
# Implement a vectorized version of the structured SVM loss, storing the #
# result in loss. #
#############################################################################
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
N = X.shape[0]
C = W.shape[1]
ones = np.ones((C, C))
tp = np.arange(N)
score = X@W
ans = np.zeros_like(score)
ans[tp, y] = 1
score = score - (score * ans)@ones + 1
score[tp, y] = 0
score[score <= 0] = 0
loss += np.sum(score) / N
loss += reg * np.sum(W * W)
return loss
|
cs |
Backpropagation (Using vectorization)
자, Forward Pass를 깔끔하게 마무리했으므로 Backpropagation도 생각보다 쉽게 할 수 있습니다!
현재, Loss가 계산되는 과정을 좀 적어보자면
입니다.
앞에서도 말했다시피
다음은
정말 다행히도 이 행렬은 score 행렬이 됩니다. 즉, 우리는 score 행렬을 보면서
이 행렬을
그러면, 현재 상황을 Trace trick을 통해 나타내면
OK, 여기까지 왔으면 거의 끝났습니다.
score에 대한 Total derivate를 계산할 때 상수는 의미없으므로 날리고, 빼기로 연결되어 있으므로 각각 따로 계산합시다.
먼저,
이제 뒷쪽을 처리하도록 하죠.
그러면,
입니다.
마지막으로, Regularization에 대한 Term만 고려해줍시다. 동일하게
즉, Regularization에 대한 gradient는
앞의 내용을 코드로 나타내면 다음과 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
def Backprop(W, X, y, reg):
"""
Structured SVM loss function, naive implementation (with loops).
Inputs have dimension D, there are C classes, and we operate on minibatches
of N examples.
Inputs:
- W: A numpy array of shape (D, C) containing weights.
- X: A numpy array of shape (N, D) containing a minibatch of data.
- y: A numpy array of shape (N,) containing training labels; y[i] = c means
that X[i] has label c, where 0 <= c < C.
- reg: (float) regularization strength
Returns a tuple of:
- loss as single float
- gradient with respect to weights W; an array of same shape as W
"""
dW = np.zeros(W.shape) # initialize the gradient as zero
#############################################################################
# TODO: #
# Implement a vectorized version of the gradient for the structured SVM #
# loss, storing the result in dW. #
# #
# Hint: Instead of computing the gradient from scratch, it may be easier #
# to reuse some of the intermediate values that you used to compute the #
# loss. #
#############################################################################
# *****START OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
score_grad = np.copy(score)
score_grad[score_grad > 0] = 1
grad_max = score_grad / N
dW = X.T @ grad_max - X.T @ ((grad_max@ones)*ans)
dW += 2 * reg * W
# *****END OF YOUR CODE (DO NOT DELETE/MODIFY THIS LINE)*****
return dW
|
cs |
Outroduction
사실 선형대수 배워봤자 쓰잘데기 없다고 생각했는데, Trace trick 하나 알아두니까 Backprop 계산이 진짜 편하네요
행렬곱 같은것도 표현 좋고
기회될 때 선형대수 관련해서 업로드 좀 하겠습니다.
이번학기에 선형대수 들었는데, 사실 귀찮아서 안올리고 있었는데 배운 내용 함 정리할게요
'개인 공부' 카테고리의 다른 글
Batch normalization Forward Pass & Backpropagation (0) | 2023.01.02 |
---|---|
Graph transformer networks based text representation (0) | 2022.09.03 |
Softmax & Loss (0) | 2022.08.13 |
B. (Variational) Auto Encoder (0) | 2022.07.16 |
A. Attention (0) | 2022.07.16 |
- Total
- Today
- Yesterday
- cs231n assignment1
- Trace tirck
- Derivate
- 수학
- 세그먼트 트리
- 로피탈
- 해석학 Chapter 5
- 해석학II
- 해석학
- Trace trick
- LInear SVM
- 수(상)
- 백준 17411
- PMA Ch5
- Differentation
- joi
- icpc.me/17411
- mathematics
- 연습문제
- 미분
- Backprop
- 백준
- PMA
- 선형대수학
- PMA 연습문제
- JOI 2021
- Deep learning
- 해석학 Ch5
- Machine Learning
- 17411
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |