Reinforcement Learning 1

Author

차상진

Published

June 2, 2024

1. Imports

import numpy as np

2. Game1 : Bandit게임

A. 게임설명 및 원시코드

- 버튼0 -> 1의 보상 , 버튼2 -> 10의 보상

- 처음에는 아는 것이 없으니 아무거나 눌러봐야겠다.

action_space = [0,1]
action = np.random.choice(action_space)
action
1
  • action_spaceaction이라는 용어를 기억

- 버튼을 누른 행위에 대한 보상 구현

reward = 1 if action == 0 else 10
reward
10

- 아무 버튼이나 10번 눌러보며 데이터 쌓기

action_space = [0,1]
for l in range(10):
    action = np.random.choice(action_space)
    reward = 1 if action == 0 else 10
    print(action , reward)
1 10
0 1
0 1
0 1
1 10
0 1
0 1
1 10
0 1
1 10

- 사람이라면 1을 눌러야겠다는 생각을 함. 그런데 컴퓨터가 이렇게 생각하게 어떻게 만들지? 생각하는 과정을 연구한 것이 강화학습이다

# 꺠달은 사람
action_space = ['버튼0','버튼1']
for _ in range(10):
    action = '버튼1'
    reward = 1 if action == "버튼0" else 10
    print(action,reward)
버튼1 10
버튼1 10
버튼1 10
버튼1 10
버튼1 10
버튼1 10
버튼1 10
버튼1 10
버튼1 10
버튼1 10

- 강화학습 : 환경(enviornment)를 이해 -> 에이전트(agent)가 행동(action)을 결정

  • 게임클리어조건: (1) 20번은 그냥 진행 (2) 최근 20번의 보상의 평균이 9.5점 이상이면 게임이 클리어 되었다고 생각하자.

- 원시코드1 : 환경을 이해하지 못한 에이전트 - 게임 클리어 불가능

action_space = [0,1]
actions = []
rewards = []
for t in range(1,51):
    action = np.random.choice(action_space)
    reward = 1 if action == 0 else 10
    actions.append(action)
    rewards.append(reward)

    print(
        f"시도:{t}\t"
        f"행동:{action}\t"
        f"보상:{reward}\t"
        f"최근20번보상평균:{np.mean(rewards[-20:]):.4f}\t"
    )

    if t<20:
        pass
    elif t==20:
        print('--')
    else:
        if np.mean(rewards[-20:]) > 9.5:
            print('Game Clear')
            break
시도:1    행동:1    보상:10   최근20번보상평균:10.0000   
시도:2    행동:0    보상:1    최근20번보상평균:5.5000    
시도:3    행동:1    보상:10   최근20번보상평균:7.0000    
시도:4    행동:0    보상:1    최근20번보상평균:5.5000    
시도:5    행동:0    보상:1    최근20번보상평균:4.6000    
시도:6    행동:1    보상:10   최근20번보상평균:5.5000    
시도:7    행동:0    보상:1    최근20번보상평균:4.8571    
시도:8    행동:0    보상:1    최근20번보상평균:4.3750    
시도:9    행동:0    보상:1    최근20번보상평균:4.0000    
시도:10   행동:1    보상:10   최근20번보상평균:4.6000    
시도:11   행동:0    보상:1    최근20번보상평균:4.2727    
시도:12   행동:0    보상:1    최근20번보상평균:4.0000    
시도:13   행동:0    보상:1    최근20번보상평균:3.7692    
시도:14   행동:0    보상:1    최근20번보상평균:3.5714    
시도:15   행동:0    보상:1    최근20번보상평균:3.4000    
시도:16   행동:1    보상:10   최근20번보상평균:3.8125    
시도:17   행동:0    보상:1    최근20번보상평균:3.6471    
시도:18   행동:0    보상:1    최근20번보상평균:3.5000    
시도:19   행동:0    보상:1    최근20번보상평균:3.3684    
시도:20   행동:1    보상:10   최근20번보상평균:3.7000    
--
시도:21   행동:1    보상:10   최근20번보상평균:3.7000    
시도:22   행동:0    보상:1    최근20번보상평균:3.7000    
시도:23   행동:1    보상:10   최근20번보상평균:3.7000    
시도:24   행동:0    보상:1    최근20번보상평균:3.7000    
시도:25   행동:0    보상:1    최근20번보상평균:3.7000    
시도:26   행동:0    보상:1    최근20번보상평균:3.2500    
시도:27   행동:0    보상:1    최근20번보상평균:3.2500    
시도:28   행동:0    보상:1    최근20번보상평균:3.2500    
시도:29   행동:1    보상:10   최근20번보상평균:3.7000    
시도:30   행동:1    보상:10   최근20번보상평균:3.7000    
시도:31   행동:1    보상:10   최근20번보상평균:4.1500    
시도:32   행동:0    보상:1    최근20번보상평균:4.1500    
시도:33   행동:0    보상:1    최근20번보상평균:4.1500    
시도:34   행동:0    보상:1    최근20번보상평균:4.1500    
시도:35   행동:1    보상:10   최근20번보상평균:4.6000    
시도:36   행동:0    보상:1    최근20번보상평균:4.1500    
시도:37   행동:1    보상:10   최근20번보상평균:4.6000    
시도:38   행동:1    보상:10   최근20번보상평균:5.0500    
시도:39   행동:0    보상:1    최근20번보상평균:5.0500    
시도:40   행동:0    보상:1    최근20번보상평균:4.6000    
시도:41   행동:0    보상:1    최근20번보상평균:4.1500    
시도:42   행동:0    보상:1    최근20번보상평균:4.1500    
시도:43   행동:0    보상:1    최근20번보상평균:3.7000    
시도:44   행동:0    보상:1    최근20번보상평균:3.7000    
시도:45   행동:1    보상:10   최근20번보상평균:4.1500    
시도:46   행동:0    보상:1    최근20번보상평균:4.1500    
시도:47   행동:0    보상:1    최근20번보상평균:4.1500    
시도:48   행동:1    보상:10   최근20번보상평균:4.6000    
시도:49   행동:1    보상:10   최근20번보상평균:4.6000    
시도:50   행동:0    보상:1    최근20번보상평균:4.1500    

