Sari la conținutul principal

Introducere în Q-Learning: un tutorial pentru începători

Află despre cel mai popular algoritm de învățare prin întărire fără model cu un tutorial în Python.
Actualizat 22 iul. 2026  · 11 min. citire

Explorează cu AI

Deschide în ChatGPTDeschide în ClaudeDeschide în Perplexity

Antet Q-Learning

Învățarea prin întărire (RL) este partea din ecosistemul de machine learning în care agentul învață interacționând cu mediul pentru a obține strategia optimă de atingere a obiectivelor. Este destul de diferită de algoritmii de învățare supravegheată, unde trebuie să alimentăm și să procesăm date. Învățarea prin întărire nu necesită date. În schimb, învață din mediu și din sistemul de recompense pentru a lua decizii mai bune.

De exemplu, în jocul video Mario, dacă un personaj face o acțiune aleatoare (de ex. se mișcă la stânga), pe baza acelei acțiuni poate primi o recompensă. După ce ia acțiunea, agentul (Mario) ajunge într-o nouă stare, iar procesul se repetă până când personajul de joc ajunge la finalul nivelului sau moare. 

Acest episod se va repeta de mai multe ori până când Mario învață să navigheze prin mediu maximizând recompensele. 

Învățare prin întărire

Imagine de autor

Putem descompune învățarea prin întărire în cinci pași simpli:

  1. Agentul se află în starea zero într-un mediu.
  2. Va face o acțiune pe baza unei strategii specifice.
  3. Va primi o recompensă sau o penalizare în funcție de acea acțiune.
  4. Învățând din mutările anterioare și optimizând strategia. 
  5. Procesul se repetă până când se găsește o strategie optimă. 

Află mai multe citind tutorialul nostru, o Introducere în învățarea prin întărire. Vei explora mai multe despre cum funcționează învățarea prin întărire, cu exemple de cod. 

În acest tutorial, vom învăța despre Q-learning și vom înțelege de ce avem nevoie de Deep Q-learning. În plus, vom învăța să creăm și să antrenăm algoritmi Q-learning de la zero folosind Numpy și Gymnasium.

Notă: Dacă ești nou în machine learning, îți recomandăm să urmezi traseul nostru de carieră Machine Learning Scientist with Python pentru a înțelege mai bine învățarea prin întărire și Q-Learning. 

Ce este Q-Learning?

Q-learning este un algoritm fără model, bazat pe valori, off-policy, care găsește cea mai bună serie de acțiuni pe baza stării curente a agentului. „Q” vine de la quality (calitate). Calitatea reprezintă cât de valoroasă este acțiunea pentru maximizarea recompenselor viitoare.  

Algoritmii cu model folosesc funcții de tranziție și de recompensă pentru a estima politica optimă și a crea modelul. În schimb, algoritmii fără model învață consecințele acțiunilor lor din experiență, fără funcție de tranziție și recompensă. 

Metoda bazată pe valori antrenează funcția de valoare pentru a învăța care stare este mai valoroasă și ce acțiune să ia. Pe de altă parte, metodele bazate pe politică antrenează direct politica pentru a învăța ce acțiune să ia într-o stare dată.

În off-policy, algoritmul evaluează și actualizează o politică diferită de politica folosită pentru a lua o acțiune. În schimb, algoritmul on-policy evaluează și îmbunătățește aceeași politică folosită pentru a lua acțiunea.  

Termeni-cheie în Q-learning

Înainte să vedem cum funcționează Q-learning, trebuie să învățăm câțiva termeni utili pentru a înțelege fundamentele Q-learning. 

  • Stări (s): poziția curentă a agentului în mediu. 
  • Acțiune (a): un pas făcut de agent într-o anumită stare. 
  • Recompense: pentru fiecare acțiune, agentul primește o recompensă sau o penalizare. 
  • Episoade: sfârșitul nivelului, unde agenții nu mai pot lua acțiuni noi. Se întâmplă când agentul a atins obiectivul sau a eșuat. 
  • Q(St+1, a): valoarea Q optimă așteptată pentru a face acțiunea într-o stare anume. 
  • Q(St, At): estimarea curentă a lui Q(St+1, a).
  • Q-Table: agentul menține un Q-table cu mulțimi de stări și acțiuni.
  • Temporal Differences (TD): folosit pentru a estima valoarea așteptată a lui Q(St+1, a) folosind starea și acțiunea curentă și starea și acțiunea anterioară. 

