n-슬롯 머신이란 강화 학습을 공부하기 처음 시작할 때 "강화 학습이 무엇인가"를 설명하기 위해 가장 흔하게 사용되는 예제이다. 강화 학습의 고급 기법들이 사용되는 건 아니지만 기본 개념을 익히기 좋다.
어떤 문제인가
n-슬롯 머신에서 "슬롯 머신"은 카지노에 있는 슬롯 머신을 가리킨다.

레버를 당기면 일정 확률로 돈이 나오거나 꽝인, 전통적인 도박 게임이다.
그런데 만약 이 기계들을 우리가 제한된 시간 내에 무료로 당길 수 있다고 해보자. 그리고 각 기계들은 각각 일정 비율로 보상이 주어지도록 되어 있는데 그 값이 모두 다르다. 그러니 우리는 레버를 막 당겨 보면서 가장 보상을 많이 주는 기계를 찾아 그 기계의 레버를 계속 당겨야 한다.
그런데 사실 이건 수많은 반복 테스트가 필요하다. 처음 몇번 정도 1번 기계가 돈을 많이 주는 것 같더라도, 확률적인 문제이기 때문에 결국 무한히 당겼을 때 돈을 더 많이 버는 기계는 2번 기계일 수도 있다. 기계가 10개라면? 돈을 가장 많이 주는 기계를 찾는게 꽤나 시간을 많이 써야 할 것이다.
그럼 우리는 로봇에게 이 일을 맡겨보자.
"너가 기계 열나게 당겨봐. 그리고 가장 보상을 많이 받아오도록 해봐."
꽤나 인공지능스럽지 않은가?
사실 강화 학습은 지금은 LLM 때문에 조금은 식었지만 한 때엔 AGI, 즉 "강인공지능"의 강력한 후보군이었다. 사실 지금도 LLM에 회의적인 인공지능 석학들은 강화 학습을 인공지능의 미래라고 보고 있기도 하다.
여하튼, 프로그램을 구현해보자. 고급 파이썬 라이브러리도 필요하지 않고 그냥 numpy만으로 쉽게 구현할 수 있다.
import numpy as np
import matplotlib.pyplot as plt
# 환경 설정
np.random.seed(0)
n_arms = 10
true_rewards = np.random.normal(0, 1, n_arms) # 각 팔의 실제 평균 보상
print("실제 보상:", np.round(true_rewards, 2))
# 하이퍼파라미터
epsilon = 0.1
n_steps = 5000
# 에이전트의 추정
Q = np.zeros(n_arms) # 보상 추정값
counts = np.zeros(n_arms) # 각 팔의 선택 횟수
rewards = []
# 학습 시작
for step in range(n_steps):
# ε-greedy 전략
if np.random.rand() < epsilon:
action = np.random.randint(n_arms) # 무작위 선택
else:
action = np.argmax(Q) # 최대 추정값 선택
# 보상 관측
reward = np.random.normal(true_rewards[action], 1)
rewards.append(reward)
# 추정값 업데이트 (표본 평균)
counts[action] += 1
Q[action] += (reward - Q[action]) / counts[action]
# 평균 보상 그래프
plt.plot(np.cumsum(rewards) / (np.arange(n_steps) + 1))
plt.xlabel("Steps")
plt.ylabel("Average Reward")
plt.title(f"ε = {epsilon}")
plt.grid()
plt.show()
실행을 해보면 아래와 같은 결과가 나온다.

코드를 찬찬히 살펴보면 강화 학습의 기본 개념을 이해할 수 있다.
우선 코드에서 보시다 시피 우리는 10개의 레버(=arm)을 이용한다. 즉 기계가 10개가 있다고 생각하면 된다.
그리고 각각의 기계와 각각의 보상을 담을 배열 2개를 모두 0으로 초기화 한다.
이러면 둘 다 [0,0,0,0,0,0,0,0,0,0] 과 같은 배열이 생긴다.
그리고 우리가 정한 횟수의 루프를 돌면서 다음의 동작을 반복한다.
else 부터 보면, 지금까지 우리가 가진 데이터를 기반으로 가장 보상이 좋았던 기계를 선택한다.
하지만, 랜덤하게, 약 10%의 확률로 다른 기계도 돌려 본다.
여기서 입실론(ε)이 이 랜덤성을 결정하는 확률로 사용된다. 0.1이면 10%, 0.2면 20%이다. 뭐가 좋은지는 우리도 모른다. 일종이 하이퍼 파라미터이다.
기계가 선택되면 보상을 받고 지금까지 받은 보상의 평균을 업데이트 해나간다.
예를 들어보자.
횟수 = [0,0,0,0,0,0,0,0,0,0]
평균보상 = [0,0,0,0,0,0,0,0,0,0]
만약 1번 기계가 선택되었다. 그리고 10의 보상을 받았다.
그럼 배열은 아래와 같이 바뀐다.
횟수 = [1,0,0,0,0,0,0,0,0,0]
평균보상 = [10,0,0,0,0,0,0,0,0,0]
평균 보상이 높은 것을 기본적으로 선택하기 때문에 이제부턴 1번 기계가 선택될 확률이 90%이다.
또 1번이 선택되었다. 그리고 6의 보상을 받았다.
만약 1번 기계가 선택되었다. 그리고 10의 보상을 받았다.
그럼 배열은 아래와 같이 바뀐다.
횟수 = [2,0,0,0,0,0,0,0,0,0]
평균보상 = [8,0,0,0,0,0,0,0,0,0]
그리고 이번엔 3번 기계가 선택되었다. 그리고 20의 보상을 받았다.
횟수 = [2,0,1,0,0,0,0,0,0,0]
평균보상 = [8,0,20,0,0,0,0,0,0,0]
이젠 3번 기계의 평균 보상이 가장 크기 때문에 3번 기계가 다시 선택될 확률이 90%로 바뀌었다.
좀 소모적으로 보이지만 이걸 5000번을 반복하고 나면 신기하게 어떤 기계가 가장 보상이 높은지 판단이 된다.
우리가 본 결과 그래프가 그것이다.

기계의 실제 보상값은 위 배열과 같았다. 즉 4번 기계의 2.24가 가장 높은 보상이다. 그리고 우리의 인공지능이 결국 수렴해낸 값도 2.24에 근접한다. 그리고 우리 데이터엔 평균 보상이 2.24에 가까운 것이 4번 기계라는 것을 안다.
결국 수많은 반복을 통해 우리 인공지능은 가장 보상이 좋은 기계를 찾아낸 것이다.
이 다음엔 좀 더 복잡한 예제로 강화학습을 더 깊게 이해해보자.
'IT 이론 공부' 카테고리의 다른 글
| 간단한 코드로 이해하는 강화학습 #3 Grid World-2 (정책, 가치 함수, 학습) (5) | 2025.07.09 |
|---|---|
| 간단한 코드로 이해하는 강화학습 #2 Grid World-1 (에이전트, 환경, 에피소드) (1) | 2025.07.09 |
| [데이터 시리즈 #4] 옵트인과 옵트아웃 이해하기 (3) | 2025.03.31 |
| [데이터 시리즈 #3] 데이터 활용과 개인정보 보호 (0) | 2025.03.31 |
| AVL 트리 (심화) - 더블 로테이션 (0) | 2025.03.12 |