이번에는 이진분류를 위한 신경망을 만들어보려 한다. 우선 이진분류 문제가 무엇인지 알아보자
✔︎ 이진 분류
이진 분류 문제는 '예', '아니오' 혹은 '0', '1' 같은 두 가지 값에 대하여 하나로 답하는 문제이다.
퍼셉트론의 선형 연산을 살펴보면 하나의 값 만을 출력한다. 즉 두 가지 값으로 결과를 표현할 수 없다는걸 알 수 있다.
초기에는 '임의의 임계치'를 설정하고 선형 연산 결과가 이 값을 넘는지에 따라 두 가지 값 중 하나를 출력하는 방법을 사용했는데, 이 방법은 미분 불가능 이라는 치명적인 문제점을 가지고 있다.
선형 연산에서는 일단 범위에 제한이 없는 실숫값을 계산하되, 이를 확률값의 성질에 맞게 즉 0~1 사이의 값을 갖도록 변환해주는 비선형 활성화 함수를 찾아내게 되는데 그게 바로 시그모이드 함수이다.
그래서 이진 분류를 수행하기 위해서 시그모이드(sigmoid)라는 비선형 활성화 함수를 사용한다.
그러면 이진분류에서는 어떤 방식으로 파라미터를 갱신할 수 있을까를 고민해보면,
신경망의 예측값에 따른 확률 분포와 실제 결괏값에 따른 확률 분포 사이의 각 확률 분포가 얼마나 다른지를 숫자 하나로 표현해주는 교차 엔트로피(𝐶𝑟𝑜𝑠𝑠 𝐸𝑛𝑡𝑟𝑜𝑝𝑦)라는 개념으로 해결 할 수 있다.
✔︎ 비선형 활성화 함수 시그모이드(Sigmoid)
- 범위에 제한이 없는 임의의 실숫값을 입력으로 받는다.
- 값을 확률값의 범위에 해당하는 0과 1 사이의 값으로 다시한번 연산을 수행한다.
- 입력값(x)을 답이 참일 가능성(𝒐𝒅𝒅𝒔)에 대해서 '로짓(𝒍𝒐𝒈𝒊𝒕)'으로 표현한 값으로 받는다.
- logit 이란 실제 표현하려는 값(𝑜𝑑𝑑𝑠)을 로그값으로 대신 나타낸 것
- 시그모이드 함수는 이 로짓값을 확률값으로 변환해주는 함수이다.
- 표기법 : $\sigma(x)$
로짓값으로 표시를 하게되면 넓은 범위의 값을 간단하게 표현할 수 있다. 또한 값의 변화를 변화량보다 변화 비율관점에서 더 민감하게 포착할 수 있게 된다.
import numpy as np
def sigmoid(x):
return 1 / (1.0 + (np.exp(-x)))
하지만 시그모이드 함수를 그대로 사용하게 되면 오버플로우 문제가 발생한다.
입력값이 양수의 경우 큰 문제가 없는데 음수의 경우 문제가 생긴다.
그래서 우리는 오버플로우 문제를 해결하기 위해 분모/분자에 $e^x$ 를 곱해주었고, 그 결과 오버플로우 문제가 해결되었다.
def sigmoid(x):
return np.exp(x) / (1.0 + (np.exp(x)))
sigmoid(-1000)
# 0.0
✔︎ 교차 엔트로피 ( Cross Entropy )
- 틀릴 수 있는 정보를 가지고 구한 최적의 엔트로피, 즉 틀릴 수 있는 정보에 대한 기댓값의 의미한다.
- Cross entropy는 일종의 loss fuction 이다.
- $p_i$ 는 어떠한 정보의 실제 확률이며, 신경망이 출력한 정보량이 실제로 어떠한 확률로 존재하는지에 대한 값이다.
- $log q_i$ 는 틀릴 수 있는 정보의 양을 나타내게 되며, 여기서 정보의 양은 신경망을 통해서 예측한 값이다.
- 딥러닝의 예측이 완전히 빗나가게 되면 교차 엔트로피값은 무한대가 되지만, 반대로 어느정도 학습이 된 경우라면 교차 엔트로피의 값은 엔트로피 값으로 수렴한다.
- 교차 엔트로피는 두 확률분포가 서로 얼마나 다른지를 나타내주는 정량적 지표 역할을 수행한다.
위의 교차엔트로피 식을 정리해보자.
이진 분류 문제에 대한 정답으로 𝑧가 주어졌다면,
참일 확률을 $P_T = z$, 거짓일 확률은 $P_F = 1-z$
이렇게 표현할 수 있다.
신경망 예측에 대한 확률값은 아래와 같이
$Q_T = \sigma (x)$ ,그리고 $Q_F = 1- \sigma (x)$
로 표현할 수 있다.
이 값들을 넣어 위의 식을 정리하면,
$H = -zlog \sigma (x) - (1-z)log(1-\sigma (x))$
정답값인 z는 0 또는 1로 주어지므로 이 값을 넣어서 정리를 해보면,
학습을 위해 위의 시그모이드 함수에 대한 교차 엔트로피의 편미분을 구하는 과정을 보면,
간단하게 정리할 수 있다.
하지만 여기서도 시그모이드가 사용이 됐기 때문에 오버플로우 문제가 발생 할 수 있다.
시그모이드를 처리한 것과 같이 간단하게 처리를 해주면 음수일 때의 문제를 해결 할 수 있다.
하지만 미니배치 처리를 할 때, 시그모이드와 시그모이드 교차 엔트로피의 수식의 입력값 𝑥에 양수와 음수가 동시에 들어오게 된다. 그래서 우리는 둘 다 들어왔을 경우에도 처리가 가능한 하나의 식을 만들어야 한다.
🔻
아래의 식처럼 표현하면 양수, 음수 모두 사용 가능한 하나의 식이 완성된다.
이 식의 목적은 입력값 𝑥 가 너무 큰 음수의 값이 들어오게 되었을 때 파이썬 인터프리터에서 발생하는 오버플로우 문제를 해결하는 것이다.
import numpy as np
# ReLU 함수
def relu(x):
return max(0, x)
# 시그모이드 함수
def sigmoid(x):
return np.exp(-relu(-x)) / (1 + np.exp(-abs(x)))
# 시그모이드 크로스 엔트로피
def sigmoid_cross_entropy_with_logits(z, x):
return relu(x) - x * z + np.log(l + np.exp(-abs(x)))
# sigmoid_cross_entropy_with_logits() 편미분 한 함수
def sigoid_cross_entropy_with_logits_derv(z, x):
return -z + sigmoid(x)
'DL(Deep-Learning) > 개념' 카테고리의 다른 글
[실습] numpy로 만드는 단층 신경망 - 다중 분류1 (0) | 2022.01.29 |
---|---|
[실습] numpy로 만드는 단층 신경망 - 이진 분류 2 (0) | 2022.01.29 |
train/test/validation 나누기 - splitfolders (0) | 2022.01.29 |
[DL] 엔트로피 Entropy (0) | 2022.01.29 |
분류 성능 지표 - Precision(정밀도), Recall(재현율) (0) | 2022.01.29 |