Cum funcționează Q-Learning?

Vom învăța în detaliu cum funcționează Q-learning folosind exemplul unui lac înghețat. În acest mediu, agentul trebuie să traverseze lacul înghețat de la start la țintă, fără să cadă în găuri. Cea mai bună strategie este să ajungă la țintă urmând drumul cel mai scurt. 

Vizualizare Q-Learning

Gif de autor

Q-Table

Agentul va folosi un Q-table pentru a lua cea mai bună acțiune posibilă pe baza recompensei așteptate pentru fiecare stare din mediu. Pe scurt, un Q-table este o structură de date cu mulțimi de acțiuni și stări, iar algoritmul de Q-learning este folosit pentru a actualiza valorile din tabel. 

Q-Function

Funcția Q folosește ecuația Bellman și primește starea (s) și acțiunea (a) ca intrare. Ecuația simplifică calculul valorilor de stare și al valorii stare-acțiune. Ecuația Bellman

Imagine de pe freecodecamp.org

Algoritmul Q-learning

Procesul Q-Learning

Imagine de autor

Inițializează Q-Table

Mai întâi vom inițializa Q-table. Vom construi tabelul cu coloane în funcție de numărul de acțiuni și rânduri în funcție de numărul de stări.

În exemplul nostru, personajul se poate mișca în sus, jos, stânga și dreapta. Avem patru acțiuni posibile și patru stări (start, inactiv, drum greșit și final). Poți considera și drumul greșit drept cădere în gaură. Vom inițializa Q-Table cu valori 0. 

Q-Table 1

Imagine de autor

Alege o acțiune

Al doilea pas este destul de simplu. La început, agentul va alege să facă o acțiune aleatoare (jos sau dreapta), iar la a doua rulare va folosi un Q-Table actualizat pentru a selecta acțiunea. 

Efectuează o acțiune

Alegerea unei acțiuni și efectuarea ei se va repeta de mai multe ori până când bucla de antrenare se oprește. Prima acțiune și prima stare sunt selectate folosind Q-Table. În cazul nostru, toate valorile din Q-Table sunt zero. 

Apoi, agentul se va mișca în jos și va actualiza Q-Table folosind ecuația Bellman. Cu fiecare mutare, vom actualiza valorile din Q-Table și le vom folosi și pentru a determina cea mai bună acțiune. 

Inițial, agentul este în modul explorare și alege o acțiune aleatoare pentru a explora mediul. Strategia Epsilon Greedy este o metodă simplă de a echilibra explorarea și exploatarea. Epsilon reprezintă probabilitatea de a alege explorarea și de a exploata atunci când șansele de explorare sunt mai mici. 

La început, rata epsilon este mai mare, ceea ce înseamnă că agentul se află în modul explorare. Pe măsură ce explorează mediul, epsilon scade, iar agentul începe să exploateze mediul. În timpul explorării, cu fiecare iterație, agentul devine mai încrezător în estimarea valorilor Q

Q-Table 2

Imagine de autor

În exemplul cu lacul înghețat, agentul nu cunoaște mediul, așa că la început ia o acțiune aleatoare (se mișcă în jos). După cum vedem în imaginea de mai sus, Q-Table este actualizat folosind ecuația Bellman.

Măsurarea recompenselor

După ce luăm acțiunea, vom măsura rezultatul și recompensa. 

  • Recompensa pentru atingerea țintei este +1
  • Recompensa pentru alegerea drumului greșit (căderea în gaură) este 0
  • Recompensa pentru inactivitate sau deplasare pe lacul înghețat este tot 0. 

Actualizează Q-Table

