기본 콘텐츠로 건너뛰기

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

활성함수

내용

  1. 시그모이드함수(Sigmoid function)
  2. ReLU 함수
  3. 하이퍼볼릭탄젠트함수

활성함수(activation function)

활성함수는 가중치 합계를 계산하고 여기에 편향을 추가하여 뉴런의 활성화 여부를 결정합니다. 즉, 이 함수를 통과하면서 선형함수의 결과를 비선형으로 전환됩니다. 선형함수는 입력과 출력사이에 상수배의 관계를 의미합니다. 즉, 동일한 변화를 가지는 것으로 직선의 형태를 보이지만 비선형은 직선으로 표시할 수 없습니다. 선형함수의 반복은 그 관계를 변화시킬 수 없으므로 입력 층에 대한 신호의 변화를 명확히 하기 위해 비선형 함수 즉, 활성함수를 사용하여야 합니다. 결과적으로 활성화 함수는 미분가능한 비선형 결과를 반환합니다. 활성화함수는 다양한 종류가 있으며 그 중 일반적으로 사용하는 몇 가지를 살펴보면 다음과 같습니다.

시그모이드함수(Sigmoid function)

시그모이드 함수는 식 1과 같으며 모든 값은 (0, 1) 구간내로 변환합니다.

$$\begin{equation}\tag{1} \begin{aligned}&\text{sigmoid} ;\\ & f(x)=\frac{1}{1+\exp(-x)} \end{aligned} \end{equation}$$

인공 뉴런은 임계값을 기준으로 활성화 여부를 결정합니다. 입력이 임계값을 초과할 때 값 1을 취하고 반대의 경우는 0을 취합니다. 딥러닝은 그라디언트 기반 학습으로 임계값 단위에 대한 매끄럽고 미분 가능한 근사값의 출력이 가능하여야 합니다. 시그모이드 함수는 이러한 조건을 충족하는 함수입니다. 그러나 입력이 0에 가까울 때 시그모이드 함수는 선형 변환에 접근합니다.

x=torch.arange(-10, 10, 0.001, requires_grad=True)
y=torch.sigmoid(x)
plt.plot(x.detach().numpy(), y.detach().numpy())
plt.xlabel("x", size=11, weight="bold")
plt.ylabel("sigmoid(x)", size=11, weight="bold")
plt.show()

이 함수의 미분은 식 2과 같습니다.

$$\begin{align}\tag{2}\frac{d}{dx}\text{sigmoid(x)}&=\frac{\exp(-x)}{(1+exp(-x)))^2}\\&=\text{sigmoid(x)}(1-\text{sigmoid(x)})\end{align}$$

시그모이드 함수의 도함수는 아래에 표시됩니다. 입력이 0일 때 시그모이드 함수의 도함수는 최대 0.25에 도달합니다. 입력이 어느 방향으로든 0에서 발산함에 따라 도함수는 0에 접근합니다.

y.backward(torch.ones_like(x), retain_graph=True)
plt.plot(x.detach().numpy(), x.grad.detach().numpy())
plt.xlabel("x", size=11, weight="bold")
plt.ylabel("grad of sigmoid", size=11, weight="bold")
plt.show()

위 그래프에서 나타낸 것과 같이 이 함수는 입력의 절대값이 클수록 도함수값이 0으로 수렴되므로 학습 중지의 가능성이 증가할 수 있습니다. 즉, 이러한 경향은 역전파 과정에서 수행하는 미분 연산을 방해하는 요인이 됩니다. 다수의 은닉층이 존재할 경우 역전파 과정에서 실행되는 변화도 (미분)는 0에 접근하므로 가중치 W의 학습이 이루어지지 않게 됩니다. 이러한 현상을 기울기 소실 (Vanishing Gradient) 라고 합니다. 이러한 이유로 은닉층에 시그모이드 함수를 적용하는 것은 지양됩니다.

ReLU 함수

구현의 단순성과 다양한 예측 작업에 대한 우수한 성능으로 인해 가장 인기 있는 선택은 ReLU(Rectified Linear Unit)입니다. ReLU는 매우 간단한 비선형 변환을 제공합니다. 요소 x가 주어지면 함수는 해당 요소의 최대값과 최소값을 0으로 정의합니다.

$$\begin{align}\tag{3} f(x)&=\begin{cases} 0 & x\lt 0\\ x & x\ge 0 \end{cases}\\ReLU(x) &= \text{max(0, x)} \end{align}$$

