Commit 5010dd58 authored by Tomáš Kažimír's avatar Tomáš Kažimír
Browse files

pridanie zdrojoveho kodu k clanku q-learning

parents
import gym
import numpy as np
# Načítame prostredie
env = gym.make("MountainCar-v0")
# Naimportujeme si jednotlivé typy pre jednoduchšie overovanie
from gym.spaces import Box, Discrete
if isinstance(env.observation_space, Discrete):
# Získanie veľkosti observation_space
OS_SIZE = [env.observation_space.n]
elif isinstance(env.observation_space, Box):
# Vytvoríme zoznam určujúci na koľko blokov chceme každý atribút rozdeliť
# Tento zápis bude všeobecne fungovať, no rozdeliť každý atribút prostredia
# na rovnaký počet blokov nemusí byť vždy optimálne
OS_SIZE = [20] * len(env.observation_space.high)
# V prípade MountainCar identický zápis - OS_SIZE = [20, 20]
# Vypočítame veľkosť jedného bloku pre každý atribút prostredia
OS_BLOCK_SIZE = (env.observation_space.high - env.observation_space.low)/OS_SIZE
if isinstance(env.action_space, Discrete):
# Získanie veľkosti action_space
AS_SIZE = [env.action_space.n]
# Vytvoríme tabuľku a naplníme ju nulami
q_table = np.full((OS_SIZE + AS_SIZE), 0.0)
# Metóda na pretypovanie stavu na tuple pre ľahšiu prácu s tabuľkou neskôr
def get_state(state):
if isinstance(env.observation_space, Discrete):
return (state,)
elif isinstance(env.observation_space, Box):
# Diskretizujeme každý atribút stavu podľa veľkosti bloku, ktorý sme
# vypočítali vyššie
discrete_state = (state - env.observation_space.low)/OS_BLOCK_SIZE
return tuple(discrete_state.astype(np.int))
EPISODES = 2000 # Počet epizód, ktoré chceme vykonať
SHOW_EVERY = 400 # Po koľkých epizódach chceme prostredie vykresľovať
LEARNING_RATE = 0.1 # Intenzita učenia (alfa)
DISCOUNT = 0.99 # Faktor zľavy (gamma)
# Šanca na zvolenie náhodnej akcie namiesto tej najlepšej
# Chceme aby sa táto hodnota v priebehu epizód zmenšovala
epsilon = 1
EPSILON_MIN_VALUE = 0 # Minimálna hodnota epsilonu, pod ktorú nechceme ísť
START_EPSILON_DECAYING = 100 # Epizóda, pri ktorej chceme začať zmenšovať epsilon
END_EPSILON_DECAYING = EPISODES//2 # Epizóda, pri ktorej chceme ukončiť zmenšovanie
# Hodnota o ktorú chceme zmenšiť epsilon na konci každej epizódy
epsilon_decay_value = (epsilon - EPSILON_MIN_VALUE) / (END_EPSILON_DECAYING - START_EPSILON_DECAYING)
for episode in range(EPISODES):
state = get_state(env.reset()) # Obnoví prostredie a vráti počiatočný stav
if episode % SHOW_EVERY == 0: # Zisťujeme, či chceme vykresliť aktuálnu epizódu
render = True
else:
render = False
done = False
while not done: # Vykonávame ďalší krok, pokiaľ nedosiahneme terminálny stav
# Exploration vs. exploitation
if np.random.random() > epsilon:
action = np.argmax(q_table[state]) # Výber najlepšej akcie podľa tabuľky
else:
action = env.action_space.sample() # Výber náhodnej akcie
# Samotné vykonanie kroku použitím akcie, ktorú sme zvolili
new_state, reward, done, _ = env.step(action)
new_state = get_state(new_state)
if render:
# Pre vyčistenie príkazového riadku (potrebné 'import os'):
# os.system('cls') vo Windows
# os.system('clear') v Linux
env.render() # Vykreslí prostredie v aktuálnom stave
# Získanie najvyššej Q hodnoty v novom stave (Qmax)
max_future_q = np.max(q_table[new_state])
# Získanie Q hodnoty pre vykonanú akciu v starom stave
current_q = q_table[state + (action,)]
# Samotný vzorec vypočítania novej Q hodnoty
new_q = (current_q) + LEARNING_RATE*(reward + DISCOUNT * max_future_q - current_q)
# Aktualizovanie Q hodnoty v tabuľke pre starý stav a akciu novou hodnotou
q_table[state + (action,)] = new_q
# Nový stav sa stáva aktuálnym stavom a môžeme pokračovať v ďalšom kroku
state = new_state
# Znižovanie hodnoty epsilonu na konci epizódy
if END_EPSILON_DECAYING >= episode >= START_EPSILON_DECAYING:
epsilon -= epsilon_decay_value
env.close() # Po ukončení trénovania zavrieme prostredie
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment