기본 콘텐츠로 건너뛰기

[ML] 결정트리(Decision Tree) 모델

순전파와 역전파(forward & backward propagation)

내용

순전파와 역전파(forward & backward propagation)

학습과정

일반적으로 신경망은 가장 먼저 층(layer)을 구성하며 입력은 그 층을 통과하여 relu 등과 같은 활성함수에 의해 출력됩니다.

tf.keras.layers.Dense(512, activation="relu")
output=relu(dot(W, input)+b)

위 relu 함수에서 W, b는 층의 속성인 텐서호 입력과 출력의 관계를 결정하는 가중치와 편차로 위 과정을 반복하면서 학습되는 매개변수입니다. 각각은 커널과 편향 속성이라고 합니다.

다음에서 나타낸 과정과 같이 초기 W, b는 임의 값으로 지정되며 입렬(input)과 함께 층으로 입력되며 드 출력이 이렂ㅇ한 기준을 만족하지 않은 경우 다시 층으로 입력되는 과정을 반복합니다. 이 과정을 학습(training)이라고 하며 학습을 통해 W, b의 최적화가 이루어지며 그에 대응하는 결과물이 출력됩니다. 이 과정이 머신러닝 또는 딥러닝의 핵십이 됩니다.

W0, b0, Inputlayers
activation, other operation
Woptim, boptim
Output
→: forward
→: backward

위 학습과정은 다음의 단계로 구성됩니다.

1 단계. 레이어, 활성함수, 출력층을 구축합니다.
가중치, 편차, 입력을 조합하는 초기 모델을 설정합니다.
2 단계. 모델에 의한 y의 추정치(ypred)를 계산합니다.
이 단계를 forward propagation(순방향 전파)라고 합니다.
3 단계. ypred와 y간의 불일치 측정값인 비용(cost) 또는 손실(loss)을 계산합니다.
비용함수를 설정합니다.
4 단계. 손실을 최소화하기 위한 W, b를 업데이트 합니다.
x의 변수에 대한 W, b의 기울기를 계산합니다.
각 기울기를 3 단계까지 사용된 W, b에 적용하여 업데이트 합니다.
이 업데이트 과정은 4단계에서 3, 2 단계로 역으로 추적되는 과정으로 backwawd propagation(역방향 전파)라고 합니다.

위 학습과정으로 인해 결국 ypred와 y간의 낮은 불일치, 즉, 손실이 매우 낮은 네트워크가 구축 됩니다. 즉, 특징(feature) x로 라벨 y를 적절하게 매핑하는 방법을 찾는 것입니다. 이 과정에서 가중치의 결정하는 4 단계가 난관이 됩니다. 만약 가중치 0.4일 경우 손실이 0.5이고 0.3일 경우 0.6이라면 가중치는 0.35로 지정되는 방식으로 진행 할 수 있지만 매우 비효율적입니다. 이에 반해 네트워크에서 사용되는 모든 연산이 미분 가능하다는 사실을 활용하고 네트워크 계수와 관련하여 손실의 기울기(gradient)를 계산하고 그 값을 가중치와 편차에 적용하는 과정을 반복하여 최적의 결과를 유도합니다. 즉, 손실을 최소화합니다.

미분

그림 1은 곡선(f) 위의 임의의 두 점, C, B를 연결하는 직선과 A와의 접선을 나타냅니다. 두 점 C와 B가 A쪽으로 접근한다면 기울기 c는 접선의 기울기 a에 근접할 것이며 결국에 기울기 c는 a와 같아질 것입니다. 결과적으로 A와 충분히 가까운 두 점 사이의 기울기를 A의 도함수 또는 미분(derivative)라고 합니다.

그림 1.

한 점에서 미분 결과의 절대값은 변화의 강도, 부호는 변화의 증가 또는 감소를 나타냅니다. 결과적으로 그 미분값은 증가 또는 감소의 속도(강도)를 알려줍니다.

