강화학습

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은 변화률이 작을 것이다.
      위를 보면 결국에는 적절한 탐색비율을 설정해야함을 알수있다.
    • 즉, '활용과 탐색의 균형'이 중요