CS231n - Lecture 4 | Introduction to Neural Networks

kimgaeul02·2023년 5월 11일

CS231n

목록 보기
4/5

본 포스팅은 Standford University의 'CS231n' 강의로 공부한 것을 정리했습니다.

Lecture 4 | Introduction to Neural Networks

학습목표

  • 프레임워크 computational graph를 이용하여 임의의 복잡한 함수를 통해 analytic gradient를 계산하는 방법을 배운다.

계산 그래프 계산 그래프(computational graph)란 계산 과정을 그래프로 나타낸 것입니다. 그래프는 노드(node)와 에지(edge)로 표현됩니다. 출처

computational graph를 이용하면 모든 변수에 대해 재귀적으로 gradient를 계산하는 역전파(backpropagation)를 사용할 수 있게 된다.

  • 이때 노드는 연산, 화살표는 데이터의 흐름을 의미한다.
  • 위 예제는 input이 x, W인 선형 classifier이다. x, W를 첫 번째 노드에 집어넣으면 xW를 연산하고, 여기에서 나온 값이 s(scores)이다. 그리고 여기에서 hinge loss를 대입한 뒤, R(W)를 더하여 최종값 L를 구하게 된다.
  • Lᵢ는 regularization 항을 가진다. 노드 R은 regularization 항을 계산하며, 최종 Loss(L)은 regularization 항과 데이터 항의 합을 의미한다.

Backpropagation

Backpropagation은 gradient를 얻기위해 computational graph 내부의 모든 변수에 대해 chain rule을 재귀적으로 사용한다. #국소적 계산 #연쇄법칙(chain rule)

역전파에 대한 자세한 설명은 다음 포스팅에서 확인할 수 있다. > CH5. 오차역전법

📌 The first example

  1. 역전파는 인풋이 아닌 아웃풋부터 살펴본다. f부터 살펴보면 df/df=1
  2. z에 대한 f의 미분 df/dz=q 이므로 3이 된다.
  3. q에 대한 f의 미분 df/dq=z 이므로 -4가 된다.
  4. x+y=q의 미분은 다음과 같이 계산할 수 있다. dq/dy=1, dq/dx=1. 따라서 df/dy=(dq/dy)x(df/dq)=1x(-4)=-4이다.
  5. df/dx=(dq/dx)x(df/dq)=1x(-4)=-4

Chain rule이란?

각 노드는 오직 주변에 대해서만 알 수 있으며 처음에 제공받는 정보는 각 노드와 각 노드의 local 입력 뿐이다. fy\frac{\partial f}{\partial y}fx\frac{\partial f}{\partial x}의 경우 바로 구하는 것이 어려우므로 chain rule을 적용한다.

  • chain rule을 이용해 합성함수의 미분 계산 가능.
  • 위와 같이 (global gradient)*(local gardient)로 표현.
  • 해당 예제에서 global gradient는 Lz\frac{\partial L}{\partial z}가 되고, local gradient는 zx\frac{\partial z}{\partial x}가 됨.

📌 The second example

  • input을 순서대로 계산하여 모든 항의 output을 구한 뒤 local gradient(upstream gradient)를 구한다.
  • 예를 들어 f(x)=1/x의 경우 global gradient=-0.53, local gradient=f'(x)=1. 즉, (-0.53)x1=-0.53이다.
  • 예를 들어 f(x)=x+1의 경우 global gradient는 앞서 계산한 -0.53가 되고, local gradient=f'(x)=1. 즉, (-0.53)x1=-0.53이다.
  • 이와 같은 방식으로 계산하면 덧셈 노드와 곱셈 노드의 차이를 알 수 있는데 이는 뒤에서 후술한다.

Sigmoid Function

  • 파란색 네모 박스에 해당하는 부분을 커다란 node로 가정하고 sigmoid function으로 잡는다. 그러면 sigmoid function의 국소 미분만 계산하면 되기에 연산량을 줄일 수 있다.
  • x=1일 때, sigmoid(x)=0.73. sigmoid'(x)=(1-sigmoid(x))x(sigmoid(x)) 이므로 (1-0.73)(0.73)=0.2, local gradient를 간단하게 구할 수 있다.

Q. 왜 이러한 방식이 특정 변수에 대해서 analytic gradient를 유도해 값을 계산하는 것보다 단순한가요?
A. 식을 절대적으로 작은 단위로 쪼개었을 때, 덧셈과 곱셈은 더 단순해질 수 없다. 그러나 sigmoid 함수의 경우 일반화 된 공식이 있으므로 더 간단하게 계산할 수 있다. sigmoid 외에도 노드나 게이트마다 쉽게 편미분 gradient를 구할 수 있는 방법이 존재한다.

Add/Max/Mul Gate

  • 각 노드에 들어온 변수를 덧셈/최댓값변환/곱셈해주는 gate의 경우 쉽게 편미분값 반환이 가능하다.

  • add gate: 기본적으로 (upstream gradient)x(local gradient)를 통해 gradient를 계산할 수 있는데 계수가 1인 일차함수 형식의 덧셈공식은 미분하면 (local G가) 1이 되므로 이전 gradient (upstream G)를 그대로 전파. 두 개의 브런치와 연결된 덧셈 게이트는 upstream gradient를 연결 된 브런치에 같은 값으로 나눠줌. gradient를 그대로 보낸다고 해서 gradient distributer라고 함.

  • max gate: 둘 중 하나에는 전체 gradient 값이, 다른 하나에는 0의 gradient가 향하게 된다. 경로를 지정하여 값을 넘겨주므로 gradient router라고 부른다.

  • mul gate: xy를 x에 대해 편미분 하면 x는 사라지고 y가 상수처럼 남으므로 해당 값을 곱해주면 된다. 편미분하고자 하는 변수를 제외한 상대 변수를 곱해준다고 하여 gradient switcher라고 부른다.