모든 연속인 함수는 미분가능하며 일정한 지점에서의 미분값을 고려함으로서 목표로 하는 방향으로 그 지점의 이동을 유도할 수 있습니다. 즉, 다음 2차 함수의 그림에서 함수 위의 임의의 점 A를 아래 방향으로 이동시키기 위해 미분을 적용한 것입니다.

그림 2.

기울기(gradient): 자동미분

기울기는 학습에 참여하는 여러 텐서들의 연산에 대한 미분 결과입니다. 즉, 학습에서 생성되는 예측치와 실측치의 차이를 감소시키는 목적으로 그 둘의 차이 즉, 식 1의 비용(cost)이 미분의 대상이 됩니다.

$$\begin{align}\tag{1}&\hat{y_i}=x_i \cdot W + b\\ &\text{cost}=\frac{\sum^N_{i=1}(y_i-y)^2}{N} \end{align}$$

식 1에서 N은 데이터의 샘플의 크기입니다. 식에서 x, y는 상수이므로 비용은 예측치($\hat{y_i}$)에 의존합니다. 이 예측치는 가중치 W와 편차 b의 함수로 결국 비용은 가중치와 편차의 함수가 됩니다.

cost = f(W, b)

식 1에서 나타낸 것과 같이 비용은 실측치와 예측치에 대한 2차 함수 즉, MSE(mean squared error)가 됩니다. 결국 위 그림 2에서 곡선을 비용함수로 간주할 수 있으므로 비용이 최소로 되는 지점까지의 이동은 가중치에 대한 비용의 미분을 고려함으로서 달성될 수 있습니다. 이 단계서 미분항의 값이 크다면 감소 속도가 증가되어 최소지점을 지나칠 가능성이 존재합니다. 이러한 가능성을 최소로 하기 위해서 감소율을 축소할 수 있습니다. 이를 위해 step factor 또는 학습율(learning factor, η)를 고려해줍니다.

W=W0 cost=f(W)
W = W-η$\mathbf{\frac{d(f(W))}{dW}}$
Woptim

자동미분

위의 미분은 연산은 tensorflow에서 자동으로 진행할 수 있는 함수를 제공합니다. 즉, 입력변수에 대한 연산의 변화 즉, 기울기(gradient)를 계산하는 자동미분은 tf.GradientTape 클래스를 통해 실행됩니다. 실행되는 모든 연산이 tf.GradientTape에 기록됩니다. 이 과정은 그림 1의 역전파(backward propagation) 단계에서 이루어집니다.

다음은 2차원 텐서에 대한 역전파로 미분 연산 과정을 나타낸 것입니다.

$$\begin{align}x=\begin{bmatrix}x_{11}=1&x_{12}=1\\x_{21}=1&x_{22}=1\end{bmatrix} &\overset{+}{\Large{\Rightarrow}} & y=\sum x \qquad &\overset{\times}{\Large{\Rightarrow}} &z=y^2\\ &&&&\Large{\Downarrow} \\ \begin{aligned}\frac{dz}{dx}&=\frac{dz}{dy}\frac{dy}{dx}\\&=8\begin{bmatrix}1&1\\1&1\end{bmatrix}\\&=\begin{bmatrix}8&8\\8&8\end{bmatrix}\end{aligned} &\Large{\Leftarrow} &\frac{dy}{dx}=\begin{bmatrix}\frac{dx_{11}}{dx_{11}}&\frac{dx_{12}}{dx_{12}}\\\frac{dx_{21}}{dx_{21}}&\frac{dx_{22}}{dx_{22}}\end{bmatrix} &\Large{\Leftarrow} &\begin{aligned}\frac{dz}{dy}&=2y\\&=8 \end{aligned} \end{align}$$
tf.GradientTape(persistent=False, watch_acessed_variables=True)
tf.GradientTape()
이 클래스는 with 문을 사용하여 객체화합니다.
tf.GradientTape.watch()
이 함수를 적용하기 위한 객체, 즉 미분인자가 될 객체는 상수가 아닌 변수형이어야 합니다. .watch()메소드에 의해 전환 합니다.
tf.GradientTape.gradient(target, sources, output_gradients=None,...)
객체의 미분된 값을 호출
persistent=True
gradient() 메소드에 의해 결과가 호출되는 즉시 기록물은 삭제 됩니다. 그러나 persistent를 True로 지정함으로서 기록물들은 보존됩니다.

