3장. 활성화 함수(Step Function)

2022. 6. 8. 16:18TIL💡/AI

입력 신호의 총합을 출력 신호로 변환하는 함수를 일반적으로 활성화 함수라 한다.

이름이 말해주듯 활성화 함수는 입력 신호의 총합이 활성화를 일으키는지를 정하는 역할을 한다.

$b$는 편향을 나타내는 매개변수로 뉴런이 얼마나 쉽게 활성화되는지를 제어한다.

$w$는 각 신호의 가중치를 나타내는 매개변수로 각 신호의 영향력을 제어한다.

 

https://github.com/WegraLee/deep-learning-from-scratch

$a = b + w_1x_1 + w_2x_2$

$y = h(a)$

 

활성화 함수는 임계값을 경계로 출력이 바뀌는데 이런 함수를 계단 함수라 한다.

그래서 퍼셉트론에서는 활성화 함수로 계단 함수를 이용한다라 할수 있다.

즉 활성화 함수로 쓸 수 있는 여러 후보 중에서 퍼셉트론은 계단 함수를 채용하고 있다.

그렇다면 계단 함수 이외의 함수는 무엇이 있을까?

 

📈 시그모이드 함수

지금까지 AI를 간단하게 구현하는 수업에서 시그모이드 식을 정말 무수히 자주 구현해보았지만 이에 대한 필요성과 원리를 파악하는 일은 처음이다;;

시그모이드 함수는 신경망에서 자주 이용하는 활성화 함수이다.

 

$h(x) = \frac{1}{1 + exp(-x)}$

 

$exp(-x)$는 $$e^{-x}를 뜻하며, e는 자연상수로 2.7182...의 값을 갖는 실수다. 복잡해보이지만 단순히 출력을 돌려주는 함수이다.

 

계단함수와 시그모이드 함수의 공통점

- 둘 다 입력이 작을 때의 출력은 0에 가깝고, 입력이 커지면 1에 가까워진다.

- 입력이 아무리 작거나 커도 0에서 1 사이의 결과

- 비선형 함수(신경망에서너는 활성화 함수로 비선형 함수를 사용해야 한다.)

계단함수와 시그모이드 함수의 차이점

- 계단함수는 매끄럽지 않지만 시그모이드는 연속적인 실수를 출력하면서 매끄러운 결과를 보여준다.

📈 ReLU 함수

지금까지 활성화 함수로서 계단 함수와 시그모이드 함수를 소개했다.

시그모이드 함수는 신경망 분야에서 오래전부터 이용해왔으나, 최근에는 ReLU(Rectified Linear Unit) 함수를 주로 이용한다.

 

ReLU는 입력이 0을 넘으면 그 입력을 그대로 출력하고, 0 이하면 0을 출력하는 함수다.

ReLU에서 Rectified란 '정류된'이란 뜻이다. 정류는 전기회로 쪽 용어로 예를 들어 +/-가 반복되는 교류에서 - 흐름을 차단하는 회로다. x가 0이하 일때를 차단하여 아무 값도 출력하지 않는(0을 출력하는) 것이다.

 

출력층 설계하기

신경망은 분류와 회귀 모두에 이용할 수 있다. 다만 둘 중 어떤 문제냐에 따라 출력층에서 사용하는 활성화 함수가 달라진다.

일반적으로 회귀에는 항등 함수를, 분류에는 소프트맥스 함수를 사용한다.

 

기계 학습 문제는 분류(classification)와 회귀(regression)로 나뉜다.
분류는 데이터가 어느 클래스에 속하느냐는 문제이다. 사진 속 인물의 성별을 분류하는 문제가 여기에 속한다.
한편, 회귀는 입력 데이터에서 (연속적인) 수치를 예측하는 문제이다. 
사진 속 인물의 몸무게를 예측하는 문제가 회귀이다.

분류와 달리 회귀라는 이름은 직관적이지 않다. 그 이유를 알려면 이름의 기원을 찾아봐야 한다.
19세기 후반 영국의 우생학자 프랜시스 골턴 경은 사람의 완두콩 등을 대상으로 키(크기)를 측정했다.
관찰 결과 키가 큰 부모의 자식은 부모보다 작고 작은 부모의 자식은 부모보다 큰, 즉 평균으로 회귀하는 경향이 있음을 알았다.
그 사이에는 선형 관계가 있어 부모의 키로부터 자식의 키를 예측할 수 있고, 그 예측 결괏값이 연속적인 수치인 것이다.

📈 항등함수

항등함수는 입력을 그대로 출력한다.

분류에서 사용하는 스프트맥스 함수의 식은 다음과 같다.

$y_k = \frac{exp(a_k)}{\sum_{i=1}^n{exp(a_i)}}$

 

$exp(x)$는 $e^x$을 뜻하는 지수함수이다. n은 출력층의 뉴런 수, $y_k$는 그중 k번째 출력임을 뜻한다.

소프트맥스 함수의 분자는 입력 신호 $a_k$의 지수함수, 분모는 모든 입력 신호의 지수 함수의 합으로 구성된다.

 

 

소프트맥스 함수 구현 시 주의점

코드로는 제대로 표현하고 있지만, 컴퓨터로 계산할 때는 결함이 있다.

바로 오버플로 문제이다.

