본 블로그는 UC Berkeley의 CS 185/285강의를 기반으로 작성했다.
이번 포스트에서는 강화학습이 나오게 된 배경에 대해서 집중적으로 다룬다.
from supervised learning to imitation learning
기존 supervised learning에서는 모델을 학습할 때 어떤 input x에 대해 정답 y라는 라벨이 있고, 이에 대한 우도를 높이도록 학습을 진행한다.
그걸 행동 학습으로 옮기면 state/observation $o_t$가 input으로 들어왔을 때 action $a_t$를 맞추는 문제가 된다.
여기서는 무엇을 보고 action을 선택할지에 대한 두가지 구분이 나온다.
- 첫 번째는 fully observed 한 경우다. 이 경우는 observation $o_t$만 봐도 실제 state를 거의 다 알 수 있다. 따라서 $\pi_{\theta}(a_t|o_t)$만으로 action을 결정할 수 있다.
- 두 번째는 partially observed 한 경우이다. 이 경우는 observation 하나만으로 state를 알기 어렵다. 예를 들면 카메라 한 장만 보고 운전 중 앞차가 급감속 했는지, 신호가 몇 초 전부터 바뀌었는지에 대한 정보는 알 수 없을 수 있다. -> 따라서 이 경우는 과거의 history를 사용하거나 압축한 state를 유지해야 한다. $\pi_{\theta}(a_t|o_t)$로 action을 결정하기 위해서는 $p(s_{t+1}|s_t,a_t)$(transition model) ${p(o_t|s_t)}$(observation model)도 필요하다.
- 추후 나올 내용이지만 요즘에는 policy가 history를 직접 입력 받아 필요한 state representation을 학습하기도 한다고 한다.
따라서 supervised learning으로 어떤 행동을 학습하기 위해서는 모든 observation, action의 순서가 담긴 trajectory에 대해 우도가 높아지도록 학습하면 된다.
the behavioral cloning algorithm
이 trajectory를 학습하는데에는 이산적인 것과 연속적인 것 두 가지 경우가 있다.
- 이산적인 경우(e.g. token for LLM, 게임 조작 등): 이 경우는 일반적인 softmax와 같은 logits를 output으로 내는 함수를 활용하여 다음 action을 선택할 수 있다.
- continuous 한 경우(e.g. 자동차 운전): 이 경우는 discrete 한 경우와 달리 행동을 logit으로 내뱉지 못한다. 따라서 어떤 분포가 있고 그 분포상의 output을 내는 것으로 continuous에 대응할 수 있다.
- 특정 정규분포가 있고 그 정규 분포의 평균과 표준편차를 데이터에 맞게 학습하면 데이터에 맞는 분포를 모사할 수 있다.
그런데 근본적인 문제가 있다. observation과 action의 trajectory로 지도학습을 했을 때(Behavioral cloning) 정말로 모델이 잘 작동할까? (예를 들어 자동차 운전의 하나의 궤적을 주고 모델을 학습시키면 자동차를 잘 운전할 수 있는 모델이 나올까?)
잘 작동하지 않을 수 있다. 이유는 처음 action까지는 좋은데 그 이후 state부터는 모델이 보지 못한 환경일 가능성이 크고, 이게 계속해서 누적될 수 있다. 각 step이 i.i.d. 가정이 보장되지 않는다.
그러면 얼마나 나빠질 수 있을까? (증명 생략)
작은 step당 error가 누적되며 expected cost가 최악의 경우 $O(\epsilon H^2)$까지 나빠질 수 있다.($\epsilon$: distribution에서 한 step의 imitation error, H: 전체 horizon(trajectory길이))
물론 이건 상한이고 진행 중 다시 train분포로 돌아가는 상황과 학습하지 않은 state를 보더라도 그렇게까지 모델이 일반화가 덜되지 않았을 수는 있기 때문에 그렇게까지는 나빠지지는 않을 수도 있다. 또 이를 볼때 학습 단계에서 실수에서 복원되는 사례를 많이 봐야 모델이 일반화를 배울 수 있다.
그러면 어떻게 Behavioral cloning을 더 좋게 할 수 있을까?
DAgger는 아래와 같은 프로세스를 진행했다
- train $\pi_{\theta}(a_t|o_t)$ from human data $D={o_1, a_1,..., o_N, a_N}$
- run $\pi_{\theta}(a_t|o_t)$ to get dataset $D_{\pi}={o_1, ..., o_M}$
- ask human to label $D_{\pi}$ with actions $a_t$
- aggregate: $D \leftarrow D\cup D_{\pi}$
이런식으로 실수에 대한 부분을 사람이 어떻게 복구할 수 있을지를 지속해서 정보를 주며 실수에 대한 복원을 잘할 수 있도록 진행한다.
문제는 정답 action을 몇천개 몇백만 개 혹은 그 이상의 state에 대해 사람이 일일이 labeling 해줘야 한다. 또한 사람도 최적 행동이 뭔지 판단하기 어려울 수 있다.
따라서 이를 중간에 개입해서 observation과 action에 대한 모든 사람의 trajectory를 추가로 데이터셋에 추가하고 학습하는 식으로 진행하기도 한다.