- 원시코드2 : 환경을 깨달은 에이전트 - 게임 클리어

action_space = [0,1]
actions = []
rewards = []
for t in range(1,51):
    action = 1
    reward = 1 if action == 0 else 10
    actions.append(action)
    rewards.append(reward)

    print(
        f"시도:{t}\t"
        f"행동:{action}\t"
        f"보상:{reward}\t"
        f"최근20번보상평균:{np.mean(rewards[-20:]):.4f}\t"
    )

    if t<20:
        pass
    elif t==20:
        print('--')
    else:
        if np.mean(rewards[-20:]) > 9.5:
            print('Game Clear')
            break
시도:1    행동:1    보상:10   최근20번보상평균:10.0000   
시도:2    행동:1    보상:10   최근20번보상평균:10.0000   
시도:3    행동:1    보상:10   최근20번보상평균:10.0000   
시도:4    행동:1    보상:10   최근20번보상평균:10.0000   
시도:5    행동:1    보상:10   최근20번보상평균:10.0000   
시도:6    행동:1    보상:10   최근20번보상평균:10.0000   
시도:7    행동:1    보상:10   최근20번보상평균:10.0000   
시도:8    행동:1    보상:10   최근20번보상평균:10.0000   
시도:9    행동:1    보상:10   최근20번보상평균:10.0000   
시도:10   행동:1    보상:10   최근20번보상평균:10.0000   
시도:11   행동:1    보상:10   최근20번보상평균:10.0000   
시도:12   행동:1    보상:10   최근20번보상평균:10.0000   
시도:13   행동:1    보상:10   최근20번보상평균:10.0000   
시도:14   행동:1    보상:10   최근20번보상평균:10.0000   
시도:15   행동:1    보상:10   최근20번보상평균:10.0000   
시도:16   행동:1    보상:10   최근20번보상평균:10.0000   
시도:17   행동:1    보상:10   최근20번보상평균:10.0000   
시도:18   행동:1    보상:10   최근20번보상평균:10.0000   
시도:19   행동:1    보상:10   최근20번보상평균:10.0000   
시도:20   행동:1    보상:10   최근20번보상평균:10.0000   
--
시도:21   행동:1    보상:10   최근20번보상평균:10.0000   
Game Clear

B. 수정1 : Env구현

- Bandit 클래스 선언 + .step()구현

class Bandit:
    def step(self,agent_action):
        reward = 1 if agent_action == 0 else 10
        return reward
env = Bandit()
action_space = [0,1]
actions = []
rewards = []
for t in range(1,51):
    action = np.random.choice(action_space)
    reward = env.step(action)
    actions.append(action)
    rewards.append(reward)

    print(
        f"시도:{t}\t"
        f"행동:{action}\t"
        f"보상:{reward}\t"
        f"최근20번보상평균:{np.mean(rewards[-20:]):.4f}\t"
    )
    if t<20:
        pass 
    elif t==20:
        print("--")
    else: 
        if np.mean(rewards[-20:]) > 9.5:
            print("Game Clear")
            break