비공식적으로 ReLU 함수는 해당 활성화를 0으로 설정하여 양수 요소만 유지하고 모든 음수 요소를 버립니다. 이 함수의 형태는 다음과 같습니다.

y_relu=torch.relu(x)
x.grad.data.zero_()
y_relu.backward(torch.ones_like(x), retain_graph=True)
plt.figure(figsize=(10, 4))
plt.subplot(1,2,1)
plt.title("ReLu")
plt.plot(x.detach().numpy(), y_relu.detach().numpy())
plt.xlabel("x", size=11, weight="bold")
plt.ylabel("ReLU(x)", size=11, weight="bold")
plt.subplot(1,2,2)
plt.title("grad of ReLU")
plt.plot(x.detach().numpy(), x.grad.detach().numpy())
plt.xlabel("x", size=11, weight="bold")
plt.ylabel("grad of ReLu", size=11, weight="bold")
plt.show()

입력이 음수이면 ReLU 함수의 도함수는 0이고 입력이 양수이면 ReLU 함수의 도함수는 1입니다. 입력이 정확히 0과 같거나 작은 경우 ReLU 함수는 기울기 소실에 직면하게 됩니다. 미분할 수 없습니다. 이러한 경우, 우리는 기본적으로 왼쪽 도함수를 사용하고 입력이 0일 때 도함수가 0이라고 말합니다. 그러나 대부분의 경우 입력이 실제로 0이 되는 경우는 드물기 때문에 이 문제를 피할 수 있습니다. 보다 적극적으로 다음 식과 같이 ReLU 함수를 수정한 parameterized ReLU(pReLU)를 적용하여 이 문제에 대한 가능성을 축소시킬 수 있습니다.

pReLU(x) = max(0, x) + α min(0, x)
y_prelu=torch.prelu(x, torch.tensor(0.2))
x.grad.data.zero_()
y_prelu.backward(torch.ones_like(x), retain_graph=True)
plt.figure(figsize=(10, 4))
plt.subplot(1,2,1)
plt.title("PReLu")
plt.plot(x.detach().numpy(), y_prelu.detach().numpy())
plt.xlabel("x", size=11, weight="bold")
plt.ylabel("ReLU(x)", size=11, weight="bold")
plt.subplot(1,2,2)
plt.title("grad of PReLU")
plt.plot(x.detach().numpy(), x.grad.detach().numpy())
plt.xlabel("x", size=11, weight="bold")
plt.ylabel("grad of ReLu", size=11, weight="bold")
plt.grid(True)
plt.show()

하이퍼볼릭탄젠트함수(Hyperbolic tangent function, tanh)

식 4의 형태를 가진 하이퍼블릭 탄젠트함수(tanh)는 시그모이드 함수와 유사하지만 변환하는 값의 범위가 (-1,1)로서 더 넓어집니다.

$$\begin{equation}\tag{4} tanh(x)=\frac{1-e^{-x}}{1+e^{-x}} \end{equation}$$
x=torch.arange(-10, 10, 0.001, requires_grad=True)
y=torch.tanh(x)
plt.figure(figsize=(7, 4))
plt.plot(x.detach().numpy(), y.detach().numpy())
plt.xlabel("x", size=12, weight="bold")
plt.ylabel("tanh(x)", size=12, weight="bold")
plt.grid(True)
plt.show()

위 그림과 같이 x축의 양끝으로 이동할수록 기울기 소실 현상이 나타납니다. 그러나 시그모이드 함수와는 달리 0을 중심으로 대칭되어 변화 영역이 넓어지므로 기울기 소실 현상이 감소됩니다. 이러한 이유로 비선형을 위한 활성함수로 시그모이드 함수보다 많이 사용됩니다.

tanh()의 미분은 다음과 같습니다.

$$\frac{d}{dx} tanh(x) = 1- tanh^2(x)$$

tanh 함수의 도함수의 형태는 다음과 같습니다. 입력이 0에 가까워짐에 따라 tanh 함수의 도함수는 최대값 1에 접근합니다. 그리고 시그모이드 함수에서 보았듯이 입력이 어느 방향으로든 0에서 멀어질수록 tanh 함수의 도함수는 0에 접근합니다.

y.backward(torch.ones_like(x), retain_graph=True)
plt.figure(figsize=(7, 4))
plt.plot(x.detach().numpy(), x.grad)
plt.xlabel("x", size=12, weight="bold")
plt.ylabel("grad of tanh", size=12, weight="bold")
plt.grid(True)
plt.show()

댓글

이 블로그의 인기 게시물

[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