소프트맥스 함수는 지수 함수를 사용하는데, 지수 함수란 것이 쉽게 아주 큰 값을 내뱉는다.

그리고 이런 큰 값끼리 나눗셈을 하면 결과 수치가 불안정해진다.

 

 

소프트맥스 함수의 특징

소프트 맥스 함수의 출력은 0에서 1.0 사이의 출력이다.

또, 소프트맥스 함수 출력의 총합은 1이다.

출력 총합이 1이 된다는 점은 소프트맥스 함수의 중요한 성질이다. 이 성질 덕분에 소프트맥스 함수의 출력을 확률로 해석할 수 있다.

 

 

가령 앞의 예에서 2번째 원소의 확률이 가장 높으니, 답은 2번째 클래스다라고 할 수 있다.

여기서 주의점으로, 소프트맥스 함수를 적용해도 각 원소의 대소 관계는 변하지 않는다.

신경망을 이용한 분류에서는 일반적으로 가장 큰 출력을 내는 뉴런에 해당하는 클래스로만 인식한다. 그리고 소프트맥스 함수를 적용해도 출력이 가장 큰 뉴런의 위치는 달라지지 않는다. 결과적으로 신경망으로 분류할 때는 출력층의 소프트맥스 함수를 생략한다. 현업에서도 지수 함수 계산에 드는 자원 낭비를 줄이고자 출력층의 소프트맥스 함수는 생략하는 것이 일반적이다.

 

기계학습의 문제풀이는 학습추론의 두 단계를 거쳐 이뤄진다.
학습 단계에서 모델을 학습하고(직업 훈련을 받고),  추론 단계에서 앞서 학습한 모델로 미지의 데이터에 대해서 추론(분류)을 수행한다.(현장에 나가 진짜 일을 한다.) 방금 설명한 대로, 추론 단계에서는 출력층의 소프트맥스 함수를 생략하는 것이 일반적이다.
한편 신경망을 학습시킬 때는 출력층에서 소프트맥스 함수를 사용한다.

순전파

추론과정을 신경망의 순전파(forward propagation)라고도 한다.

기계학습과 마찬가지로 신경망도 두 단계를 거쳐 문제를 해결한다. 먼저 훈련 데이터를 사용해 가중치 매개변수를 학습하고, 추론 단계에서는 앞서 학습한 매개변수를 사용하여 입력 데이터를 분류한다.

 

손글씨 숫자 인식 실습

원-핫 인코딩 형태

예를 들어 [0,0,1,0,0,0,0,0,0]처럼 정답을 뜻하는 원소만 1이고, 나머지는 모두 0인 배열이다.

 

파이썬에는 pickle이라는 편리한 기능이 있다. 이는 프로그램 실행 중에 특정 객체를 파일로 저장하는 기능이다.
저장해둔 pickle 파일을 로드하면 실행 당시의 객체를 즉시 복원할 수 있다.
MNIST 데이터셋을 읽는 load_mnist() 함수에서도 pickle을 이용한다.

정규화: 데이터를 특정 범위로 변환하는 처리

전처리: 신경망의 입력 데이터에 특정 변환을 가하는 것

 

여기에서는 입력 이미지 데이터에 대한 전처리 작업으로 정규화를 수행한 셈이다.

 

현업에서도 신경망(딥러닝)에 전처리를 활발히 사용한다.
전처리를 통해 식별 능력을 개선하고 학습 속도를 높이는 등의 사례가 많이 제시되고 있다.
앞의 예에서는 각 픽셀의 값을 255로 나누는 단순한 정규화를 수행했지만, 현업에서는 데이터 전체의 분포를 고려해 전처리하는 경우가 많다. 예를 들어 데이터 전체 평균과 표준 편차를 이용하여 데이터들이 0을 중심으로 분포하도록 이동하거나 데이터의 확산 범위를 제한하는 정규화를 수행한다. 그 외에도 전체 데이터를 균일하게 분포시키는 데이터 백색화 등도 있다.

 

배치 처리

이전까지는 이미지 1장씩 처리했다면 이제는 100개 단위로 이미지를 묶어서 처리한다면 입력층은 100 * 784(28 * 28)로 입력하고, 출력층은 1차원이 아니라 100 * 10(0~9)로 나타난다.

 

이처럼 하나로 묶은 입력 데이터를 배치(batch)라 한다.

배치 처리는 컴퓨터로 계산할 때 큰 이점을 준다. 이미지 1장당 처리 시간을 대폭 줄여주는 것이다.
크게 두 가지 이유가 있는데, 하나는 수치 계산 라이브러리 대부분이 큰 배열을 효율적으로 처리할 수 있도록 고도로 최적화되어 있기 때문이다.
그리고 커다란 신경망에서는 데이터 전송이 병목으로 작용하는 경우가 자주 있는데, 배치 처리를 함으로써 버스에 주는 부하를 줄인다는 것이 두번째 이유이다.(정확히는 느린 I/O를 통해 데이터를 읽는 횟수가 줄어, 빠른 CPU나 GPU로 순수 계산을 수행하는 비율이 높아진다.)
즉, 배치 처리를 수행함으로써 큰 배열로 이뤄진 계산을 하게 되는데, 컴퓨터에서는 큰 배열을 한꺼번에 계산하는 것이 분할된 작은 배열을 여러 번 계산하는 것보다 빠르다.

전체 실습 코드