지금까지 선형 모델을 어떻게 학습시키는지, 파이토치로 구현시 내부에서 어떤 일이 일어나는지를 살펴보았다. 단순한 예제 덕에 모델 자체의 구현보다 모델이 어떻게 학습하는지에 집중할 수 있었다. 파라미터에 오차를 역전파하고 손실값에 근거한 기울기로 파라미터를 조정하는 과정은 어떤 모델을 사용하더라도 동일했다.
이번 6장에서는 모델 아키텍처를 수정하여, 온도 변환 문제를 풀기위한 완전한 인공 신경망을 구현해보도록 한다.
신경망이라는 용어는 인간의 뇌가 동작하는 방식을 연상시키지만, 오늘날의 인공 신경망은 실제 뇌의 뉴런의 동작과는 거리가 멀다.
본질적으로 뉴런은 단순히 입력에 대한 선형 변환
(가중치를 곱하고 편향값을 더하는 등)과 활성 함수(activation function)
라 부르는 고정된 비선형 함수를 적용하는 역할을 한다.
수학적으로는 o = f(w * x + b)로 적을 수 있으며 x는 입력, w는 가중치 혹은 비율인자, b는 편향값 혹은 오프셋이라 부른다. f는 활성 함수인데 쌍곡탄젠트로 우선 설정했다. 일반적으로 x나 o는 단순 스칼라값 혹은 벡터이고, w또한 단일 스칼라 혹은 행렬이며, b는 스칼라나 벡터일 수 있지만 벡터인 경우에는 입력 및 가중치와 차원이 일치해야 한다.
계층(layer)
라고 한다.여러 뉴런으로 구성된 계층의 출력을 이어지는 다음 계층의 입력으로 사용한다. 여기에서 w_0은 행렬이고 x는 벡터임을 주의하자! w_0은 뉴런 전체에 대한 가중치를 담고 있기 때문이다.
이전 선형 모델과 앞으로 사용할 딥러닝과의 주요한 차이점 중 하나는 오차 함수의 모양이다. 선형 모델과 오차를 제곱한 손실 함수는 볼록 함수 형태의 오차 곡선을 가지고 있으므로 최솟값이 분명하게 하나로 정의된다. 하지만 신경망의 경우 볼록 함수의 오차 곡선의 모양이 이와 다르다. 우리가 근사하려는 각 파라미터는 정해진 답이 없다. 참값에 근사하기 위한 파라미터의 수정에 대한 노력만 있을 뿐이다. 즉 불완전함을 뜻한다.
우리는 출력 범위 제한을 통해 예로 점수를 추출할 때 0~10점을 의도한다면, 마이너스가 되는 값과 10점을 초과하는 값에 대해 제한을 두어 10점과 0점에 묶어두어야 한다.
출력 범위를 줄일 수도 있다. 이를 위한 함수로 torch.nn.Sigmoid가 있다. 예시로, x가 음의 무한대로 가면 -1이나 0에 가까워지고 양의 무한대로 갈수록 1에 가까워지는 곡선을 가진다. x == 0 일때 상수기울기를 가진다.
활성화 함수 vs 선형 함수
활성화 함수는 직선 하나로 표현이 불가능하다. 책에서 나오는 tanh그래프의 예시만 봐도 그렇다. 우리는 활성화 함수에 선형함수를 채택하지 않는다. 그 이유는 선형함수의 특징에 있다. 선형함수의 합성함수를 고려해보면, f = ax 의 선형함수가 여러번 결합되는 꼴이다. 즉 f(f(f(x)))의 경우 f = a^3x로 결국 상수만 변화하는 선형함수로 나타난다. 신경망의 경우 보통은 여러 변수 및 파라미터가 포함된다. 이들을 모두 데이터에 대해 학습시키는 과정을 거치는데, 보통은 대부분의 문제에서 선형모델로 나타나지 않는다는 점이다.
Sigmoid 시그모이드 함수는 활성화 함수의 한 종류로써 비선형 함수이다. 함수의 특징을 보면 입력값에 따라 0~1의 출력값을 주게되며, 입력값의 절댓값이 커질수록 미분값이 작아진다. 출력값을 작게 바꾸어주기 때문에, 기울기 폭증등의 이전에 실습에서 보았던(정규화로 해결했던) 문제가 발생하지 않는다. 또한 이전에 언급한 활성화 함수의 장점들을 가지고 있어 신경망 내에서 표현력을 갖추고 있다. 하지만, 위의 그림 처럼 기울기 소실의 문제가 발생한다. 기울기 소실 문제는, 시그모이드의 특성인 출력을 0에서 1까지 만들기 때문이다. 또한 출력의 중앙값이 0이아닌 0.5이므로, 출력의 가중치 합이 입력의 가중치 합보다 커지게 된다. 이를 통해 편향이동이 발생하며 함수의 출력이 0과 1에 수렴하게 된다.
- 이제는 출력값이 확률적일 때 값을 0에서 1 사이로 옮기는 경우 외에는 많이 사용하지 않는다.
ReLU의 경우 통상 활성 함수들 중에서 가장 성능이 좋기에 최신 연구 결과에 많이 사용된다. 실제로 효과가 증명된 함수가 다양하게 분포한다. 어떤 경우에는 명백히 틀린 활용이라고 볼 수 있지만, 활성 함수의 일반적 특성 비선형
이라는 점과 미분가능
하다는 점이다.
파이토치를 이용해 바닥부터 모델을 설계할 때, 첫 번째는 우리의 선형 모델을 신경망 유닛으로 바꾸는 것이다. 파이토치에는 torch.nn이라는 신경망 전용 서브모듈이 있다. 이 모듈에는 모든 신경망 아키텍처를 만들 수 있는 빌딩 블럭
이 들어있다. 파이토치 모듈은 nn.Module 베이스 클래스에서 파생된 파이썬 클래스이다.
파이토치가 제공하는 nn.Module의 모든 서브클래스에는 __call__
메소드가 정의 되어있으며 이를 통해 nn.Linear를 인스턴스화 하여 마치 함수인 것처럼 실행 가능하다. 실제로 call메서드에는 단순히 forward를 호출하는 것 뿐안 아니라 그 이전에 몇 가지 중요한 작업을 수행하기에 forward메서드로 실행하지 않고 y = model(x)같은 예시로 실행한다.
온도 변환계를 선형모델 대신 신경망을 근사 함수로 사용하도록 바꾸어 보자. 온도 보정 문제 자체가 근본적으로 선형이기 때문에 신경망 모델을 사용한다고 해서 성능이 더 좋아지지는 않는다.(단순히 방법론 관점에서)
손실 함수를 포함한 나머지 모든 것을 그대로 두고 model만 재정의 하도록 한다. 되도록이면 제일 단순한 신경망으로 제작한다. 선형 모듈 뒤에 활성 함수를 달고 다른 선형 모듈에 연결하도록 한다.
# 모델 정의
seq_model = nn.Sequential(
nn.Linear(1,13),
nn.Tanh(),
nn.Linear(13,1))
모델의 첫 번째 모듈은 nn.Sequential의 첫 번째 인자에 해당한다. 이 모듈의 중간 출력은 이어지는 다른 모듈에 전달되며, 최종적으로 마지막 모듈에 의해 출력이 만들어진다. 즉 모델은 한 개의 입력 피처로부터 13개의 은닉된 피처로 펼쳐지며, 결괏값을 tanh 활성 함수로 넘겨 결과로 나온 13개의 숫자를 하나의 출력 피처로 만들기 위해 선형적으로 다시 결합한다.