이 포스팅은 밑바닥부터 시작하는 딥러닝을 공부하고 정리한것 입니다.
1. ReLU 계층
활성화 함수로 사용되는 ReLU의 수식은 다음과 같다.
바로 위의 식과 같이 순전파 때의 입력인 x가 0보다 크면 역전파는 상류의 값을 그대로 하류로 흘린다. 반면, 순전파 때 x가 0 이하면 역전파 때는 하류로 신호를 보내지 않는다. (0을 보낸다). 계산 그래프로는 다음처럼 그릴 수 있다.
이제 이 ReLU 계층을 구현해보자. 신경망 계층의 forward() 와 backward() 함수는 넘파이 배열을 인수로 받는다고 가정하자.
class Relu:
def __init__ (slef):
self.mask=None
def forward(self,x):
self.mask=(x<=0)
out=x.copy()
out[self.mask]=0
return out
def backward(self,dout):
dout[self.mask]=0
dx=dout
return dx
2. Sigmoid 계층
시그모이드 함수는 다음 식을 의미하는 함수이다.
exp 노드는 y=exp(x) 계산을 수행하고 '/' 노드는 y=1/x 계산을 수행한다.
먼저 '/' 노드 즉 y=1/x를 미분하면 다음 식이 된다.
위 식에 따르면 역전파 때는 상류에서 흘러온 값에 -y^2 (순전파의 출력을 제곱한 후 마이너스를 붙인 값)을 곱해서 하류로 전달한다. 계산 그래프에서는 다음과 같다.
+ 노드는 상류의 값을 여과 없이 하류로 보낸다.
'exp' 노드는 y=exp(x) 연산을 수행하며, 그 미분은 다음과 같다.
계산 그래프에서는 상류의 값에 순전파 때의 출력(이 예에서는 exp(-x))을 곱해 하류로 전파한다.
x노드는 순전파 때의 값을 서로 바꿔 곱한다. 이 예에서는 -1을 곱하면 된다.
역전파의 최종 출력을 x,y로만 계산할 수 있다.
class Sigmoid:
def __init__(self):
self.out=None
def forward(self,x):
out= 1/(1+np.exp(-x))
self.out=out
return out
def backward(self,dout):
dx=dout * (1.0-self.out) * self.out
return dx
이 구현에서는 순전파의 출력을 인스턴스 변수 out에 보관했다가, 역전파 계산 때 그 값을 사용한다.
3. Affine 계층
신경망의 순전파 때 수행하는 행렬의 곲은 기하학에서는 어파인 변환 이라고 한다.
X,W,B가 행렬(다차원 배열)이라는 점에 주의해야 한다. 행렬을 사용한 역전파도 행렬의 원소마다 전개해보면 스칼라값을 사용한 지금까지의 계산 그래프와 같은 순서로 생각할 수 있다.
각 변수의 형상에 주의해서 살펴보자. 특히 X와 dL/dX는 같은 형상이고, W와 dL/dW도 같은 형상이다.
데이터 N개를 묶어 순전파 하는 경우, 즉 배치용 Affine 계층의 계산 그래프는 다음과 같다.
기존과 다른 부분은 입력인 X의 형상이 (N,2)가 된 것뿐이다. 순전파의 편향 덧셈은 각각의 데이터(1번째 데이터, 2번째 데이터,...)에 더해진다. 그래서 역전파 때는 각 데이터의 역전파 값이 편향의 원소에 모여야 한다.
dy=np.array([[1,2,3],[4,5,6]])
db=np.sum(dy,axis=0)
print(db)
이 예에서는 데이터가 2개라고 가정한다. 편향의 역전파는 그 두 데이터에 대한 미분을 데이터마다 더해서 구한다. 그래서 np.sum() 에서 0번째 축(데이터를 단위로 한 축)에 대해서 (axis=0)의 총합을 구하는 것이다.
class Affine:
def __init__ (self,W,b):
self.W=W
self.b=b
self.x=None
self.dW=None
self.db=None
def forward(self,x):
self.x=x
out=np.dot(x,self.W) + self.b
return out
def backward(self,dout):
dx=np.dot(dout,self.W.T)
self.dW=np.dot(self.x.T,dout)
self.db=np.sum(dout,axis=0)
return dx
4. Softmax-with-Loss 계층
소프트맥스 함수는 입력 값을 정규화하여 출력한다.
여기서 주목할 것은 역전파의 결과이다. Softmax 계층의 역전파는 (y1-t1,y2-t2,y3-t3)라는 말끔한 결과를 내놓았다. (y1,y2,y3)는 Softmax 계층의 출력이고 (t1,t2,t3)는 정답 레이블이므로 (y1-t1,y2-t2,y3-t3)는 Softmax 계층의 출력과 정답 레이블의 차분인 것이다. 신경망의 역전파에서는 이 차이인 오차가 앞 계층에 전해지는 것이다. 이는 신경망 학습의 중요한 성질이다.
그런데 신경망 학습의 목적은 신경망의 출력(softamx의 출력)이 정답 레이블과 가까워지도록 가중치 매개변수의 값을 조정하는 것이였다. 그래서 신경망의 출력과 정답 레이블의 오차를 효울적으로 앞 계층에 전달해야 한다. 앞의 (y1-t1,y2-t2,y3-t3)라는 결과는 바로 Softamx 계층의 출력과 정답 레이블릐 차이로, 신경망의 현재 출력과 정답 레이블의 오차를 있는 그대로 드러내는 것이다.
class SoftmaxWithLoss:
def __init__ (self):
self.loss=None # 손실
self.y=None # softmax의 출력
self.t=None # 정답 레이블(원-핫 벡터)
def forward(self,x,t):
self.t=t
self.y=softmax(x)
self.loss=cross_entropy_error(self.y,self.t)
return self.loss
def backward(self,dout=1):
batch_size=self.t.shape[0]
dx=(self.y-self.t) / batch_size
return dx
'Deep learning > 모델 구현' 카테고리의 다른 글
9. 학습 관련 기술들 (1) - 매개변수 갱신(SGD,모멘텀,AdaGrad,Adam) (0) | 2021.04.23 |
---|---|
9. 오차역전법(3) - 오차역전법 구현하기 (0) | 2021.04.22 |
7. 오차역전파법(1) (0) | 2021.04.21 |
6. 신경망 학습 (3) - 학습 알고리즘 구현하기 (0) | 2021.04.20 |
5. 신경망 학습 (2) - 기울기 (0) | 2021.04.20 |