시도:1    행동:1    보상:10   최근20번보상평균:10.0000   
시도:2    행동:1    보상:10   최근20번보상평균:10.0000   
시도:3    행동:1    보상:10   최근20번보상평균:10.0000   
시도:4    행동:1    보상:10   최근20번보상평균:10.0000   
시도:5    행동:1    보상:10   최근20번보상평균:10.0000   
시도:6    행동:0    보상:1    최근20번보상평균:8.5000    
시도:7    행동:0    보상:1    최근20번보상평균:7.4286    
시도:8    행동:0    보상:1    최근20번보상평균:6.6250    
시도:9    행동:1    보상:10   최근20번보상평균:7.0000    
시도:10   행동:0    보상:1    최근20번보상평균:6.4000    
시도:11   행동:1    보상:10   최근20번보상평균:6.7273    
시도:12   행동:0    보상:1    최근20번보상평균:6.2500    
시도:13   행동:1    보상:10   최근20번보상평균:6.5385    
시도:14   행동:0    보상:1    최근20번보상평균:6.1429    
시도:15   행동:1    보상:10   최근20번보상평균:6.4000    
시도:16   행동:0    보상:1    최근20번보상평균:6.0625    
시도:17   행동:1    보상:10   최근20번보상평균:6.2941    
시도:18   행동:1    보상:10   최근20번보상평균:6.5000    
시도:19   행동:0    보상:1    최근20번보상평균:6.2105    
시도:20   행동:0    보상:1    최근20번보상평균:5.9500    
--
시도:21   행동:1    보상:10   최근20번보상평균:5.9500    
시도:22   행동:1    보상:10   최근20번보상평균:5.9500    
시도:23   행동:1    보상:10   최근20번보상평균:5.9500    
시도:24   행동:0    보상:1    최근20번보상평균:5.5000    
시도:25   행동:1    보상:10   최근20번보상평균:5.5000    
시도:26   행동:0    보상:1    최근20번보상평균:5.5000    
시도:27   행동:1    보상:10   최근20번보상평균:5.9500    
시도:28   행동:0    보상:1    최근20번보상평균:5.9500    
시도:29   행동:1    보상:10   최근20번보상평균:5.9500    
시도:30   행동:0    보상:1    최근20번보상평균:5.9500    
시도:31   행동:1    보상:10   최근20번보상평균:5.9500    
시도:32   행동:1    보상:10   최근20번보상평균:6.4000    
시도:33   행동:1    보상:10   최근20번보상평균:6.4000    
시도:34   행동:0    보상:1    최근20번보상평균:6.4000    
시도:35   행동:0    보상:1    최근20번보상평균:5.9500    
시도:36   행동:1    보상:10   최근20번보상평균:6.4000    
시도:37   행동:1    보상:10   최근20번보상평균:6.4000    
시도:38   행동:1    보상:10   최근20번보상평균:6.4000    
시도:39   행동:0    보상:1    최근20번보상평균:6.4000    
시도:40   행동:0    보상:1    최근20번보상평균:6.4000    
시도:41   행동:0    보상:1    최근20번보상평균:5.9500    
시도:42   행동:0    보상:1    최근20번보상평균:5.5000    
시도:43   행동:1    보상:10   최근20번보상평균:5.5000    
시도:44   행동:1    보상:10   최근20번보상평균:5.9500    
시도:45   행동:1    보상:10   최근20번보상평균:5.9500    
시도:46   행동:0    보상:1    최근20번보상평균:5.9500    
시도:47   행동:0    보상:1    최근20번보상평균:5.5000    
시도:48   행동:0    보상:1    최근20번보상평균:5.5000    
시도:49   행동:0    보상:1    최근20번보상평균:5.0500    
시도:50   행동:0    보상:1    최근20번보상평균:5.0500    

C. 수정2 : Agent구현 (인간지능)

- Agent 클래스 설계

  • 액션을 하고, 본인의 행동과 환경에서 받은 reward를 기억
  • .act()함수와 .save_experience()함수 구현
class Agent:
    def __init__(self):
        self.action_space = [0,1]
        self.action = None
        self.reward = None
        self.actions = []
        self.rewards = []
    def act(self):
        self.action = 1
    def save_experience(self):
        self.actions.append(self.action)
        self.rewards.append(self.reward)

시점0 : init

agent = Agent()
env = Bandit()
agent.action, agent.reward, agent.actions, agent.rewards
(None, None, [], [])

시점1 : agent가 action을 선택

agent.act()
agent.action, agent.reward, agent.actions, agent.rewards
(1, None, [], [])

