Python으로 OX 게임 AI를 처음부터 만드는 그 250: 탐색과 활용에 올인한 다중 팔 밴딧 문제 알고리즘의 그래프 비교 및 고찰
요약
본 기사는 다중 팔 밴딧 문제(MAB)를 해결하는 알고리즘을 Python으로 구현하고, 탐색과 활용의 트레이드오프를 시각적으로 비교 분석합니다. 특히 '탐색에 올인한' Random_MAB_Agent와 '활용에 올인한' Greedy_MAB_Agent 두 가지 극단적인 접근 방식을 실제 시뮬레이션으로 구동하여 그 차이를 명확히 보여줍니다.
핵심 포인트
- Random_MAB_Agent는 탐색(Exploration)에 집중하는 알고리즘입니다.
- Greedy_MAB_Agent는 현재 정보 기반의 활용(Exploitation)에 집중합니다.
- 두 알고리즘을 비교하여 '탐색과 활용'의 트레이드오프를 시각적으로 이해할 수 있습니다.
- 실제 대규모 시뮬레이션을 통해 두 에이전트의 성능 차이를 분석했습니다.
본 기사의 프로그램은 Python 버전 3.13에서 실행하고 있습니다. 또한, numpy 버전은 2.3.5입니다.
| 링크 | 설명 |
|---|---|
| marubatsu.py | 마루바츠(Marubatsu), Marubatsu_GUI 클래스 정의 |
| ... | |
| AI 목록과 지금까지 만든 데이터 파일에 대해서는 아래 기사를 참조해 주십시오. |
지난 기사에서는 다중 팔 밴딧 문제(Multi-arm Bandit Problem)를 해결하는 다양한 알고리즘의 기반이 되는 기본 클래스를 MAB_Agent라는 이름으로 정의하고, MAB_Agent 클래스를 상속받아 탐색에 올인한 원시 몬테카를로법 근사치를 수행하는 Random_MAB_Agent 클래스를 몇 줄만으로 간결하게 정의할 수 있음을 보여주었습니다.
이번 기사에서는 활용에 올인한 클래스를 정의하고, 이전 기사에서 수식을 사용하여 고찰했던 다음 두 가지 극단적인 알고리즘을 실제로 프로그램을 구동하여 그래프를 그리고, 수식으로 생각했던 '탐색과 활용의 트레이드오프(딜레마)'가 실제 데이터로 어떻게 그래프에 나타나는지 시각적으로 이해하기 쉽게 비교하고 해설합니다.
탐색에 올인한 알고리즘 (완전히 무작위로 계속 당기기) -
활용에 올인한 알고리즘 (현재 데이터를 믿고 최선이라고 생각되는 슬롯머신을 계속 당기기)
참고로, MAB_Agent 클래스의 상세 사양은 지난 기사를 참조해 주십시오.
강화학습(Reinforcement Learning)에서의 활용은 지금까지의 스텝에서 얻은 정보를 바탕으로 가장 잘 맞을 것이라고 생각되는 슬롯머신을 선택합니다. 이러한, **현재 시점에서 얻고 있는 정보 중에서 최적의 것을 선택하는 알고리즘을 '탐욕법(greedy algorithm)'**이라고 부릅니다.
이에 활용에 올인한 알고리즘 클래스 이름을 Greedy_MAB_Agent로 명명했습니다. 아래는 Greedy_MAB_Agent 클래스의 정의입니다. 지난 기사에서 정의했던 Random_MAB_Agent 클래스와 마찬가지로, 공통 처리는 기본 클래스(MAB_Agent)에 맡김으로써, 하위 클래스 측에서는 NAME 속성 설정과 select_arm 메서드 몇 줄만 작성하면 새로운 클래스를 쉽게 정의할 수 있습니다. select_arm 메서드의 처리 내용은 이전 기사와 같으므로, 잊으신 분은 복습해 주십시오.
from ai import MAB_Agent, Random_MAB_Agent
import numpy as np
class Greedy_MAB_Agent(MAB_Agent):
...
참고로 탐욕법의 Wikipedia 항목 링크를 아래에 제시합니다.
이전 기사에서 자세히 고찰했듯이, 탐색에 올인한 알고리즘과 활용에 올인한 알고리즘은 둘 다 획득 코인의 총수(목적 함수)가 '모든 슬롯머신의 적중 평균 확률 ($p_{mean} = 0.5$)에 시도 횟수를 곱한 매수' 근처에서 저조하게 머물러 버립니다만, '비슷하게 낮은 점수가 나오는 이유'는 양자 사이에 완전히 다릅니다.
따라서 Random_MAB_Agent (탐색 올인)과 Greedy_MAB_Agent (활용 올인)의 구현 클래스를 사용하여 실제로 1,000회의 시뮬레이션(에피소드)을 수행하고, 각종 그래프의 거동을 비교함으로써 그 결정적인 성질 차이를 명확히 합니다.
먼저 두 알고리즘에 대해 이전 기사와 완전히 동일한 다음 조건을 설정하고, '총 스텝 수 1만 회'의 대규모 시뮬레이션을 각각 1,000번씩 실행합니다.
슬롯머신의 대수: 3대 -
각 슬롯머신의 적중 진 확률: [0.3, 0.5, 0.7]
총 수천만 번의 계산을 루프시키기 때문에 필자의 컴퓨터에서는 실행 결과에서 보이듯이 두 에이전트 합계로 약 6분간의 대기 시간이 발생했습니다. 시간을 들여 모은 실험 데이터는 JupyterLab을 닫으면 사라지므로, 계산한 데이터를 save 메서드를 호출하여 파일에 저장해 두기로 합니다.
데이터 저장 폴더는 지금까지의 일련 기사와 마찬가지로, 프로그램이 있는 곳에서 한 단계 위 계층에 있는 data 폴더(`
)를 지정합니다. 인수로 전달할 base name 1은 간단히 "random_agent"와 "greedy_agent"로 합니다. 이를 통해 폴더 내에는 확장자 .pkl가 붙은 압축된 데이터 파일이 자동으로 저장됩니다.
아래는 이 처리를 수행하는 프로그램입니다.
p = [0.3, 0.5, 0.7]
random_agent = Random_MAB_Agent(p=p)
random_agent.play_episodes(stepnum=10000, episodenum=1000)
...
실행 결과
100%|██████████| 1000/1000 [02:40<00:00, 6.23it/s]
save completed.
100%|██████████| 1000/1000 [03:02<00:00, 5.48it/s]
...
위의 프로그램을 실행하여 저장되는 random_agent.pkl와 greedy_agent.pkl 파일 크기는 모두 300 MB 이상의 크기가 됩니다.
앞으로 다양한 시뮬레이션을 수행하고 데이터를 저장할 때마다 이러한 거대한 크기의 파일이 생성되면, 저장된 파일의 총 크기가 순식간에 수 기가바이트를 초과하여 하드디스크 용량을 압박하는 심각한 문제가 발생합니다.
이에 이 문제를 해결하기 위해, 저장하는 파일의 크기를 줄이는 방법을 적용하기로 합니다.
MAB_Agent 클래스에서는 데이터를 numpy의 ndarray에 저장하고 있는데, 이때 데이터 타입은 64비트(8바이트) 부동소수점 타입입니다. 즉, ndarray의 하나의 요소는 8바이트의 데이터 크기를 가집니다. 따라서 "에피소드 수 × 스텝 수"개의 요소를 가진 mean_coins_by_step 속성에 기록된 ndarray의 데이터 크기는 1000 × 10000 × 8 = 약 80 MB이고, "슬롯머신 기계 대수 × 에피소드 수 × 스텝 수"개의 요소를 가진 slotratio_by_step 속성에 기록된 ndarray의 데이터 크기는 3 × 1000 × 10000 × 8 = 약 240 MB라는 거대한 크기가 됩니다.
numpy가 지원하는 다른 부동소수점 타입을 나타내는 데이터 타입으로는 16비트(2바이트)의 np.float16과 32비트(4바이트)의 np.float32가 있습니다. 당연하게도, 데이터 크기를 64비트에서 16비트나 32비트로 줄이면 데이터의 정밀도(몇 자리까지 데이터를 정확하게 표현할 수 있는지)가 다음과 같이 낮아집니다.
- 64비트 부동소수점의 정밀도: 10진수로 약 16자리
- 32비트 부동소수점의 정밀도: 10진수로 약 7자리
- 16비트 부동소수점의 정밀도: 10진수로 약 3자리
3자리의 정밀도가 있다면 예를 들어 0.575처럼 0 이상 1 이하의 수치를 소수점 3번째 자리까지 정확하게 표현할 수 있기 때문에, 얻은 코인 개수의 평균을 기록하여 알고리즘 간에 비교한다는 목적이라면 충분한 정밀도라고 할 수 있습니다. 이에 ndarray가 기록하는 데이터의 데이터 타입을 16비트(2바이트) 부동소수점 타입으로 변경하여 ndarray의 데이터 크기를 1/4로 줄이는 방법을 적용하기로 합니다2.
numpy의 데이터 타입3은 가변 인자 dtype로 지정할 수 있습니다. 16비트 부동소수점의 경우에는 dtype="float16"을 지정합니다. 아래는 거대한 ndarray를 기록하는 mean_coins_by_step과 slotratio_by_step의 데이터 타입을 수정하는 프로그램입니다.
def play_episodes(self, stepnum, episodenum):
self.stepnum = stepnum
self.episodenum = episodenum
...
위와 같은 수정을 통해, save 메서드로 저장된 파일의 크기가 약 300 MB에서 약 14 MB로 대폭 감소하는 것을 확인할 수 있었습니다4. 이후로는 이 축소된 데이터를 사용하여 고찰을 진행하기로 합니다. 참고로, 이번 기사의 ai.py는 위와 같은 수정이 완료된 내용입니다.
그래프를 표시하기 전에, 먼저 print_summary
메소드를 호출하여 각 실험 결과의 통계 데이터를 문자로(텍스트로) 출력하고, 수치에서 읽을 수 있는 성질에 대해 고찰합니다.
참고로, 지난 기사에서 설명했듯이, 1 에피소드의 집계 결과를 기록하는 속성은 '가장 마지막에 실행한(최신) 1회분의 에피소드 데이터가 덮어쓰여 남아 있다'는 사양을 했기 때문에, print_summary
은 10,000회의 에피소드 중 최종 에피소드의 결과를 표시합니다.
random_agent.print_summary()
greedy_agent.print_summary()
실행 결과
완전 랜덤(원시 몬테카를로법의 근사) 의 결과 요약
============================
총 스텝 수 = 10000
...
아래는 '마지막으로 이루어진 1 에피소드의 결과'를 정리한 표입니다.
| 완전 랜덤(탐색에 전념) | 탐욕법(활용에 전념) | |
|---|---|
| 얻은 코인의 총수 | 4952 | 3000 |
| ... |
완전 랜덤의 경우, 3대의 슬롯 머신이 거의 균등하게(각 약 3,333회씩) 선택됩니다. 그 결과, 대수의 법칙이 작용하여 획득 코인의 평균값(0.297 / 0.514 / 0.684)은 슬롯 머신의 진정한 확률(0.3 / 0.5 / 0.7)에 거의 정확하게 수렴하고 있습니다. 또한, 전체 평균값(0.495)도 전대 평균 확률인 0.500에 거의 정확하게 수렴합니다.
반면, 탐욕법의 점수는 0.300이라는 형편없는 결과입니다. 내역을 살펴보면, 가장 당첨 확률이 낮은 슬롯 0(확률 0.3)만 1만 회 모두 계속 뽑고 다른 2대는 한 번도 건드리지 않았습니다. 이는 '1만 스텝의 초기에 우연히 슬롯 0에서 당첨이 나왔다'는 것이 원인입니다. 탐욕법 AI는 '처음에 우연히 당첨된 슬롯 0이야말로 최고의 당첨 기계다'라고 착각하고, 눈앞의 이익을 쫓다가 평생 슬롯 0만 뽑는 사고 정지 루프(まちぼうけ現象)에 빠져버린 것입니다.
참고로, 이번 시뮬레이션에서는 최종 에피소드에서 우연히 당첨 확률이 가장 낮은 슬롯 0에서 처음에 당첨을 끌어냈지만, 물론 반대로 최고의 당첨 기계에서 처음에 당첨을 끌어낼 수도 있으며, 그 경우 탐욕법의 점수는 0.700이라는 최고 점수가 됩니다. 즉, 탐욕법은 운이 좋으면 최고의 점수를 얻을 수 있지만, 반대로 운이 나쁘면 최저 점수가 되어버리는 하이 리스크 하이 리턴한 전술이라고 할 수 있습니다.
다음으로, 아래의 1,000회 에피소드를 중첩시킨 최종 스텝(1만 번째)의 집계 데이터를 비교합니다. 표준편차는 소수점 이하 제4자리에서 반올림했습니다.
| 완전 랜덤 (탐색에 전념) | 탐욕법 (활용에 전념) |
|---|---|
| 스텝당 코인의 평균 | 0.500 |
| 스텝당 코인의 표준편차 | 0.005 |
| ... | |
| 위 표에서 '스텝당 코인의 평균'은 어느 알고리즘 모두 슬롯 머신의 당첨 평균인 0.5와 거의 같은 값이 되는 것을 알 수 있습니다. 참고로, 탐욕법의 경우 0.559처럼 0.5보다 약간 큰 값이 되는 이유에 대해서는 이전 기사를 참조해 주십시오. |
완전 랜덤의 경우 각 슬롯 머신의 당첨 추정치는 모두 슬롯 머신의 진정한 당첨 확률과 거의 같습니다. 또한, 표준편차가 0.005와 같은 매우 작은 값이라는 점에서, 거의 모든 에피소드에서 모든 슬롯 머신의 당첨 확률을 극히 높은 정확도로 추정할 수 있음을 알 수 있습니다. 이는 모든 슬롯 머신이 균등하게 약 3,000회 이상 선택된 결과, 대수의 법칙이 작용한 덕분입니다.
반면, 탐욕법의 각 슬롯 머신의 당첨 추정치는 모두 진정한 당첨 확률보다 상당히 작은 값이 됩니다. 이는 처음에 당첨된 슬롯 머신만 계속 선택되기 때문에, 그 외의 슬롯 머신은 에피소드를 통해 한 번도 당첨이 나오지 않아, 당첨 추정치가 반드시 0으로 추정되어 버리기 때문입니다. 그 결과, 당첨 추정치는 0 또는 진정한 당첨 확률 중 하나의 값이 계산되게 되어 평균이 진정한 당첨 확률에서 크게 감소합니다. 또한, 당첨 추정치로 0 또는 진정한 당첨 확률이라는 두 가지 다른 수치가 계산되기 때문에, 변동을 나타내는 표준편차도 0.1 이상의 큰 값이 됩니다.
표시되는 수치들을 나열한 표는 직관적으로 이해하기 어렵다는 문제가 있습니다. 따라서 두 알고리즘의 속성 차이를 다양한 그래프를 사용하여 고찰함으로써, 다른 관점에서 시각적으로 명확히 보여드리겠습니다.
두 알고리즘의 마지막 에피소드 데이터를 기반으로, 스텝 수(시간)가 지남에 따라 획득 코인의 총합이 어떻게 쌓여왔는지를 나타내는 '누적 보상 추이'를 시각화합니다.
완전 랜덤(탐색 전용)에서의 이 그래프의 상세한 해석 방법은 이전 기사를 참고해 주십시오.
random_agent.draw_cumulative_reward()
greedy_agent.draw_cumulative_reward()
실행 결과
탐욕법(Greedy)이 출력하는 그래프를 주의 깊게 관찰하면, 이 알고리즘에는 다음과 같은 특성이 있음을 알 수 있습니다.
- 완전히 겹치는 '코인 총합'과 '슬롯 0' 그래프
하늘색의 '코인 총합' 실선과 주황색의 '슬롯 머신 0' 점선이 시작 직후부터 끝까지 완벽하게 일치하고 있습니다. 이는 AI가 1만 스텝 처리 과정 내내 슬롯 0 레버만을 선택했다는 증거입니다. - 사라진 '슬롯 1'과 바닥을 기는 '슬롯 2'
그래프 상에는 녹색의 '슬롯 머신 1' 점선이 보이지 않으며, 빨간색의 '슬롯 머신 2' 점선은 가장 아래쪽인 '枚数 0'의 바닥에 붙어 있는 것처럼 보입니다. 이 역시 AI가 '슬롯 0'만을 편애하며 계속 사용한 결과, '슬롯 1'과 '슬롯 2' 모두 한 번도 레버를 당기지 못해 획득 매수 0매로 그래프가 완전히 겹쳐져서 보이지 않게 된 것입니다. 그 결과, '슬롯 1'의 녹색 그래프는 이후에 그려진 '슬롯 2'의 빨간색 그래프에 의해 완전히 가려져서 전혀 보이지 않게 되었습니다.
이처럼 그래프로 만들어 봄으로써, 사전에 실험(탐색)을 소홀히 한 탐욕법이 처음 당첨된 슬롯 머신에 집착하고 다른 슬롯 머신들을 완전히 무시한다는 속성이 한눈에 명확해졌습니다.
두 알고리즘의 마지막 에피소드 데이터를 기반으로, '1 스텝당 획득 코인의 평균 매수'가 시간 경과(스텝 수)에 따라 어떻게 변화했는지를 시각화합니다.
완전 랜덤(탐색 전용)에서의 이 그래프의 상세한 해석 방법은 이전 기사를 참고해 주십시오.
random_agent.draw_cumulative_reward_per_step()
greedy_agent.draw_cumulative_reward_per_step()
실행 결과
실행 결과로부터 다음과 같은 사실을 알 수 있습니다.
- 완전 랜덤(탐색 전용): 시작 직후의 큰 변동성이 가라앉은 후에는 모든 슬롯 머신의 평균 확률인 0.5 라인으로 수렴합니다. - 탐욕법(활용 전용): 완전 랜덤보다 더 낮은 위치에 있는, 슬롯 0의 실제 실력인 0.3 라인으로 수렴합니다.
누적 보상 그래프에서는 우상향으로 길게 늘어져 있어 실력 차이가 눈에 잘 띄지 않았지만, 이 '1회당 평균값'으로 변환한 그래프를 나란히 놓음으로써, 두 알고리즘이 범하는 치명적인 약점이 그래프에서 명확하게 드러나게 됩니다.
- 완전 랜덤의 한계
아무리 스텝 수를 거듭하여 데이터(경험)를 축적하더라도, 그것을 이후 머신 선택에 전혀 활용하지 못합니다. 따라서 그래프 선은 신의 상한선(0.7)을 향해 우상향으로 성장하는 것이 아니라, '당첨 평균(0.5)'에 완전히 고정된 채 수평하게 이어집니다. - 탐욕법의 자멸
최종 에피소드에서의 탐욕법은 처음에 슬롯 0에서 당첨을 뽑아버린 바람에, 최악의 꽝 기계인 '슬롯 0'를 평생 계속 돌리게 됩니다. 따라서 1 스텝당 획득 코인은 전체 평균 확률인 0.5(하늘색 그래프)보다 크게 낮은, 슬롯 0의 실제 확률인 0.3에 딱 붙어 버립니다.
사전 실험(탐색)을 소홀히 하고 눈앞의 이익에 뛰어든 결과, 완전 랜덤보다 압도적으로 손해를 보고 자멸할 수 있다는 탐욕법의 결점이 이 두 그래프의 차이를 통해 명확하게 드러났습니다.
두 알고리즘의 마지막 에피소드 데이터를 기반으로, 시간 경과(스텝 수)에 따라 '각 슬롯 머신이 몇 번 선택되었는지'라는 누적 선택 횟수의 추이를 비교합니다.
완전 랜덤(탐색 전개)의 경우, 이 그래프를 상세하게 해석하는 방법은 이전 기사를 참조해 주십시오.
random_agent.draw_selectnum()
greedy_agent.draw_selectnum()
실행 결과
실행 결과로부터 다음 사항을 알 수 있습니다.
- 완전 랜덤(탐색 전개): 모든 슬롯 머신의 그래프가 거의 일직선상에 겹쳐지며 균등하게 우상향합니다. -
탐욕법(활용 전개): 하늘색의 '슬롯 0' 한 개만 급각도로 우상향하며 독주하고, 그 외는 완전히 바닥인 0에 붙어 수평을 유지합니다.
지금까지의 수치 분석이나 수식적 고찰에서 언급해 온, '완전 랜덤은 모두를 평등하게 취급한다'는 특징과 '탐욕법은 첫 경험을 맹신한다'는 대조적인 행동 특성이 그래프 선의 기울기로 시각화되었습니다.
- 완전 랜덤(탐색 전개)
3개의 선이 완벽하게 나란한 하나의 직선처럼 보이는 것은, AI가 '편애'를 전혀 하지 않고 1만 스텝까지 모든 기계를 항상 확률 $(rac{1}{3})$로 평등하게 선택했기 때문입니다5. -
탐욕법(활용 전개)
'슬롯 0'만 '편애'되어 계속 선택된 결과, 하늘색의 '슬롯 0'만 총 스텝 수와 같은 '1만 번'을 향해 곧게 뻗어 나갑니다6.
과거에 아무리 유망한 데이터가 쌓이려고 해도 정보를 전혀 활용하지 않는 완전 랜덤과, 단 한 번의 당첨 경험으로 사고를 정지시켜 미지의 가능성을 닫아버리는 탐욕법이라는, 양자가 가진 극단적인 할당의 폐해(트레이드오프)가 이 극단적인 직선 형태에 나타나 있습니다.
두 알고리즘의 마지막 에피소드 데이터를 기반으로, 시간 경과(스텝 수)에 따라 AI가 머릿속에서 추정하는 '각 기계 당첨 확률의 추정치(표본 평균)'가 어떻게 변화했는지 비교합니다.
완전 랜덤(탐색 전개)의 경우, 이 그래프를 상세하게 해석하는 방법은 이전 기사를 참조해 주십시오.
random_agent.draw_estimated_odds_of_arm()
greedy_agent.draw_estimated_odds_of_arm()
실행 결과
실행 결과로부터 다음 사항을 알 수 있습니다.
- 완전 랜덤(탐색 전개): 모든 슬롯 머신의 추정치가 검은 점선으로 그려진 '진정한 당첨 확률(0.3, 0.5, 0.7)'로 수렴해 갑니다. -
탐욕법(활용 전개): 하늘색의 '슬롯 0'만 진정한 확률(0.3)에 수렴하고, 나머지 2대는 완전히 바닥인 0에 붙어 수평을 유지합니다7.
이 그래프를 통해 탐욕법이 '잘못된 선택을 평생 계속할 수 있다'는 원인이 시각적으로 명확하게 보입니다. 탐욕법이 자멸하는 원인은 특정 1대 외의 추정치가 전혀 믿을 수 없게 되고, 그러한 신뢰할 수 없는 데이터를 기반으로 선택을 하기 때문입니다.
- 완전 랜덤(탐색 전개)
모든 슬롯 머신을 완전히 평등하게 계속 당긴 결과, 충분한 실험 데이터(표본)가 모입니다. 이를 통해 대수의 법칙의 수학적 혜택을 최대한 받아 모든 슬롯 머신의 당첨 확률 추정치가 진정한 당첨 확률로 거의 완벽하게 겹쳐지게 됩니다. 답이 거의 100% 보이는 상태를 만들 수 있는 것이 완전 랜덤의 강점이지만, 그 정확한 추정치를 전혀 활용하지 못한다는 치명적인 약점이 있습니다. -
탐욕법(활용 전개)
처음에 당첨된 '슬롯 0'만 편애하여 계속 당겼기 때문에, '슬롯 0'의 확률(0.3)만 올바르게 학습되지만, 나머지 '슬롯 1'과 '슬롯 2'는 한 번도 레버가 당겨지지 않아 확률 추정치가 초기값인 0.0에 머물러 전혀 변하지 않습니다.
탐욕법 AI 내부에는 '슬롯 0 = 확률 0.3', '슬롯 1 = 확률 0', '슬롯 2 = 확률 0'으로 기록되어 있기 때문에, 탐욕법의 규칙(가장 높은 수치를 선택)을 따를 경우 필연적으로 확률 0.3인 '슬롯 0'만 계속 선택할 수밖에 없습니다. '실제로는 더 잘 당기는 슬롯 머신(확률 0.7)이 있을지도 모르는데, 그것을 확인하기 위한 단 한 번의 실험(탐색)조차 거절하고 눈앞의 코인에 뛰어들었기 때문에, 평생 꽝 기계에 묶여 있게 된다'는 탐욕법의 치명적인 약점이 이 바닥에 붙은 두 개의 직선으로 명확해졌습니다.
여기까지는 마지막에 실시된 일회성 우연의 산물인 1 에피소드 결과를 그래프로 그렸습니다. 여기부터는 여러 번의 에피소드 집계 결과를 그래프화하여, 우연에 좌우되지 않는 알고리즘의 본질적인 성질을 시각화하고 비교해 보겠습니다.
먼저 10회 분량의 에피소드(각 1만 스텝)의 '스텝당 획득 코인' 추이를 겹쳐서 그래프를 그립니다. 이를 통해 각 알고리즘이 가진 '결과의 안정성(위험도)'을 한눈에 비교할 수 있습니다.
완전 랜덤(탐색 전념)에서의 이 그래프 상세 해석 방법은 이전 기사를 참고해 주세요.
random_agent.draw_cumulative_rewards(10)
greedy_agent.draw_cumulative_rewards(10)
실행 결과
실행 결과로부터 다음과 같은 것을 알 수 있습니다.
- 완전 랜덤(탐색 전념): 시작 직후의 변동이 가라앉은 후, 10개의 모든 선 그래프가 하나의 두꺼운 다발처럼 되어 평균 확률인 0.5 라인으로 수렴합니다.
- 탐욕법(활용 전념): 10개의 그래프가 하나의 다발을 이루지 않고, 슬롯머신들의 진정한 확률인 0.3, 0.5, 0.7의 세 지점에서 나뉘어 수렴합니다.
이 10개 선을 겹쳐 놓은 그래프를 관찰하면, '완전 랜덤은 품질은 낮지만 변동 없는 안정형(저위험・저수익)'이며, '탐욕법은 일확천금 도박형(고위험・고수익)'이라는 두 방식의 결정적인 위험 특성 차이가 명확해집니다.
- 완전 랜덤(탐색 전념)
몇 번 승부(에피소드)를 다시 하더라도, 1만 스텝이라는 충분한 시도 횟수만 있다면 반드시 최종 점수는 전체 평균 확률인 0.5 근처로 수렴합니다. 대수의 법칙에 의해 운이나 불운의 요소가 완전히 사라지며, '언제든 확실하게(평균인) 0.5의 실력을 안정적으로 발휘한다'는 변동이 적은 성질이 깔끔하게 겹쳐진 선을 통해 명확해졌습니다. 반면, 신의 시점에서 얻을 수 있는 최고 점수인 0.7에는 미치지 못한다는 점에서, 얻을 수 있는 결과가 낮은 품질임도 분명해졌습니다.
- 탐욕법(활용 전념)
10개의 선이 3개의 목표 지점에 달라붙어 있으며, 초기 단계(데이터 부족 단계)에는 어떤 슬롯머신에서 당첨을 했는지라는 '운'만으로 최종적으로 얻게 되는 점수가 결정됩니다. 운 좋게 슬롯 2(확률 0.7)를 뽑으면 신과 같은 최고 점수를 계속 벌어들이지만, 운 나쁘게 슬롯 0(확률 0.3)에 걸리면 최악의 낮은 점수에 갇히게 됩니다. 즉, '운이 좋으면 큰돈을 벌고, 나쁘면 크게 폭망한다'는 결과가 전혀 안정적이지 않은 위험(고위험・고수익)한 전략이라는 것이 시각적으로 명확해졌습니다.
아무리 스텝 수를 늘려 1만 번 레버를 당기게 하더라도, 사전에 탐색을 게을리한 탐욕법은 결과가 에피소드별 운에 완전히 의존하게 됩니다. 극단적인 할당이 가져오는 운에 맡기는 전략이 이 3개의 목표 지점에 분열된 그래프를 통해 명확해졌습니다.
1,000 에피소드라는 방대한 실험 데이터를 집계한 두 알고리즘의 '실력의 진실(기대값 추이)'을 검증합니다.
각각의 실력 변화가 확실하게 전달되도록 개별적으로 표시한 그래프와, 두 그래프를 같은 화면에서 직접 대결시킨 '겹쳐서 표시'한 그래프를 동시에 그렸습니다.
완전 랜덤(탐색 전념)에서의 이 그래프 상세 해석 방법은 이전 기사를 참고해 주세요.
agent_list = [random_agent, greedy_agent]
random_agent.draw_mean_cumulative_reward_by_step()
greedy_agent.draw_mean_cumulative_reward_by_step()
...
실행 결과
실행 결과로부터 다음과 같은 것을 알 수 있습니다.
완전 랜덤(탐색 전념): 시작 직후의 변동이 수그러든 후에는 모든 슬롯머신의 평균 확률인 0.500을 향해 일직선으로 수평하게 수렴합니다.
탐욕법(활용 전념): 완전 랜덤과 마찬가지로, 초반 이후에는 우상향하며 성장하는 것이 아니라, 0.559라는 평균 확률보다 약간 높은 값에서 완전히 수평하게 수렴합니다.
두 가지를 겹쳐 비교한 그래프: 두 그래프 모두 시작 직후의 변동이 수그러든 후에는 전혀 기울기(성장)가 없는 '깨끗한 두 개의 수평선'으로 나란히 놓입니다.
앞서 print_summary 메서드로 출력했던 최종 단계의 수치 데이터(0.500과 0.559) 가 단순한 우연이 아니라, 1만 단계의 여정 거의 모든 곳에서 완전히 고정되어 있었다는 것이 시각적으로 명확해졌습니다.
두 개의 겹쳐진 그래프를 관찰하면, 강화학습의 핵심인 '탐색과 활용의 중요성' 그리고 한쪽에 전념한 알고리즘이 안고 있는 **아무리 많은 시간(단계 수)을 들여도 AI의 실력이 '1밀리미터도 성장하지 않는다'**는 치명적인 결함이 드러납니다.
이 그래프에서 가장 주목해야 할 점은, 두 그래프 모두 변동성이 안정된 후에는 기울기가 완전히 0인 수평선이라는 사실입니다.
완전 랜덤(탐색 전념) '경험을 활용하지 못하는 무계획': 1만 번 레버를 당기는 동안, 중반의 3,000번째이든 후반의 9,000번째이든, AI의 머릿속에는 각 슬롯머신의 진정한 확률(0.3, 0.5, 0.7)을 거의 정확하게 추측할 수 있습니다. 그럼에도 불구하고, 그 막대한 '경험'을 다음 선택에 전혀 활용하지 않고 완전한 랜덤(제비뽑기)으로 계속 당기고 있기 때문에, 실력은 평균인 0.5에서 영원히 향상되지 않습니다.
- **탐욕법(활용 전념) '운빨의 한계치'
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기