Vom actualiza funcția Q(St, At) folosind ecuația. Aceasta folosește valorile Q estimate din episodul anterior, rata de învățare și eroarea de tip Temporal Differences. Eroarea TD este calculată folosind recompensa imediată, recompensa viitoare maximă așteptată, actualizată cu discount, și vechea valoare estimată Q. 

Procesul se repetă de mai multe ori până când Q-Table este actualizat, iar funcția de valoare Q este maximizată. 

Ecuația Q-learning

Imagine de autor | Vizualizări ale ecuației de la Thomas Simonini

La început, agentul explorează mediul pentru a actualiza Q-table. Iar când Q-Table este gata, agentul începe să exploateze și să ia decizii mai bune. Q-Table 3

Imagine de autor

În cazul lacului înghețat, agentul va învăța să ia drumul cel mai scurt pentru a ajunge la țintă și să evite să sară în găuri. 

Tutorial Q-Learning în Python 

În această secțiune, vom construi modelul nostru Q-learning de la zero folosind mediul Gymnasium, Pygame și Numpy. Tutorialul în Python este o versiune modificată a Notebok-ului de Thomas Simonini. Include inițializarea mediului și a Q-Table, definirea politicii greedy, setarea hiperparametrilor, crearea și rularea buclei de antrenare și a evaluării, și vizualizarea rezultatelor.   

Dacă întâmpini probleme la crearea și rularea buclei de antrenare, poți verifica sursa de cod cu rezultatul.   

Configurare

Configurează un ecran virtual

Mai întâi vom instala toate dependențele pentru a genera un video de reluare (Gif). Vom avea nevoie de un ecran virtual (pyvirtualdisplay) pentru a reda mediul și a înregistra cadrele. 

Notă: folosind %%capture suprimăm ieșirea celulei Jupyter. 

%%capture
!pip install pyglet==1.5.1
!apt install python-opengl
!apt install ffmpeg
!apt install xvfb
!pip3 install pyvirtualdisplay

# Virtual display
from pyvirtualdisplay import Display

virtual_display = Display(visible=0, size=(1400, 900))
virtual_display.start()

Instalează dependențele

Acum vom instala dependențele care ne vor ajuta să creăm, rulăm și evaluăm bucla de antrenare. 

  • gymnasium: folosit pentru a inițializa mediul FrozenLake-v1.
  • pygame: folosit pentru interfața FrozenLake-v1.
  • numPy: folosit pentru crearea și gestionarea Q-table.
%%capture
!pip install gymnasium
!pip install pygame
!pip install numpy

!pip install imageio imageio_ffmpeg

Importă pachetele

Acum vom importa bibliotecile necesare. 

  • Imageio este folosit pentru a crea animația. 
  • tqdm este folosit pentru barele de progres. 
import numpy as np
import gymnasium as gym
import random
import imageio
from tqdm.notebook import trange

Mediul Gymnasium Frozen Lake 

Vom crea un mediu 4x4 non-alunecos folosind biblioteca Frozen Lake din Gymnasium

  • Există două versiuni de grilă, „4x4” și „8x8”.
  • Dacă is_slippery=True, agentul s-ar putea să nu se miște în direcția dorită din cauza naturii alunecoase a lacului înghețat. 

După inițializarea mediului, vom face o analiză a mediului. 

env = gym.make("FrozenLake-v1",map_name="4x4",is_slippery=False)

print("Observation Space", env.observation_space)
print("Sample observation", env.observation_space.sample()) # display a random observation

Există 16 spații unice în mediu afișate în poziții aleatoare. 

Observation Space Discrete(16)
Sample observation 15

Hai să aflăm numărul de acțiuni și să afișăm o acțiune aleatoare. 

Spațiul de acțiuni:

  • 0: mișcare la stânga
  • 1: mișcare în jos
  • 2: mișcare la dreapta
  • 3: mișcare în sus

Funcția de recompensă:

  • Atingerea țintei: +1
  • Căderea în gaură: 0
  • Rămânerea pe lacul înghețat: 0