미분의 결과를 기록하기 위한 객체를 x라고 하면 이 객체를 변수로 지정해야 합니다. 위에서 언급한 것과 같이 tf.GradientTape.watch(x)를 적용합니다. 이 적용에 의해 객체 x에 대한 미분 결과들이 클래스 인스턴스에 기록됩니다. 다음은 x=5에 대한 미분 과정입니다.

$$\begin{align}&x=5, \quad y=x^5\\ &\frac{dy}{dx}=2x=10 \\&\frac{d^2y}{dx^2}=2 \end{align}$$
import tensorflow as tf
from tensorflow import keras
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
x=tf.constant(5.0)
with tf.GradientTape() as g: # 2차 미분(gradeient)를 위한 class instance
    g.watch(x) #2차 미분을 위한 전환
    with tf.GradientTape() as gg:#1차 미분(gradient)를 위한 class instance
        gg.watch(x)
        y=x**2
    dydx1=gg.gradient(y, x) #1차 미분
dydx2=g.gradient(dydx1, x)

dydx1   
<tf.Tensor: shape=(), dtype=float32, numpy=10.0 >
dydx2
<tf.Tensor: shape=(), dtype=float32, numpy=2.0 >
x=tf.constant(5.0)
y=x**2
with tf.GradientTape() as f:
    f.watch(x)
    y=x**2
    z=y**2
    w=z**2
dwdx=f.gradient(w, x)
dwdx
<tf.Tensor: shape=(), dtype=float32, numpy=625000.0>

f인 tf.GradientTape() 클래스 인스턴스에서 상수 x를 변수로 정의하고 객체 y, z, w를 선언하였스며 그 과정에서 각각의 그래디언트가 실행되었습니다. 즉, 객체 y, z, w를 변수 x 대해 미분이 시행된 상태입니다. 이 결과들 중 w의 미분을 호출한 것입니다.

다음으로 z의 미분결과를 호출하면 에러가 발생합니다. 이는 클래스의 매개변수 중 persistent=False로 지정하였으므로 결과를 호출한 즉시 f에 대한 모든 기록이 삭제되기 때문입니다. 대신에 기록들을 보존하기 위해서는 이 매개변수 persistent를 True로 지정합니다.

dzdx=f.gradient(z, x)
dzdx
---------------------------------------------------------------------------
   RuntimeError: A non-persistent GradientTape can only be used tocompute one set of gradients (or jacobians)
x=tf.constant(5.0)
y=x**2
with tf.GradientTape(persistent=True) as f:
    f.watch(x)
    y=x**2
    z=y**2
    w=z**2
dwdx=f.gradient(w, x)
dwdx
<tf.Tensor: shape=(), dtype=float32, numpy=625000.0>
f.gradient(z, x)
<tf.Tensor: shape=(), dtype=float32, numpy=500.0>
f.gradient(y, x)
<tf.Tensor: shape=(), dtype=float32, numpy=10.0>

기본적으로 GradientTape는 컨텍스트 내에서 접근되는 모든 학습 가능한 변수를 자동으로 감시합니다. 감시되는 변수를 세부적으로 제어하려면 watch_accessed_varaibles=False를 테이프 생산성자에 전달하여 자동 추적을 비활성화 할 수 있습니다. 이 경우 기록을 위해 지정된 변수에 대한 계산만 수행됩니다.