시점2: env가 agent에게 보상을 줌

agent.reward = env.step(agent.action)
agent.action, agent.reward, agent.actions, agent.rewards
(1, 10, [], [])

시점3: 경험을 저장

agent.save_experience()
agent.action, agent.reward, agent.actions, agent.rewards
(1, 10, [1], [10])

-전체코드-

env = Bandit()
agent = Agent()
for t in range(1,51):
    agent.act()
    agent.reward = env.step(agent.action)
    agent.save_experience()

    print(
        f"시도:{t}\t"
        f"행동:{agent.action}\t"
        f"보상:{agent.reward}\t"
        f"최근20번보상평균:{np.mean(agent.rewards[-20:]):.4f}\t"
    )
    if t<20:
        pass 
    elif t==20:
        print("--")
    else: 
        if np.mean(agent.rewards[-20:]) > 9.5:
            print("Game Clear")
            break    
시도:1    행동:1    보상:10   최근20번보상평균:10.0000   
시도:2    행동:1    보상:10   최근20번보상평균:10.0000   
시도:3    행동:1    보상:10   최근20번보상평균:10.0000   
시도:4    행동:1    보상:10   최근20번보상평균:10.0000   
시도:5    행동:1    보상:10   최근20번보상평균:10.0000   
시도:6    행동:1    보상:10   최근20번보상평균:10.0000   
시도:7    행동:1    보상:10   최근20번보상평균:10.0000   
시도:8    행동:1    보상:10   최근20번보상평균:10.0000   
시도:9    행동:1    보상:10   최근20번보상평균:10.0000   
시도:10   행동:1    보상:10   최근20번보상평균:10.0000   
시도:11   행동:1    보상:10   최근20번보상평균:10.0000   
시도:12   행동:1    보상:10   최근20번보상평균:10.0000   
시도:13   행동:1    보상:10   최근20번보상평균:10.0000   
시도:14   행동:1    보상:10   최근20번보상평균:10.0000   
시도:15   행동:1    보상:10   최근20번보상평균:10.0000   
시도:16   행동:1    보상:10   최근20번보상평균:10.0000   
시도:17   행동:1    보상:10   최근20번보상평균:10.0000   
시도:18   행동:1    보상:10   최근20번보상평균:10.0000   
시도:19   행동:1    보상:10   최근20번보상평균:10.0000   
시도:20   행동:1    보상:10   최근20번보상평균:10.0000   
--
시도:21   행동:1    보상:10   최근20번보상평균:10.0000   
Game Clear

D. 수정3: Agent 구현 (인공지능)

- 지금까지 풀이의 한계 - 사실 강화학습은 환경을 이해 -> 행동을 결정 과정에서 ->의 과정을 수식화 한 것 - 그런데 지금까지는 환경을 파악하면 인간의 지능으로 코드를 수정했으므로 기계가 스스로 생각했다고 할 수 없다.

- Agent가 데이터를 보고 스스로 학습할 수 있도록 설계 - 부제: agent.learn()을 설계하자

  1. 데이터를 모아서 q_table을 만든다.
  2. q_table을 바탕으로 적절한 정책(=policy)를 설정한다.
  • \((\frac{q_0}{q_0+q_1} , \frac{q_1}{q_0+q_1})\)으로 생각하면 될 것 같다.

- q_table을 계산하는 코드 예시

agent.actions = [0, 1, 1,  0, 1,   0, 0] 
agent.rewards = [1, 9, 10, 1, 9.5, 1, 1.2] 
actions = np.array(agent.actions)
rewards = np.array(agent.rewards)
q0 , q1 = np.mean(rewards[actions == 0]) , np.mean(rewards[actions == 1])
q_table = np.array([q0,q1])
q_table
array([1.05, 9.5 ])
prob = q_table / q_table.sum()
agent.action = np.random.choice(action_space , p = prob)
agent.action
0

- 최종코드 정리

class Agent:
    def __init__(self):
        self.action_space = [0,1]
        self.action = None 
        self.reward = None
        self.actions = []
        self.rewards = []
        self.q_table = np.array([0.001,0.001])
        self.n_experience = 0 
    def act(self):
        if self.n_experience <= 20:
            self.action = np.random.choice(self.action_space)
        else:
            prob = q_table / q_table.sum()
            self.action = np.random.choice(self.action_space , p=prob)
    def save_experience(self):
        self.actions.append(self.action)
        self.rewards.append(self.reward)
        self.n_experience = self.n_experience + 1 
    def learn(self):
        if self.n_experience < 20:
            pass 
        else: 
            actions = np.array(self.actions)
            rewards = np.array(self.rewards)      
            q0,q1 = rewards[actions==0].mean(), rewards[actions==1].mean()
            self.q_table = np.array([q0,q1])