print("Action Space Shape", env.action_space.n)
print("Action Space Sample", env.action_space.sample())
Action Space Shape 4
Action Space Sample 1

Creează și inițializează Q-table

Q-Table are coloanele ca acțiuni și rândurile ca stări. Putem folosi Gymnasium pentru a afla spațiul de acțiuni și spațiul de stări. Apoi vom folosi aceste informații pentru a crea Q-Table. 

state_space = env.observation_space.n
print("There are ", state_space, " possible states")

action_space = env.action_space.n
print("There are ", action_space, " possible actions")
There are  16  possible states
There are  4  possible actions

Pentru inițializarea Q-Table, vom crea un array Numpy din spațiul de stări și spațiul de acțiuni. Vom crea un array 16 X 4. 

def initialize_q_table(state_space, action_space):
  Qtable = np.zeros((state_space, action_space))
  return Qtable

Qtable_frozenlake = initialize_q_table(state_space, action_space)

Politica epsilon-greedy

În secțiunea anterioară am învățat despre strategia epsilon greedy care gestionează compromisurile dintre explorare și exploatare. Cu o probabilitate de 1 - ɛ, facem exploatare, iar cu probabilitatea ɛ, facem explorare. 

În epsilon_greedy_policy vom:

  1. Genera un număr aleator între 0 și 1.
  2. Dacă numărul aleator este mai mare decât epsilon, vom face exploatare. Asta înseamnă că agentul va lua acțiunea cu cea mai mare valoare pentru o stare dată.
  3. Altfel, vom face explorare (luând o acțiune aleatoare). 
def epsilon_greedy_policy(Qtable, state, epsilon):
  random_int = random.uniform(0,1)
  if random_int > epsilon:
    action = np.argmax(Qtable[state])
  else:
    action = env.action_space.sample()
  return action

Definește politica greedy

Acum știm că Q-learning este un algoritm off-policy, ceea ce înseamnă că politica de luare a acțiunii și politica de actualizare sunt diferite. 

În acest exemplu, politica Epsilon Greedy este politica de acțiune, iar politica Greedy este politica de actualizare. 

Politica Greedy va fi și politica finală când agentul este antrenat. Este folosită pentru a selecta cea mai mare valoare stare-acțiune din Q-Table.

def greedy_policy(Qtable, state):
  action = np.argmax(Qtable[state])
  return action

Hiperparametrii modelului

Acești hiperparametri sunt folosiți în bucla de antrenare, iar reglarea lor fină îți va oferi rezultate mai bune. 

Agentul trebuie să exploreze suficient spațiul de stări pentru a învăța o aproximare bună a valorilor; avem nevoie de o scădere progresivă a lui epsilon. Dacă rata de scădere este mare, agentul s-ar putea bloca, deoarece nu a explorat suficient spațiul de stări.

  • Există 10.000 de episoade de antrenare și 100 de evaluare.
  • Rata de învățare este 0,7.
  • Folosim „FrozenLake-v1” ca mediu, cu 99 de pași maximi per episod.
  • Gamma (rata de discount) este 0,95.
  • eval_seed: seed de evaluare pentru mediu.
  • Probabilitatea epsilon de explorare la start este 1,0, iar probabilitatea minimă va fi 0,05.
  • Rata de decădere exponențială pentru probabilitatea epsilon este 0,0005.
# Training parameters
n_training_episodes = 10000
learning_rate = 0.7        

# Evaluation parameters
n_eval_episodes = 100      

# Environment parameters
env_id = "FrozenLake-v1"   
max_steps = 99             
gamma = 0.95               
eval_seed = []             

# Exploration parameters
max_epsilon = 1.0           
min_epsilon = 0.05           
decay_rate = 0.0005           

Antrenarea modelului 

