강화학습
slot machine ( E-greedy 정책 )
정지홍
2024. 11. 26. 10:48
슬롯 머신
- 슬롯머신 클래스 구현
import numpy as np
class Slot_machine:
def __init__(self , arms=7): # arms는 슬롯 머신의 갯수이다.
print(f'설정한 슬롯머신의 갯수 : {arms}')
self.rates = np.random.rand(arms) # 슬롯머신의 각각의 승률을 무작위로 설정. np.random.rand로 배열 생성
self.arms=arms
print(f'슬롯 머신들의 승률 : {self.rates}')
def play(self , arm): # arm은 몇번째 슬롯 머신을 플레이 할지 설정한다.
rate = self.rates[arm]
if rate>np.random.rand():
return 1
else:
return 0
slot = Slot_machine(5)
for i in range(3):
print(slot.play(3))

에이전트
- 이는 기본적인 에이전트 알고리즘이다.

- 에이전트 클래스 구현
# epsilon-greepy policy
class Agent:
def __init__(self , epsilon , machines=10):
self.epsilon = epsilon # 무작위로 행동할 확률 ( 탐색 확률 )
self.Qs = np.zeros(machines) # 가치 추정치를 0으로 초기화시킨 배열 생성
self.ns = np.zeros(machines) # 각 슬롯 머신의 플레이 횟수를 0으로 초기화
def update( self , action , reward ): # 슬롯 머신의 가치 추정
self.ns[ action ] += 1
self.Qs[ action ] += ( reward - self.Qs[action] ) / self.ns[action]
def get_action(self): # epsilon - greedy 정책으로, 행동을 선택하는 경우
if np.random.rand() < self.epsilon: # 탐색하는 경우
return np.random.randint( 0 , len(self.Qs ) )
return np.argmax(self.Qs) # 활용하는 경우. 현재 Qs에서 값이 가장 큰 원소의 인덱스를 가져옴
위의 에이전트를 가지고 슬롯머신 플레이
import matplotlib.pyplot as plt
steps = 1000
epsilon = 0.1
machines = 10
slot = Slot_machine(machines)
agent = Agent(epsilon)
sum_of_reward = 0
rewards = [] # 보상의 합
rates = [] # 승률
for step in range( 0 , steps ):
action = agent.get_action() # 행동을 선택
reward = slot.play(action) # 슬롯 머신을 플레이하고 보상을 받는다.
agent.update( action , reward ) # 행동과 보상을 통해서 학습
sum_of_reward += reward
rewards.append(sum_of_reward) # 현재까지의 보상의 합을 저장
rates.append( sum_of_reward / (step+1) ) # 현재까지의 승률을 저장
print(sum_of_reward)


위의 과정은 단 한번만 실험을 하였다.
하지만 강화학습 알고리즘은 무작위성으로 인해 한 번의 실험만으로 판단하는 것은 의미가 없다.
(실제로 위의 에이전트를 실행하면 어떤 경우에는 승률이 0.5인 반면에, 어떤 경우에는 0.9가 넘는다.)
그래서 같은 실험을 여러번 반복하여, 평균을 구하는 방식으로 알아봐야 한다.
=> 위의 슬롯머신 에이전트를 200번 실행하여 평균을 내보자.
runs = 200
steps = 1000
epsilon = 0.1
machines = 10
all_rates = np.zeros( ( runs , steps ) )
for i in range ( 0,runs):
slot = Slot_machine( machines )
agent = Agent(epsilon)
sum_of_reward = 0
rates = []
for j in range( 0,steps ):
action = agent.get_action()
reward = slot.play(action)
agent.update(action , reward)
sum_of_reward += reward
rates.append( sum_of_reward / (j+1 ) )
all_rates[i] = rates
avg = np.average( all_rates , axis=0 )
plt.ylabel('rates')
plt.xlabel('steps')
plt.plot(avg)
plt.show()

- 위의 과정에서 epsilon값을 다르게 0.01 , 0.1 , 0.3해보면 각각 결과가 다를 것이다.
- 아마도 0.3은 급격히 상승하다가 꺽일것이며, 0.01은 변화률이 작을 것이다.
위를 보면 결국에는 적절한 탐색비율을 설정해야함을 알수있다. - 즉, '활용과 탐색의 균형'이 중요
- 아마도 0.3은 급격히 상승하다가 꺽일것이며, 0.01은 변화률이 작을 것이다.