{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 13wk-2: 강화학습 (1) – Bandit\n",
"\n",
"최규빈 \n",
"2024-05-29\n",
"\n",
"
\n",
"\n",
"# 1. 강의영상\n",
"\n",
"\n",
"\n",
"# 2. Imports"
],
"id": "dfc29062-4442-473d-b2b1-aa17a57e3af3"
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"import numpy as np"
],
"id": "bf93dfa6-34a4-44ab-8bc5-61b02797dc0a"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 3. 강화학습 Intro\n",
"\n",
"`-` 강화학습(대충설명): 어떠한 “(게임)환경”이 있을때 거기서 “뭘 할지”를\n",
"학습하는 과업\n",
"\n",
"`-` 딥마인드: breakout $\\to$ 알파고\n",
"\n",
"- \n",
"\n",
"`-` 강화학습 미래? (이거 잘하면 먹고 살 수 있을까?)\n",
"\n",
"# 4. Game1: `Bandit` 게임\n",
"\n",
"## A. 게임설명 및 원시코드\n",
"\n",
"`-` 문제설명: 두 개의 버튼이 있다. `버튼0`을 누르면 1의 보상을,\n",
"`버튼1`을 누르면 10의 보상을 준다고 가정\n",
"\n",
"`-` 처음에 어떤 행동을 해야 하는가?\n",
"\n",
"- 처음에는 아는게 없음\n",
"- 일단 “아무거나” 눌러보자.\n",
"\n",
"`-` 버튼을 아무거나 누르는 코드를 작성해보자."
],
"id": "00149303-5bc8-4b14-bf78-a69f0a41c852"
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [],
"source": [
"action_space = ['버튼0','버튼1']\n",
"action = np.random.choice(action_space,p=[0.5,0.5])\n",
"action"
],
"id": "b59a9c17-68af-4172-b9a1-a57698c48064"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> `action_space` 와 `action` 이라는 용어를 기억할 것\n",
"\n",
"`-` 버튼을 누른 행위에 따른 보상을 구현하자."
],
"id": "42306d8d-8087-4e7a-9e4f-b45c0df17a59"
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"reward = 1 if action == \"버튼0\" else 10 \n",
"reward"
],
"id": "284085fb-fe92-420f-b1f1-e4e8f8bbe93c"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> `reward`라는 용어를 기억할 것\n",
"\n",
"`-` 아무버튼이나 10번정도 눌러보면서 데이터를 쌓아보자."
],
"id": "e075ba1f-d75e-4b26-b583-99c588fdad5d"
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"버튼1 10\n",
"버튼1 10\n",
"버튼1 10\n",
"버튼0 1\n",
"버튼1 10\n",
"버튼1 10\n",
"버튼0 1\n",
"버튼0 1\n",
"버튼1 10\n",
"버튼0 1"
]
}
],
"source": [
"action_space = ['버튼0','버튼1']\n",
"for _ in range(10):\n",
" action = np.random.choice(action_space)\n",
" reward = 1 if action == \"버튼0\" else 10\n",
" print(action,reward)"
],
"id": "047ed7c3-8764-4ddd-bf0d-d19f819579f4"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`-` 깨달았음: `버튼0`을 누르면 1점을 받고, `버튼1`을 누르면 10점을 받는\n",
"“환경(environment)”이구나? $\\to$ `버튼1`을 누르는 “동작(=action)”을\n",
"해야하는 상황이구나?\n",
"\n",
"- 여기에서 $\\to$의 과정을 체계화 시킨 학문이 강화학습\n",
"\n",
"> `environment`라는 용어를 기억할 것"
],
"id": "6cf2042d-c7f3-4135-ba02-98e953c77f8a"
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"버튼1 10\n",
"버튼1 10\n",
"버튼1 10\n",
"버튼1 10\n",
"버튼1 10\n",
"버튼1 10\n",
"버튼1 10\n",
"버튼1 10\n",
"버튼1 10\n",
"버튼1 10"
]
}
],
"source": [
"action_space = ['버튼0','버튼1']\n",
"for _ in range(10):\n",
" action = '버튼1'\n",
" reward = 1 if action == \"버튼0\" else 10\n",
" print(action,reward)"
],
"id": "7c411be6-725e-4437-861e-637a74d9d9e0"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- 게임 클리어\n",
"\n",
"`-` 강화학습: 환경(environment)을 이해 $\\to$ 에이전트(agent)가\n",
"행동(action)을 결정\n",
"\n",
"> `agent`라는 용어를 기억할 것\n",
"\n",
"***위의 과정이 잘 되었다는 의미로 사용하는 문장들***\n",
"\n",
"- 강화학습이 성공적으로 잘 되었다.\n",
"- 에이전트가 환경의 과제를 완료했다.\n",
"- 에이전트가 환경에서 성공적으로 학습했다.\n",
"- 에이전트가 올바른 행동을 학습했다.\n",
"- 게임 클리어 (비공식)\n",
"\n",
"`-` 게임이 클리어 되었다는 것을 의미하는 지표를 정하고 싶다.\n",
"\n",
"- 첫 생각: `버튼1`을 누르는 순간 게임클리어로 보면 되지 않나?\n",
"- 두번째 생각: 아니지? 우연히 누를수도 있잖아?\n",
"- 게임클리어조건: (1) 20번은 그냥 진행 (2) 최근 20번의 보상의 평균이\n",
" 9.5점 이상이면 게임이 클리어 되었다고 생각하자.[1]\n",
"\n",
"`-` 원시코드1: 환경을 이해하지 못한 에이전트 – 게임을 클리어할 수 없다.\n",
"\n",
"[1] `버튼1`을 눌러야 하는건 맞지만 몇번의 실수는 눈감아 주자는 의미"
],
"id": "92489ae4-ee6e-4605-ad4d-0c96eef45b07"
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"시도:1 행동:0 보상:1 최근20번보상평균:1.0000 \n",
"시도:2 행동:0 보상:1 최근20번보상평균:1.0000 \n",
"시도:3 행동:0 보상:1 최근20번보상평균:1.0000 \n",
"시도:4 행동:1 보상:10 최근20번보상평균:3.2500 \n",
"시도:5 행동:0 보상:1 최근20번보상평균:2.8000 \n",
"시도:6 행동:1 보상:10 최근20번보상평균:4.0000 \n",
"시도:7 행동:0 보상:1 최근20번보상평균:3.5714 \n",
"시도:8 행동:1 보상:10 최근20번보상평균:4.3750 \n",
"시도:9 행동:0 보상:1 최근20번보상평균:4.0000 \n",
"시도:10 행동:0 보상:1 최근20번보상평균:3.7000 \n",
"시도:11 행동:1 보상:10 최근20번보상평균:4.2727 \n",
"시도:12 행동:0 보상:1 최근20번보상평균:4.0000 \n",
"시도:13 행동:1 보상:10 최근20번보상평균:4.4615 \n",
"시도:14 행동:1 보상:10 최근20번보상평균:4.8571 \n",
"시도:15 행동:1 보상:10 최근20번보상평균:5.2000 \n",
"시도:16 행동:0 보상:1 최근20번보상평균:4.9375 \n",
"시도:17 행동:0 보상:1 최근20번보상평균:4.7059 \n",
"시도:18 행동:0 보상:1 최근20번보상평균:4.5000 \n",
"시도:19 행동:1 보상:10 최근20번보상평균:4.7895 \n",
"시도:20 행동:0 보상:1 최근20번보상평균:4.6000 \n",
"--\n",
"시도:21 행동:1 보상:10 최근20번보상평균:5.0500 \n",
"시도:22 행동:0 보상:1 최근20번보상평균:5.0500 \n",
"시도:23 행동:1 보상:10 최근20번보상평균:5.5000 \n",
"시도:24 행동:1 보상:10 최근20번보상평균:5.5000 \n",
"시도:25 행동:0 보상:1 최근20번보상평균:5.5000 \n",
"시도:26 행동:0 보상:1 최근20번보상평균:5.0500 \n",
"시도:27 행동:1 보상:10 최근20번보상평균:5.5000 \n",
"시도:28 행동:1 보상:10 최근20번보상평균:5.5000 \n",
"시도:29 행동:1 보상:10 최근20번보상평균:5.9500 \n",
"시도:30 행동:1 보상:10 최근20번보상평균:6.4000 \n",
"시도:31 행동:1 보상:10 최근20번보상평균:6.4000 \n",
"시도:32 행동:1 보상:10 최근20번보상평균:6.8500 \n",
"시도:33 행동:1 보상:10 최근20번보상평균:6.8500 \n",
"시도:34 행동:1 보상:10 최근20번보상평균:6.8500 \n",
"시도:35 행동:0 보상:1 최근20번보상평균:6.4000 \n",
"시도:36 행동:0 보상:1 최근20번보상평균:6.4000 \n",
"시도:37 행동:1 보상:10 최근20번보상평균:6.8500 \n",
"시도:38 행동:1 보상:10 최근20번보상평균:7.3000 \n",
"시도:39 행동:1 보상:10 최근20번보상평균:7.3000 \n",
"시도:40 행동:1 보상:10 최근20번보상평균:7.7500 \n",
"시도:41 행동:0 보상:1 최근20번보상평균:7.3000 \n",
"시도:42 행동:1 보상:10 최근20번보상평균:7.7500 \n",
"시도:43 행동:0 보상:1 최근20번보상평균:7.3000 \n",
"시도:44 행동:0 보상:1 최근20번보상평균:6.8500 \n",
"시도:45 행동:0 보상:1 최근20번보상평균:6.8500 \n",
"시도:46 행동:1 보상:10 최근20번보상평균:7.3000 \n",
"시도:47 행동:1 보상:10 최근20번보상평균:7.3000 \n",
"시도:48 행동:0 보상:1 최근20번보상평균:6.8500 \n",
"시도:49 행동:0 보상:1 최근20번보상평균:6.4000 \n",
"시도:50 행동:1 보상:10 최근20번보상평균:6.4000 "
]
}
],
"source": [
"action_space = [0,1]\n",
"actions = []\n",
"rewards = []\n",
"for t in range(1,51):\n",
" action = np.random.choice(action_space)\n",
" reward = 1 if action == 0 else 10\n",
" actions.append(action)\n",
" rewards.append(reward)\n",
" #--#\n",
" print(\n",
" f\"시도:{t}\\t\"\n",
" f\"행동:{action}\\t\"\n",
" f\"보상:{reward}\\t\"\n",
" f\"최근20번보상평균:{np.mean(rewards[-20:]):.4f}\\t\"\n",
" )\n",
" if t<20:\n",
" pass \n",
" elif t==20:\n",
" print(\"--\")\n",
" else: \n",
" if np.mean(rewards[-20:]) > 9.5:\n",
" print(\"Game Clear\")\n",
" break"
],
"id": "e4b8d98a-4bfa-492f-b91d-8c90776bd395"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`-` 원시코드2: 환경을 깨달은 에이전트 – 게임클리어"
],
"id": "7e923235-a35f-45f0-b9ef-beadbb4c2e76"
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"시도:1 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:2 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:3 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:4 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:5 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:6 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:7 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:8 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:9 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:10 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:11 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:12 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:13 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:14 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:15 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:16 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:17 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:18 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:19 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:20 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"--\n",
"시도:21 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"Game Clear"
]
}
],
"source": [
"action_space = [0,1]\n",
"actions = []\n",
"rewards = []\n",
"for t in range(1,51):\n",
" action = 1\n",
" reward = 1 if action == 0 else 10\n",
" actions.append(action)\n",
" rewards.append(reward)\n",
" #--#\n",
" print(\n",
" f\"시도:{t}\\t\"\n",
" f\"행동:{action}\\t\"\n",
" f\"보상:{reward}\\t\"\n",
" f\"최근20번보상평균:{np.mean(rewards[-20:]):.4f}\\t\"\n",
" )\n",
" if t<20:\n",
" pass \n",
" elif t==20:\n",
" print(\"--\")\n",
" else: \n",
" if np.mean(rewards[-20:]) > 9.5:\n",
" print(\"Game Clear\")\n",
" break"
],
"id": "19ce8841-5909-49d3-a43d-d361a2950d35"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## B. 수정1: `Env` 구현\n",
"\n",
"`-` `Bandit` 클래스 선언 + `.step()` 구현"
],
"id": "6be0efa7-625e-48ef-86d1-a19ddef8580c"
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [],
"source": [
"class Bandit:\n",
" def step(self,agent_action):\n",
" reward = 1 if agent_action == 0 else 10\n",
" return reward"
],
"id": "9fbd588a-45c0-4842-aebe-8aec6b601f8a"
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"시도:1 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:2 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:3 행동:0 보상:1 최근20번보상평균:7.0000 \n",
"시도:4 행동:0 보상:1 최근20번보상평균:5.5000 \n",
"시도:5 행동:0 보상:1 최근20번보상평균:4.6000 \n",
"시도:6 행동:1 보상:10 최근20번보상평균:5.5000 \n",
"시도:7 행동:0 보상:1 최근20번보상평균:4.8571 \n",
"시도:8 행동:1 보상:10 최근20번보상평균:5.5000 \n",
"시도:9 행동:1 보상:10 최근20번보상평균:6.0000 \n",
"시도:10 행동:1 보상:10 최근20번보상평균:6.4000 \n",
"시도:11 행동:1 보상:10 최근20번보상평균:6.7273 \n",
"시도:12 행동:0 보상:1 최근20번보상평균:6.2500 \n",
"시도:13 행동:1 보상:10 최근20번보상평균:6.5385 \n",
"시도:14 행동:1 보상:10 최근20번보상평균:6.7857 \n",
"시도:15 행동:1 보상:10 최근20번보상평균:7.0000 \n",
"시도:16 행동:1 보상:10 최근20번보상평균:7.1875 \n",
"시도:17 행동:0 보상:1 최근20번보상평균:6.8235 \n",
"시도:18 행동:1 보상:10 최근20번보상평균:7.0000 \n",
"시도:19 행동:0 보상:1 최근20번보상평균:6.6842 \n",
"시도:20 행동:1 보상:10 최근20번보상평균:6.8500 \n",
"--\n",
"시도:21 행동:0 보상:1 최근20번보상평균:6.4000 \n",
"시도:22 행동:0 보상:1 최근20번보상평균:5.9500 \n",
"시도:23 행동:1 보상:10 최근20번보상평균:6.4000 \n",
"시도:24 행동:0 보상:1 최근20번보상평균:6.4000 \n",
"시도:25 행동:0 보상:1 최근20번보상평균:6.4000 \n",
"시도:26 행동:1 보상:10 최근20번보상평균:6.4000 \n",
"시도:27 행동:0 보상:1 최근20번보상평균:6.4000 \n",
"시도:28 행동:1 보상:10 최근20번보상평균:6.4000 \n",
"시도:29 행동:1 보상:10 최근20번보상평균:6.4000 \n",
"시도:30 행동:0 보상:1 최근20번보상평균:5.9500 \n",
"시도:31 행동:1 보상:10 최근20번보상평균:5.9500 \n",
"시도:32 행동:0 보상:1 최근20번보상평균:5.9500 \n",
"시도:33 행동:0 보상:1 최근20번보상평균:5.5000 \n",
"시도:34 행동:0 보상:1 최근20번보상평균:5.0500 \n",
"시도:35 행동:0 보상:1 최근20번보상평균:4.6000 \n",
"시도:36 행동:0 보상:1 최근20번보상평균:4.1500 \n",
"시도:37 행동:1 보상:10 최근20번보상평균:4.6000 \n",
"시도:38 행동:1 보상:10 최근20번보상평균:4.6000 \n",
"시도:39 행동:1 보상:10 최근20번보상평균:5.0500 \n",
"시도:40 행동:0 보상:1 최근20번보상평균:4.6000 \n",
"시도:41 행동:1 보상:10 최근20번보상평균:5.0500 \n",
"시도:42 행동:0 보상:1 최근20번보상평균:5.0500 \n",
"시도:43 행동:1 보상:10 최근20번보상평균:5.0500 \n",
"시도:44 행동:0 보상:1 최근20번보상평균:5.0500 \n",
"시도:45 행동:0 보상:1 최근20번보상평균:5.0500 \n",
"시도:46 행동:0 보상:1 최근20번보상평균:4.6000 \n",
"시도:47 행동:1 보상:10 최근20번보상평균:5.0500 \n",
"시도:48 행동:1 보상:10 최근20번보상평균:5.0500 \n",
"시도:49 행동:0 보상:1 최근20번보상평균:4.6000 \n",
"시도:50 행동:0 보상:1 최근20번보상평균:4.6000 "
]
}
],
"source": [
"env = Bandit()\n",
"action_space = [0,1]\n",
"actions = []\n",
"rewards = []\n",
"for t in range(1,51):\n",
" action = np.random.choice(action_space)\n",
" reward = env.step(action)\n",
" actions.append(action)\n",
" rewards.append(reward)\n",
" #--#\n",
" print(\n",
" f\"시도:{t}\\t\"\n",
" f\"행동:{action}\\t\"\n",
" f\"보상:{reward}\\t\"\n",
" f\"최근20번보상평균:{np.mean(rewards[-20:]):.4f}\\t\"\n",
" )\n",
" if t<20:\n",
" pass \n",
" elif t==20:\n",
" print(\"--\")\n",
" else: \n",
" if np.mean(rewards[-20:]) > 9.5:\n",
" print(\"Game Clear\")\n",
" break"
],
"id": "a5defbf3-27d4-4dc2-a007-f6f0a934e7a1"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## C. 수정2: `Agent` 구현 (인간지능)\n",
"\n",
"`-` Agent 클래스 설계\n",
"\n",
"- 액션을 하고, 본인의 행동과 환경에서 받은 reward를 기억\n",
"- `.act()`함수와 `.save_experience()`함수 구현"
],
"id": "89d9a5e8-b08a-4964-8139-bb38d7a35e07"
},
{
"cell_type": "code",
"execution_count": 83,
"metadata": {},
"outputs": [],
"source": [
"class Agent:\n",
" def __init__(self):\n",
" self.action_space = [0,1]\n",
" self.action = None \n",
" self.reward = None\n",
" self.actions = []\n",
" self.rewards = [] \n",
" def act(self):\n",
" prob = [0.5, 0.5]\n",
" self.action = 1 #np.random.choice(self.action_space,p=prob)\n",
" def save_experience(self):\n",
" self.actions.append(self.action)\n",
" self.rewards.append(self.reward)"
],
"id": "07b20e58-cf65-4dd3-8967-42f723f4d586"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"— 대충 아래와 같은 느낌으로 코드가 돌아가요 —\n",
"\n",
"**시점0**: init"
],
"id": "245f7517-da1d-4b2b-abe9-3ecb2a0453b3"
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {},
"outputs": [],
"source": [
"agent = Agent()\n",
"env = Bandit()"
],
"id": "f0381129-4060-4926-86e1-9241dc950f4f"
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {},
"outputs": [],
"source": [
"agent.action, agent.reward, agent.actions, agent.rewards"
],
"id": "9228a4ef-6158-4339-9474-da5d804dc87f"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**시점1**: agent 가 acition을 선택"
],
"id": "b066e038-d9f9-49af-86e8-0bd00013d254"
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {},
"outputs": [],
"source": [
"agent.act()"
],
"id": "220c17f1-0fb2-445b-8c63-5c2ac5b98697"
},
{
"cell_type": "code",
"execution_count": 78,
"metadata": {},
"outputs": [],
"source": [
"agent.action, agent.reward, agent.actions, agent.rewards"
],
"id": "2aa0b490-0154-4ad4-94dd-43a378726659"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**시점2**: env가 agent에게 보상을 줌"
],
"id": "95daac19-e495-4be9-8a78-fc64a09ba587"
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {},
"outputs": [],
"source": [
"agent.reward = env.step(agent.action)"
],
"id": "8257dd32-6a78-4086-8785-33c00dd1fe61"
},
{
"cell_type": "code",
"execution_count": 80,
"metadata": {},
"outputs": [],
"source": [
"agent.action, agent.reward, agent.actions, agent.rewards"
],
"id": "174baf76-fad9-40b7-a7bb-177420c151cb"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**시점3**: 경험을 저장"
],
"id": "c254db63-b0bf-4bb1-84e7-547c870f76a7"
},
{
"cell_type": "code",
"execution_count": 81,
"metadata": {},
"outputs": [],
"source": [
"agent.save_experience()"
],
"id": "24ad0a83-2544-4263-9004-ade828924610"
},
{
"cell_type": "code",
"execution_count": 82,
"metadata": {},
"outputs": [],
"source": [
"agent.action, agent.reward, agent.actions, agent.rewards"
],
"id": "cdc18916-42ed-45bf-986e-3f0e53251037"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"– 전체코드 –"
],
"id": "82fc2fc0-c4af-476a-8174-efc92f831063"
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"시도:1 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:2 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:3 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:4 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:5 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:6 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:7 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:8 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:9 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:10 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:11 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:12 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:13 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:14 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:15 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:16 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:17 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:18 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:19 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:20 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"--\n",
"시도:21 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"Game Clear"
]
}
],
"source": [
"env = Bandit()\n",
"agent = Agent()\n",
"for t in range(1,51):\n",
" agent.act()\n",
" agent.reward = env.step(agent.action)\n",
" agent.save_experience()\n",
" #--#\n",
" print(\n",
" f\"시도:{t}\\t\"\n",
" f\"행동:{agent.action}\\t\"\n",
" f\"보상:{agent.reward}\\t\"\n",
" f\"최근20번보상평균:{np.mean(agent.rewards[-20:]):.4f}\\t\"\n",
" )\n",
" if t<20:\n",
" pass \n",
" elif t==20:\n",
" print(\"--\")\n",
" else: \n",
" if np.mean(agent.rewards[-20:]) > 9.5:\n",
" print(\"Game Clear\")\n",
" break "
],
"id": "69629e5d-9f16-4a12-b5b4-c7b2d1de51d6"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## D. 수정3: `Agent` 구현 (인공지능)\n",
"\n",
"`-` 지금까지 풀이의 한계\n",
"\n",
"- 사실 강화학습은 “환경을 이해 $\\to$ 행동을 결정” 의 과정에서\n",
" “$\\to$”의 과정을 수식화 한 것이다.\n",
"- 그런데 지금까지 했던 코드는 환경(environment)를 이해하는 순간\n",
" 에이전트(agent)가 최적의 행동(action)[1]을 **“직관적으로”**\n",
" 결정하였으므로 기계가 스스로 학습을 했다고 볼 수 없다.\n",
"\n",
"`-` 에이전트가 데이터를 보고 스스로 학습할 수 있도록 설계 – 부제:\n",
"`agent.learn()`을 설계하자.\n",
"\n",
"1. 데이터를 모아서 `q_table` 를 만든다. `q_table`은 아래와 같은 내용을\n",
" 포함한다.\n",
"\n",
"| 행동 | 보상(추정값) |\n",
"|:--------------:|:------------:|\n",
"| 버튼0 ($=a_0$) | 1 ($=q_0$) |\n",
"| 버튼1 ($=a_1$) | 10 ($=q_1$) |\n",
"\n",
"1. `q_table`을 바탕으로 적절한 정책(=`policy`)을 설정한다.\n",
"\n",
"- 이 예제에서는 버튼0과 버튼1을 각각\n",
" $\\big(\\frac{q_0}{q_0+q_1},\\frac{q_1}{q_0+q_1}\\big)$ 의 확률로\n",
" 선택하는 “정책”을 이용하면 충분할 듯\n",
"- 처음부터 이러한 확률로 선택하기보다 처음 20번정도는 데이터를 쌓기\n",
" 위해서 행동을 랜덤하게 선택하고, 그 이후에 위에서 제시한 확률값으로\n",
" 행동을 선택하는게 합리적인듯.\n",
"\n",
"> 여기에서 `q_table`, `policy`라는 용어를 기억하세요.\n",
"\n",
"`-` `q_table`을 계산하는 코드 예시\n",
"\n",
"[1] `버튼1`을 누른다"
],
"id": "1d54fab7-b5cb-4f93-b44c-a841e0a75051"
},
{
"cell_type": "code",
"execution_count": 105,
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"agent.actions = [0, 1, 1, 0, 1, 0, 0] \n",
"agent.rewards = [1, 9, 10, 1, 9.5, 1, 1.2] \n",
"actions = np.array(agent.actions)\n",
"rewards = np.array(agent.rewards)"
],
"id": "cccaa9c0-d474-4f7e-9574-d8965ac2bfc1"
},
{
"cell_type": "code",
"execution_count": 112,
"metadata": {},
"outputs": [],
"source": [
"q0,q1 = rewards[actions==0].mean(), rewards[actions==1].mean()"
],
"id": "3a0cd0d3-3ee2-433c-ab85-ecf86aabdeb5"
},
{
"cell_type": "code",
"execution_count": 114,
"metadata": {},
"outputs": [],
"source": [
"q_table = np.array([q0,q1])\n",
"q_table"
],
"id": "61b936fc-fe8f-4ca2-a690-7c8fc0025230"
},
{
"cell_type": "code",
"execution_count": 116,
"metadata": {},
"outputs": [],
"source": [
"q_table/ q_table.sum()"
],
"id": "b0dc5fd7-5aa8-4590-8ef4-dcecab25f8fa"
},
{
"cell_type": "code",
"execution_count": 124,
"metadata": {},
"outputs": [],
"source": [
"prob = q_table/ q_table.sum()\n",
"agent.action = np.random.choice(agent.action_space,p = prob )\n",
"agent.action"
],
"id": "49632925-f681-4b05-9adb-87a5c6d09286"
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`-` 최종코드정리"
],
"id": "09060d0a-def4-49ee-ac09-ef4f9615430b"
},
{
"cell_type": "code",
"execution_count": 134,
"metadata": {},
"outputs": [],
"source": [
"class Agent:\n",
" def __init__(self):\n",
" self.action_space = [0,1]\n",
" self.action = None \n",
" self.reward = None\n",
" self.actions = []\n",
" self.rewards = []\n",
" self.q_table = np.array([0.001,0.001])\n",
" self.n_experience = 0 \n",
" def act(self):\n",
" if self.n_experience <= 20:\n",
" self.action = np.random.choice(self.action_space)\n",
" else: \n",
" prob = self.q_table/ self.q_table.sum() \n",
" self.action = np.random.choice(self.action_space,p = prob )\n",
" def save_experience(self):\n",
" self.actions.append(self.action)\n",
" self.rewards.append(self.reward)\n",
" self.n_experience = self.n_experience + 1 \n",
" def learn(self):\n",
" if self.n_experience < 20:\n",
" pass \n",
" else: \n",
" actions = np.array(self.actions)\n",
" rewards = np.array(self.rewards) \n",
" q0,q1 = rewards[actions==0].mean(), rewards[actions==1].mean()\n",
" self.q_table = np.array([q0,q1])"
],
"id": "03f53425-b31a-4f36-a540-566852a9b3b8"
},
{
"cell_type": "code",
"execution_count": 135,
"metadata": {},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"시도:1 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:2 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:3 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:4 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:5 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:6 행동:1 보상:10 최근20번보상평균:10.0000 \n",
"시도:7 행동:0 보상:1 최근20번보상평균:8.7143 \n",
"시도:8 행동:1 보상:10 최근20번보상평균:8.8750 \n",
"시도:9 행동:1 보상:10 최근20번보상평균:9.0000 \n",
"시도:10 행동:1 보상:10 최근20번보상평균:9.1000 \n",
"시도:11 행동:1 보상:10 최근20번보상평균:9.1818 \n",
"시도:12 행동:1 보상:10 최근20번보상평균:9.2500 \n",
"시도:13 행동:0 보상:1 최근20번보상평균:8.6154 \n",
"시도:14 행동:1 보상:10 최근20번보상평균:8.7143 \n",
"시도:15 행동:0 보상:1 최근20번보상평균:8.2000 \n",
"시도:16 행동:1 보상:10 최근20번보상평균:8.3125 \n",
"시도:17 행동:1 보상:10 최근20번보상평균:8.4118 \n",
"시도:18 행동:1 보상:10 최근20번보상평균:8.5000 \n",
"시도:19 행동:0 보상:1 최근20번보상평균:8.1053 \n",
"시도:20 행동:1 보상:10 최근20번보상평균:8.2000 \n",
"--\n",
"시도:21 행동:1 보상:10 최근20번보상평균:8.2000 \n",
"시도:22 행동:0 보상:1 최근20번보상평균:7.7500 \n",
"시도:23 행동:1 보상:10 최근20번보상평균:7.7500 \n",
"시도:24 행동:1 보상:10 최근20번보상평균:7.7500 \n",
"시도:25 행동:1 보상:10 최근20번보상평균:7.7500 \n",
"시도:26 행동:1 보상:10 최근20번보상평균:7.7500 \n",
"시도:27 행동:1 보상:10 최근20번보상평균:8.2000 \n",
"시도:28 행동:1 보상:10 최근20번보상평균:8.2000 \n",
"시도:29 행동:1 보상:10 최근20번보상평균:8.2000 \n",
"시도:30 행동:1 보상:10 최근20번보상평균:8.2000 \n",
"시도:31 행동:1 보상:10 최근20번보상평균:8.2000 \n",
"시도:32 행동:1 보상:10 최근20번보상평균:8.2000 \n",
"시도:33 행동:1 보상:10 최근20번보상평균:8.6500 \n",
"시도:34 행동:1 보상:10 최근20번보상평균:8.6500 \n",
"시도:35 행동:1 보상:10 최근20번보상평균:9.1000 \n",
"시도:36 행동:1 보상:10 최근20번보상평균:9.1000 \n",
"시도:37 행동:1 보상:10 최근20번보상평균:9.1000 \n",
"시도:38 행동:1 보상:10 최근20번보상평균:9.1000 \n",
"시도:39 행동:1 보상:10 최근20번보상평균:9.5500 \n",
"Game Clear"
]
}
],
"source": [
"env = Bandit()\n",
"agent = Agent()\n",
"for t in range(1,51):\n",
" # step1: 행동\n",
" agent.act()\n",
" # step2: 보상\n",
" agent.reward = env.step(agent.action)\n",
" # step3: 저장 & 학습\n",
" agent.save_experience()\n",
" agent.learn() \n",
" #--#\n",
" print(\n",
" f\"시도:{t}\\t\"\n",
" f\"행동:{agent.action}\\t\"\n",
" f\"보상:{agent.reward}\\t\"\n",
" f\"최근20번보상평균:{np.mean(agent.rewards[-20:]):.4f}\\t\"\n",
" )\n",
" if t<20:\n",
" pass \n",
" elif t==20:\n",
" print(\"--\")\n",
" else: \n",
" if np.mean(agent.rewards[-20:]) > 9.5:\n",
" print(\"Game Clear\")\n",
" break "
],
"id": "e337fb3b-c6ac-470f-baa6-b871a8672b71"
}
],
"nbformat": 4,
"nbformat_minor": 5,
"metadata": {
"kernelspec": {
"name": "python3",
"display_name": "Python 3 (ipykernel)",
"language": "python"
},
"language_info": {
"name": "python",
"codemirror_mode": {
"name": "ipython",
"version": "3"
},
"file_extension": ".py",
"mimetype": "text/x-python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
}
}
}