x=tf.constant(5.0)
w=tf.constant(2.0)
with tf.GradientTape(persistent=True, watch_accessed_variables=False) as g:
    g.watch(x)
    y=x**3
    z=w**3
dydx=g.gradient(y, x)
dydx.numpy()
75.0
dzdw=g.gradient(z, w) #w에 대한 미분을 실행되지 않음 
dzdw

댓글

이 블로그의 인기 게시물

[Linear Algebra] 유사변환(Similarity transformation)

유사변환(Similarity transformation) n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사행렬(similarity matrix)이 되며 행렬 A를 가역행렬 P와 B로 분해하는 것을 유사 변환(similarity transformation) 이라고 합니다. $$\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B $$ 식 2는 식 1의 양변에 B의 고유값을 고려한 것입니다. \begin{align}\tag{식 2} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align} 식 2의 행렬식은 식 3과 같이 정리됩니다. \begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \textsf{det}(I)\end{aligned}\end{align} 유사행렬의 특성 유사행렬인 두 정방행렬 A와 B는 'A ~ B' 와 같

[matplotlib] 히스토그램(Histogram)

히스토그램(Histogram) 히스토그램은 확률분포의 그래픽적인 표현이며 막대그래프의 종류입니다. 이 그래프가 확률분포와 관계가 있으므로 통계적 요소를 나타내기 위해 많이 사용됩니다. plt.hist(X, bins=10)함수를 사용합니다. x=np.random.randn(1000) plt.hist(x, 10) plt.show() 위 그래프의 y축은 각 구간에 해당하는 갯수이다. 빈도수 대신 확률밀도를 나타내기 위해서는 위 함수의 매개변수 normed=True로 조정하여 나타낼 수 있다. 또한 매개변수 bins의 인수를 숫자로 전달할 수 있지만 리스트 객체로 지정할 수 있다. 막대그래프의 경우와 마찬가지로 각 막대의 폭은 매개변수 width에 의해 조정된다. y=np.linspace(min(x)-1, max(x)+1, 10) y array([-4.48810153, -3.54351935, -2.59893717, -1.65435499, -0.70977282, 0.23480936, 1.17939154, 2.12397372, 3.0685559 , 4.01313807]) plt.hist(x, y, normed=True) plt.show()

R 미분과 적분

내용 expression 미분 2차 미분 mosaic를 사용한 미분 적분 미분과 적분 R에서의 미분과 적분 함수는 expression()함수에 의해 생성된 표현식을 대상으로 합니다. expression expression(문자, 또는 식) 이 표현식의 평가는 eval() 함수에 의해 실행됩니다. > ex1<-expression(1+0:9) > ex1 expression(1 + 0:9) > eval(ex1) [1] 1 2 3 4 5 6 7 8 9 10 > ex2<-expression(u, 2, u+0:9) > ex2 expression(u, 2, u + 0:9) > ex2[1] expression(u) > ex2[2] expression(2) > ex2[3] expression(u + 0:9) > u<-0.9 > eval(ex2[3]) [1] 0.9 1.9 2.9 3.9 4.9 5.9 6.9 7.9 8.9 9.9 미분 D(표현식, 미분 변수) 함수로 미분을 실행합니다. 이 함수의 표현식은 expression() 함수로 생성된 객체이며 미분 변수는 다음 식의 분모의 변수를 의미합니다. $$\frac{d}{d \text{변수}}\text{표현식}$$ 이 함수는 어떤 함수의 미분의 결과를 표현식으로 반환합니다. > D(expression(2*x^3), "x") 2 * (3 * x^2) > eq<-expression(log(x)) > eq expression(log(x)) > D(eq, "x") 1/x > eq2<-expression(a/(1+b*exp(-d*x))); eq2 expression(a/(1 + b * exp(-d * x))) > D(eq2, "x") a * (b * (exp(-d * x) * d))/(1 + b