중간 정리

local gradient

  • forward pass 과정에서 구하고 메모리에 저장.

global gradient (upstream gradient)

  • backward pass 동안에만 구할 수 있음.
  • backward pass 과정에서 chain rule 발생.

gradient = global gradient x local gradient


벡터의 미분

  • 지금까지 스칼라 값의 미분을 배웠다. 변수 x, y, z에 대해 숫자 대신 vector를 가지고 있다면 gradient가 Jacobian 행렬이 된다.

input으로 4096차원의 벡터를 받고, output으로 4096의 벡터가 나오게 한다면, 자코비안 행렬은 409640964096*4096이 될 것이다. 이때 minibatch가 100이라면 409600409600409600*409600이 될 것이다.

자코비안 행렬은 대각 행렬이다. gradient의 차원은 원래 벡터의 차원과 같으므로 q=Wxq=W*x의 경우 다음과 같은 꼴을 취하게 된다.

  • qk를 wiw_i, wjw_j로 미분하면 k=ik=i일 때 ixj_ix_j의 값은 xjx_j가 되고, 아닐 경우 0이 된다. (1(k=i)1_(k=i)는 indictor variable: k와 i가 동일할 때는 1이고 그렇지 않으면 0)

  • q1q_1에 해당하는 값은 W_11x_1+W_12x_2로 구하게 된다. 즉, k와 i가 같을 때만 W의 성분이 q에게 영향을 줄 수 있게 된다.

  • 실제 값을 계산하면 다음과 같이 계산될 수 있다.

  • 앞 부분은 2_q1이 되므로 0.44, 뒷부분은 x_1이 되므로 0.2, 이를 계산하면 0.088
  • 위와 같은 계산을 통해 행렬 W의 요소를 모두 구할 수 있다.
  • fW\frac{\partial f}{\partial W}를 vectorized term으로 쓰자면 2qxT2q*x^T로 표현할 수 있다.

  • x의 local gradient인 d_pk/dx_i는 W_k,i로 표현되는데 이 또한 q=Wxq=W*x를 생각해보면 알 수 있다.

  • W_11x_1+W_12x_2=q1이고, W_21x_1+W_21x_2=q2 이므로

  • dq_1/dx_1=W_11가 된다.

  • df/d_x를 실제로 구해보자면

가 될 것이며 df/d_1x는 0.440.1+0.52(-0.3)=-0.112가 된다.
이를 vectorized term으로 쓰자면

가 된다.

  • 요약: 이미지는 모든 pixel을 1차원 array로 재배열하므로 차원이 굉장히 높음. class도 여러 개인 이미지 데이터의 가중치는 엄청나게 큰 행렬일 수 밖에 없음. 이럴 때는 Jacobian matrix(행렬 미분연산)를 사용해야 함. 이 행렬은 크지만 diagonal의 특성 상 대각행렬만 계산하면 되므로 간단함!

📌 The third example

  1. L2 distance의 경우 q를 제곱한 것과 동일하므로 이를 미분하면 2q_i가 된다,
  • 행렬 사이즈 맞추기에 주의할 것

Neural Network

지금까지는 layer가 1개인 Linear regression을 사용하였으나 linear function과 비선형 함수를 겹겹이 합치면 더 복잡한 문제를 해결 가능하다. 두 개의 네트워크를 쌓아 2-layer Neural Network를 만들 수 있다.

  • 2-layer Neural Network 예제
  • CIFAR-10의 경우 x는 크기가 3072x1인 column vector이고, W는 크기가 10x3072인 행렬. 따라서 output score의 크기가 10x1인 벡터임. 여기에 2-layer Neural Network를 적용하면?

  • 뉴런과 CNN은 비슷한 형태를 띄고 있으나 뉴런이 훨씬 복잡한 구조이다.
class Neuron:
	#  ...
    def neuron_tick(inputs):
    	"""  assume inputs and weights are 1-D numpy arrays and bias is a number """
        cell_body_sum = np.sum(inputs*self.weights) + self.bias
        firing_rate = 1.0 / (1.0 + math.exp(-cell_body_sum)) #sigmoid activation function
        return firing_rate

활성화 함수

  • 네트워크 안의 각 노드에 forward pass를 수행하는 것은 이전에 보여주었던 뉴런의 행동과 같음.
  • 그리고 실제 동작에서 생각해볼 수 있는 것은 기본적으로 각 히든 레이어는 완전한 벡터라는 것. 이러한 행렬 곱셈을 통해 뉴런 값을 계산하는 방식으로 쓰면 뉴런의 전체 레이어를 효율적으로 평가할 수 있음. 따라서 하나의 행렬 곱셈을 사용하면 10,50 또는 100개의 뉴런을 의미하는 레이어의 출력값을 얻을 수 있음.

  • 우리가 가지고 있는 벡터 행렬 형태의 출력은 비선형성을 가집니다.
  • F: sigmoid 함수
  • 데이터는 x로 받음
  1. 첫 번째 행렬 곱 W1은 가장 윗줄
  2. 비선형성을 적용한 다음, 두 번째 히든 레이어 h2를 얻기 위한 두 번째 행렬곱
  3. 최종 출력

0개의 댓글