env = Bandit()
agent = Agent()
for t in range(1,51):
    # step1: 행동
    agent.act()
    # step2: 보상
    agent.reward = env.step(agent.action)
    # step3: 저장 & 학습
    agent.save_experience()
    agent.learn()    
    #--#
    print(
        f"시도:{t}\t"
        f"행동:{agent.action}\t"
        f"보상:{agent.reward}\t"
        f"최근20번보상평균:{np.mean(agent.rewards[-20:]):.4f}\t"
    )
    if t<20:
        pass 
    elif t==20:
        print("--")
    else: 
        if np.mean(agent.rewards[-20:]) > 9.5:
            print("Game Clear")
            break    
시도:1    행동:1    보상:10   최근20번보상평균:10.0000   
시도:2    행동:1    보상:10   최근20번보상평균:10.0000   
시도:3    행동:1    보상:10   최근20번보상평균:10.0000   
시도:4    행동:1    보상:10   최근20번보상평균:10.0000   
시도:5    행동:1    보상:10   최근20번보상평균:10.0000   
시도:6    행동:0    보상:1    최근20번보상평균:8.5000    
시도:7    행동:1    보상:10   최근20번보상평균:8.7143    
시도:8    행동:0    보상:1    최근20번보상평균:7.7500    
시도:9    행동:0    보상:1    최근20번보상평균:7.0000    
시도:10   행동:1    보상:10   최근20번보상평균:7.3000    
시도:11   행동:0    보상:1    최근20번보상평균:6.7273    
시도:12   행동:0    보상:1    최근20번보상평균:6.2500    
시도:13   행동:0    보상:1    최근20번보상평균:5.8462    
시도:14   행동:0    보상:1    최근20번보상평균:5.5000    
시도:15   행동:0    보상:1    최근20번보상평균:5.2000    
시도:16   행동:0    보상:1    최근20번보상평균:4.9375    
시도:17   행동:1    보상:10   최근20번보상평균:5.2353    
시도:18   행동:1    보상:10   최근20번보상평균:5.5000    
시도:19   행동:0    보상:1    최근20번보상평균:5.2632    
시도:20   행동:1    보상:10   최근20번보상평균:5.5000    
--
시도:21   행동:0    보상:1    최근20번보상평균:5.0500    
시도:22   행동:1    보상:10   최근20번보상평균:5.0500    
시도:23   행동:1    보상:10   최근20번보상평균:5.0500    
시도:24   행동:1    보상:10   최근20번보상평균:5.0500    
시도:25   행동:1    보상:10   최근20번보상평균:5.0500    
시도:26   행동:1    보상:10   최근20번보상평균:5.5000    
시도:27   행동:1    보상:10   최근20번보상평균:5.5000    
시도:28   행동:1    보상:10   최근20번보상평균:5.9500    
시도:29   행동:1    보상:10   최근20번보상평균:6.4000    
시도:30   행동:1    보상:10   최근20번보상평균:6.4000    
시도:31   행동:1    보상:10   최근20번보상평균:6.8500    
시도:32   행동:1    보상:10   최근20번보상평균:7.3000    
시도:33   행동:1    보상:10   최근20번보상평균:7.7500    
시도:34   행동:1    보상:10   최근20번보상평균:8.2000    
시도:35   행동:0    보상:1    최근20번보상평균:8.2000    
시도:36   행동:1    보상:10   최근20번보상평균:8.6500    
시도:37   행동:1    보상:10   최근20번보상평균:8.6500    
시도:38   행동:1    보상:10   최근20번보상평균:8.6500    
시도:39   행동:0    보상:1    최근20번보상평균:8.6500    
시도:40   행동:1    보상:10   최근20번보상평균:8.6500    
시도:41   행동:1    보상:10   최근20번보상평균:9.1000    
시도:42   행동:1    보상:10   최근20번보상평균:9.1000    
시도:43   행동:1    보상:10   최근20번보상평균:9.1000    
시도:44   행동:1    보상:10   최근20번보상평균:9.1000    
시도:45   행동:1    보상:10   최근20번보상평균:9.1000    
시도:46   행동:1    보상:10   최근20번보상평균:9.1000    
시도:47   행동:1    보상:10   최근20번보상평균:9.1000    
시도:48   행동:1    보상:10   최근20번보상평균:9.1000    
시도:49   행동:0    보상:1    최근20번보상평균:8.6500    
시도:50   행동:1    보상:10   최근20번보상평균:8.6500