În bucla de antrenare, vom:

  1. Crea o buclă pentru episoadele de antrenare.
  2. Mai întâi vom reduce epsilon. Avem nevoie de tot mai puțină explorare și de mai multă exploatare cu fiecare episod. 
  3. Reseta mediul.
  4. Crea o buclă imbricată pentru numărul maxim de pași.
  5. Alege acțiunea folosind politica epsilon greedy. 
  6. Fă acțiunea (At) și observă recompensa așteptată (Rt+1) și starea (St+1).
  7. Ia acțiunea (a) și observă starea rezultată (s') și recompensa (r).
  8. Actualizează funcția Q folosind formula. 
  9. Dacă done= True, încheie episodul și întrerupe bucla.
  10. În final, schimbă starea curentă în noua stare. 
  11. După ce toate episoadele de antrenare se încheie, funcția va returna Q-Table actualizat. 
def train(n_training_episodes, min_epsilon, max_epsilon, decay_rate, env, max_steps, Qtable):
  for episode in trange(n_training_episodes):
 
    epsilon = min_epsilon + (max_epsilon - min_epsilon)*np.exp(-decay_rate*episode)
    # Reset the environment
    state = env.reset()
    step = 0
    done = False

    # repeat
    for step in range(max_steps):
   
      action = epsilon_greedy_policy(Qtable, state, epsilon)

   
      new_state, reward, done, info = env.step(action)

   
      Qtable[state][action] = Qtable[state][action] + learning_rate * (reward + gamma * np.max(Qtable[new_state]) - Qtable[state][action])

      # If done, finish the episode
      if done:
        break
     
      # Our state is the new state
      state = new_state
  return Qtable

Ne-au trebuit 3 secunde pentru a finaliza 10.000 de episoade de antrenare. 

Qtable_frozenlake = train(n_training_episodes, min_epsilon, max_epsilon, decay_rate, env, max_steps, Qtable_frozenlake)

Rezultatul episoadelor de antrenare

După cum se vede, Q-Table antrenat are valori, iar agentul va folosi acum aceste valori pentru a naviga mediul și a atinge obiectivul.  

Qtable_frozenlake
array([[0.73509189, 0.77378094, 0.77378094, 0.73509189],
      [0.73509189, 0.        , 0.81450625, 0.77378094],
      [0.77378094, 0.857375  , 0.77378094, 0.81450625],
      [0.81450625, 0.        , 0.77378094, 0.77378094],
      [0.77378094, 0.81450625, 0.        , 0.73509189],
      [0.        , 0.        , 0.        , 0.        ],
      [0.        , 0.9025    , 0.        , 0.81450625],
      [0.        , 0.        , 0.        , 0.        ],
      [0.81450625, 0.        , 0.857375  , 0.77378094],
      [0.81450625, 0.9025    , 0.9025    , 0.        ],
      [0.857375  , 0.95      , 0.        , 0.857375  ],
      [0.        , 0.        , 0.        , 0.        ],
      [0.        , 0.        , 0.        , 0.        ],
      [0.        , 0.9025    , 0.95      , 0.857375  ],
      [0.9025    , 0.95      , 1.        , 0.9025    ],
      [0.        , 0.        , 0.        , 0.        ]])

Evaluare

evaluate_agent rulează pentru n_eval_episodes episoade și returnează media și abaterea standard a recompensei. 

  1. În buclă, vom verifica mai întâi dacă există un seed de evaluare. Dacă nu, resetăm mediul fără seed. 
  2. Bucla imbricată va rula până la max_steps.
  3. Agentul va lua acțiunea cu recompensa viitoare maximă așteptată într-o stare dată folosind Q-Table. 
  4. Calculează recompensa.
  5. Schimbă starea.
  6. Dacă s-a terminat (agentul cade în gaură sau ținta a fost atinsă), întrerupe bucla.
  7. Adaugă rezultatele.
  8. La final, vom folosi aceste rezultate pentru a calcula media și abaterea standard. 
def evaluate_agent(env, max_steps, n_eval_episodes, Q, seed):

  episode_rewards = []
  for episode in range(n_eval_episodes):
    if seed:
      state = env.reset(seed=seed[episode])
    else:
      state = env.reset()
    step = 0
    done = False
    total_rewards_ep = 0
   
    for step in range(max_steps):
      # Take the action (index) that have the maximum reward
      action = np.argmax(Q[state][:])
      new_state, reward, done, info = env.step(action)
      total_rewards_ep += reward
       
      if done:
        break
      state = new_state
    episode_rewards.append(total_rewards_ep)
  mean_reward = np.mean(episode_rewards)
  std_reward = np.std(episode_rewards)

  return mean_reward, std_reward

După cum poți vedea, am obținut scorul perfect cu abatere standard zero. Asta înseamnă că agentul nostru a ajuns la țintă în toate cele 100 de episoade. 

# Evaluate our Agent
mean_reward, std_reward = evaluate_agent(env, max_steps, n_eval_episodes, Qtable_frozenlake, eval_seed)
print(f"Mean_reward={mean_reward:.2f} +/- {std_reward:.2f}")
Mean_reward=1.00 +/- 0.00

Vizualizarea rezultatului

Până acum am lucrat cu numere, iar pentru a oferi o demonstrație, trebuie să creăm un Gif animat al agentului de la start până când ajunge la țintă. 

  1. Mai întâi vom crea starea resetând mediul cu un întreg aleator 0-500. 
  2. Randăm mediul folosind rdb_array pentru a crea un array de imagini. 
  3. Apoi adăugăm img la array-ul images
  4. În buclă, vom face pasul folosind Q-Table și vom reda imaginea pentru fiecare pas. 
  5. La final, vom folosi acest array și imageio pentru a crea un Gif cu un cadru pe secundă. 
def record_video(env, Qtable, out_directory, fps=1):
  images = [] 
  done = False
  state = env.reset(seed=random.randint(0,500))
  img = env.render(mode='rgb_array')
  images.append(img)
  while not done:
    # Take the action (index) that have the maximum expected future reward given that state
    action = np.argmax(Qtable[state][:])
    state, reward, done, info = env.step(action) # We directly put next_state = state for recording logic
    img = env.render(mode='rgb_array')
    images.append(img)
  imageio.mimsave(out_directory, [np.array(img) for i, img in enumerate(images)], fps=fps)

Dacă ești într-un notebook Jupyter, poți afișa Gif-ul folosind funcția Image din IPython.display

video_path="/content/replay.gif"
video_fps=1
record_video(env, Qtable_frozenlake, video_path, video_fps)

from IPython.display import Image
Image('./replay.gif')

Acum poți să împarți aceste rezultate cu colegii tăi sau să le postezi pe rețelele sociale.

Întrebări frecvente despre Q-Learning

Care este dezavantajul Q-learning?

Procesul de învățare în Q-learning este costisitor pentru agent, mai ales la început. De ce? Pentru a converge către politica optimă, fiecare pereche stare-acțiune este vizitată frecvent.

De ce se numește Q-learning Q-learning?

În Q-learning, „Q” vine de la quality (calitate). Reprezintă cât de utilă este o acțiune dată pentru a obține recompense viitoare, fiind folosită pentru a crea o hartă a stărilor și acțiunilor pentru a maximiza recompensele așteptate.

De ce este Q-Learning off-policy?

În Q-learning, politica actualizată este diferită de politica de comportament (acțiune), motiv pentru care este numit algoritm off-policy.

Converge întotdeauna Q-learning?

Da. În timpul antrenării, algoritmul converge întotdeauna către politica optimă.

De ce avem nevoie de deep Q-learning?

Q-learning este un algoritm simplu conceput pentru un mediu mai mic și discret. În cazul unui mediu mai mare, vom avea nevoie de un Q-table uriaș de stări și acțiuni, care va necesita memorie și calcul mai mare pentru antrenare. În schimb, Deep Q-learning înlocuiește Q-table cu o rețea neurală pentru a gestiona medii mari care implică acțiuni și stări continue.

Subiecte

Cursuri de Machine Learning

course

Proiectarea fluxurilor de lucru pentru Machine Learning în Python

4 oră
12.6K
Învață să construiești pipeline-uri care rezistă testului timpului.
Vezi detaliiRight Arrow
Începeți Cursul
Vezi mai multRight Arrow