개요
아래와 같은, 다이내믹 프로그래밍의 3가지 한계를 극복하기 위해서 등장한 것이 바로 강화학습이었습니다.
1. 계산 복잡도
2. 차원의 저주
3. 환경에 대한 완벽한 정보가 필요
하지만 저희가 배운 살사나 큐러닝 알고리즘을 생각해봅시다. 환경의 모델을 사용하지는 않았지만, 저희는 각 상태의 큐함수를 테이블 형식으로 저장했습니다.
만약 에이전트에게 주어지는 상태가 정말 다양하고 환경이 시간에 따라서 변할 때, 예를 들어 알파고처럼 바둑을 학습하거나 로봇이 일상생활공간에서 학습한다면 저희는 살사나 큐러닝 알고리즘을 사용할 수 있을까요?
무수히 많은 상태의 정보를 테이블 형식으로 저장하여 계산하는 것이란 불가능한 일입니다.
즉 살사나 큐러닝 알고리즘은 3번의 문제만을 해결하고 계산 복잡도나 차원의 저주 문제는 해결하지 못한 것이죠.
이 문제는 큐함수를 매개변수로 근사함으로써 해결할 수 있습니다. 큐함수를 근사함수로 표현하여 사용하는 것이죠.
여러가지 근사함수 중 강화학습과 함께 많이 사용되는 것이 인공신경망입니다.
이번 포스팅에서는 이 인공신경망의 개념과 인공신경망의 학습 방법에 대해서 다뤄보도록 하겠습니다.
근사함수
인공신경망에 대해서 설명하기 전에 먼저 근사함수로 표현한다는 것이 정확히 무엇을 뜻하는지 알아봅시다.
아래 그림과 같이 2차원 평면에 많은 좌표 데이터가 파란색 동그라미로 표현되어 있다고 해봅시다.
좌표 데이터 하나하나를 모두 저장하는 것이 정확하겠지만, 데이터가 많을 경우에는 경향을 파악해 어떠한 함수로 근사하여 식으로 나타내는 것이 훨씬 효율적입니다.
위의 경우에는 데이터의 경향이 3차함수와 유사하기 때문에 $y = ax^3 + bx^2 + cx + d$로 근사한다면 상당히 정확하게 데이터를 표현할 수 있습니다.
이렇게 기존의 데이터를 매개변수(a, b, c, d)를 통해 근사하는 함수를 근사함수라고 하고 여러 가지의 근사함수 중 강화학습과 함께 사용되는 것이 인공신경망인 것이죠.
인공신경망
인공신경망의 개념
인공신경망은 인간의 뇌를 구성하는 신경세포(뉴런)에서 영감을 받아 만든 수학적 모델입니다. 그렇기에 먼저 뉴런의 구조에 대해서 간단히 알아봅시다.
위의 그림처럼 생긴 뉴런은 수상돌기를 통해 신호를 받아 축삭을 거쳐 다른 뉴런으로 신호를 전달합니다. 이때 뉴런은 입력 신호를 처리하여 일정 임계치를 넘어야만 신호를 전달합니다.
인공신경망에서 뉴런과 같은 역할을 하는 것이 노드(Node)입니다. 표를 통해서 뉴런의 구조에 해당하는 노드의 구조를 알아보도록 하겠습니다.
뉴런 | 노드 |
뉴런으로 들어오는 신호 | 입력 |
입력을 처리하는 함수 | 활성함수 |
뉴런에서 나가는 정보 | 출력 |
노드 또한 뉴런처럼 다른 노드로부터 들어온 입력을 활성함수로 처리한 후 출력됩니다. 노드의 구조는 다음과 같습니다.
노드와 활성함수
생물학적 뉴런은 아래 그림과 같이 시냅스(synapse)로 연결돼 있습니다.
수많은 뉴런은 시냅스로 연결되어 뇌의 복잡한 기능을 수행하는 것처럼 노드 또한 서로 연결되어 인공신경망의 역할을 수행합니다.
인공신경망의 노드끼리는 다음 그림처럼 계층 구조를 이루며 화살표로 연결되어 있습니다. 노드끼리의 화살표가 시냅스에 해당하는 것이죠.
이때 각 층을 레이어(Layer)라고 부르며 크게 입력층, 은닉층, 출력층으로 나뉩니다.
같은 층의 노드끼리는 연결이 없으며 정보는 단방향으로 입력층으로 들어와 은닉층을 거쳐 출력층으로 나갑니다.
층의 개수와 각 층마다의 노드의 수, 연결방법은 다르지만 큰 틀에서 구조는 모두 위의 그림과 같습니다.
뉴런을 연결하는 각 시냅스는 가중치를 가지고 있어서 단순히 연결만 하는 것이 아니라 연결의 비중도 조절합니다.
노드의 구조에서 가중치와 편향이 이를 나타낸 것입니다.
다른 인접한 노드로부터 3개의 입력을 받는다면 이 노드는 세 개의 입력을 다른 비중으로 생각하는 것이죠.
즉 노드에 입력이 들어오면 각 입력을 가중치에 곱하고 편향을 더한 값이 활성함수의 입력으로 들어가고 이 활성함수의 출력이 다음 노드의 입력이 되는 과정이 반복됩니다.
활성함수의 입력 = $\sum$(입력) x (가중치) + 편향
그렇다면 이제 활성함수가 무엇인지 알아봐야겠죠?
활성함수는 앞에서 설명했듯이 노드의 입력을 처리하는 함수입니다. 인공신경망에서 사용하는 활성함수에는 대표적으로 ReLU 함수, Tanh 함수, Sigmoid 함수가 있습니다.
가장 기본적으로 사용되는 활성함수는 Sigmoid 함수입니다. Sigmoid 함수의 식과 그래프는 다음과 같습니다.
$$f(x) = \frac{1}{1+e^{-x}}$$
이 식은 입력으로 어떤 값이 들어오든 0과 1 사이의 연속적인 값을 출력으로 내놓는다는 특징이 있습니다.
또 다른 활성함수로는 ReLU 함수가 있습니다. ReLU 함수의 식과 그래프는 다음과 같습니다.
$$f(x) = \begin{cases} x, &x ≥ 0 \\ 0, &x < 0 \end{cases} $$
현재 대부분의 인공신경망에서 이 ReLU 함수를 활성함수로 사용하고 있습니다.
지금 살펴본 Sigmoid 함수와 ReLU 함수는 둘 다 비선형 함수라는 공통점이 있습니다. 비선형 함수는 직선 1개로 표현할 수 없는 함수를 말합니다.
이렇게 활성함수로 비선형 함수를 사용하는 이유는 복잡한 문제를 풀기 위함에 있습니다. 저희는 활성함수의 출력이 다음 노드의 입력이 되는 과정이 반복되는 인공신경망 구조에 대해서 배웠습니다.
이때 만약 선형함수 $f(x) = ax + b$ 를 활성함수로 쓴 노드 2개가 연결되어 있다고 가정해 봅시다. 가중치와 편향을 0이라고 한다면 마지막 노드의 출력값은 $f(f(x)) = a^2x + ab + b$ 꼴로 다시 선형함수 꼴이 됨을 확인할 수 있습니다.
이는 가중치와 편향이 존재하고 노드가 여러 개 연결되어 있다고 해도 선형 함수의 계수만 바뀔 뿐이지 마지막 출력값이 선형함수 꼴임은 바뀌지 않습니다.
이런 선형함수로는 복잡한 문제를 표현하여 풀기란 불가능합니다. 인공신경망의 층을 넓히고 쌓는 의미도 어차피 결과는 입력값과 같은 선형함수이므로 사라지죠.
반면에 활성함수로 비선형 함수를 쓴다면 층을 넓히고 쌓을수록 함수는 새로운 형태로 변형되면서 여러 가지 복잡한 문제들을 표현하고 풀 수 있습니다. 이것이 활성함수로 비선형 함수를 사용하는 이유입니다.
복잡한 문제를 풀기 위해서는 은닉층이 더 늘어나야 합니다. 이때 2개 이상의 은닉층을 가진 인공신경망을 심층신경망이라고 합니다.
딥러닝
강화학습에 대해서 배우고 있는데 웬 딥러닝??이라고 생각하실 수도 있습니다.
딥러닝이란 아래 그림과 같이 단순히 여러 층을 가진 인공신경망을 사용하는 머신러닝 기법 중 하나를 뜻합니다.
강화학습에 심층신경망이 사용되는 것은 심층 강화학습(Deep reinforce learning)이라고 부르는데, 그 유명한 알파고에 이 기술이 사용된 것입니다.
딥러닝을 통해 가능한 것은 다양하고 복잡한 데이터에서 특징을 추출해 높은 추상화가 가능하다는 것입니다.
딥러닝 이전의 기계학습 알고리즘에서는 특징을 알고리즘을 사용하는 사람이 의도하는 대로 추출해서 사용했습니다. 따라서 사람이 특징을 잘못 추출했다면 학습의 성능이 매우 낮았습니다.
하지만 딥러닝에서는 특징 추출을 스스로 하면서 사람에 비해 효과적으로 여러 가지 복잡한 특징을 추출할 수 있습니다.
신경망의 학습
딥러닝을 통해 다양하고 복잡한 데이터에서 특징을 추출해 추상화를 했다면 이제 이를 이용하여 학습을 할 차례입니다.
딥러닝에서 학습은 결과적으로 가중치와 편향을 학습하는 것입니다. 학습과정을 살펴보기 위해서 머신러닝의 한 분야인 지도학습에서의 학습을 살펴보겠습니다.
지도학습이란 정답을 알고 있는 데이터를 이용한 학습이었습니다. 목표는 당연히 입력에 대한 출력이 정답과 같게 만드는 것이죠. 따라서 지도학습에서의 학습 데이터는 입력과 정답입니다.
입력이 심층신경망을 통과해서 나온 출력을 예측이라고 하고 학습 데이터의 정답은 타깃이라고 합니다.
입력이 심층신경망을 통과해 예측 값이 나왔다면 이제 오차함수를 이용하여 타깃과 예측의 오차를 계산해야 합니다.
대표적인 오차함수로는 평균제곱오차(Mean Squared Error)가 있습니다. 타깃에서 예측을 빼서 그 값을 제곱하는 것이죠.
오차 = $($타깃 - 예측$)^2$
오차함수를 통해 오차값을 구했다면, 오차를 최소화하도록 심층신경망의 가중치와 편향을 업데이트해야 합니다.
각 가중치와 편향이 오차에 얼마큼 기여했는지 구한 후 이 값을 오차와 곱한 만큼 업데이트해주면 될 것입니다.
업데이트 값 ∝ 오차 x 오차 기여도
이때 오차 기여도를 계산하기 위해 필요한 것이 역전파 알고리즘입니다.
역전파 알고리즘은 출력에서 계산한 오차로부터 다시 각 가중치와 편향의 오차 기여도를 오차에 대한 편미분값으로 계산하는 것입니다.
오차에 영향을 끼칠 수 있는 것은 심층신경망 내의 모든 가중치와 편향 값이기 때문에 편미분을 이용하면 각 가중치 혹은 편향 값을 조금 증가시키거나 감소시켰을 때 오차가 어떻게 변하는지, 즉 오차 기여도를 알 수 있습니다.
이 정보를 통해서 신경망 내부의 각 가중치나 편향 값을 업데이트하는 방법을 경사하강법이라고 부릅니다.
경사하강법은 아래 그림과 같이 출발점(Starting Point)에서 시작해서 가중치 값을 업데이트시켜가며 최종적으로 오차를 최소화하는 최종값(Final Value)에 도달하는 것입니다.
경사하강법에는 한 번 심층신경망을 업데이트할 때 이동거리(step size)를 얼마로 설정할지 결정하는 것이 중요합니다.
위 그림과 같이 step size를 작게 설정하면 학습 속도가 너무 오래 걸리고 반대로 너무 크게 설정한다면 오차의 최솟값으로 수렴하지 못하고 발산할 수 있습니다.
이런 경사하강법에는 SGD, RMSprop, Adam과 같은 방법이 있는데 이 책의 예제 코드들은 모두 Adam을 사용합니다.
책에는 이 방법들이 어떤 방법과 수식으로 가중치 값을 업데이트시켜 나가는지에 대해서는 자세한 설명이 나와있지 않은데, 이에 대해서는 시간이 될 때 따로 포스팅하도록 하겠습니다.
지금까지 인공신경망의 개념과 학습 방법에 대해서 알아봤습니다. 다음 포스팅에서는 이 인공신경망을 이용하여 새로운 그리드월드 예시에 적용시켜 에이전트가 어떻게 최적 정책을 학습하는지 코드와 함께 알아보도록 하겠습니다.
오늘도 읽어주셔서 감사합니다~!
http://www.yes24.com/Product/Goods/44136413
※ 이 글은 위의 책 내용을 바탕으로 작성한 글입니다.
'강화학습 > 파이썬과 케라스로 배우는 강화학습(스터디)' 카테고리의 다른 글
[강화학습] 11 - REINFORCE 알고리즘 (1) | 2023.01.08 |
---|---|
[강화학습] 10 - 딥살사(DeepSARSA) (1) | 2023.01.03 |
[강화학습] 08 - 큐러닝(QLearning) (2) | 2022.12.28 |
[강화학습] 07 - 살사(SARSA) (4) | 2022.12.27 |
[강화학습] 06 - 몬테카를로와 시간차 예측 (2) | 2022.12.24 |