Direkt zum Inhalt

Aktionswertfunktion: Ein Leitfaden mit Python-Beispielen

Dieser Beitrag erklärt die Aktionswertfunktion, ein zentrales Konzept im verstärkenden Lernen, und zeigt dir, wie du sie mit Q-Learning und DQNs in Python umsetzen kannst.
Aktualisierte 8. Juli 2025  · 15 Min. Lesezeit

Reinforcement Learning (RL) ist ein Paradigma des maschinellen Lernens, bei dem ein Agent durch Interaktion mit einer externen Umgebung lernt, die richtigen Entscheidungen zu treffen. Die Umgebung gibt Feedback in Form von Belohnungen, wenn man das Richtige macht. 

Das Ziel des Agenten ist es, die kumulierten Belohnungen zu maximieren. In vielen praktischen Problemen kommt das Feedback an den Agenten von einem Menschen; das nennt man RL mit menschlichem Feedback (RLHF)

RLHF wird oft benutzt, um LLMs so einzustellen, dass sie Ergebnisse liefern, die mit menschlichen Werten und Vorlieben übereinstimmen. Wenn eine KI Feedback gibt, nennen wir das RL mit KI-Feedback.

Der Agent nutzt die Aktionswertfunktion, um zu entscheiden, welche Aktion in jedem Schritt gewählt werden soll. Eine optimierte Aktionswertfunktion hilft dem Agenten, bei jedem Schritt die beste Aktion zu wählen, um seine kumulierten Belohnungen zu maximieren.

In diesem Tutorial zeige ich dir die Aktionswertfunktion, erkläre, wofür sie in RL wichtig ist, und zeige dir, wie du sie von Grund auf umsetzt.

Was ist eine Aktions-Wert-Funktion?

Die Handlungswertfunktion (Q) schätzt die erwartete kumulative Belohnung (Rendite), die durch eine bestimmte Aktion (a) in einem bestimmten Zustand (s) und anschließender Befolgung der Richtlinie π . Es wird als (s,a). Wenn klar ist, dass der Agent die beste Strategie verfolgt, kann man das einfacher so schreiben: Q(s,a)ausgedrückt.

Die Aktionswertfunktion wird benutzt, um die Aktion auszuwählen, die ausgehend von einem bestimmten Zustand den höchsten Ertrag bringt. Die beste Strategie (π*) bringt den erwarteten Gewinn auf ein Maximum. Also, in jedem Zustand wählt die Richtlinie die Maßnahme, die den höchsten erwarteten Ertrag bringt. Diese optimale Strategie wird als π ausgedrückt.* = argmaxa Q(s,a).

Die Q-Funktion wird normalerweise als Q-Tabelle dargestellt. Diese Tabelle speichert den Wert jeder möglichen Aktion für jeden möglichen Zustand der Umgebung. In komplexen Umgebungen wird diese Tabelle unübersichtlich groß und ineffizient. Deshalb modellieren wir die Q-Tabelle für die meisten nicht trivialen Umgebungen als neuronales Netzwerk statt als Tabelle. Dieses Netzwerk kommt der Funktion der Q-Tabelle ziemlich nahe. Ausgehend von einem Zustand gibt es die diesem Zustand entsprechenden Aktionswerte aus. 

Warum Aktionswertfunktionen in RL wichtig sind

Wenn man die wahre Aktionswertfunktion kennt, sollte die Strategie die Aktion wählen, die die höchsten erwarteten Belohnungen bringt. Diese Strategie wird als Ausnutzung bezeichnet. Allerdings ist die wahre Aktionswertfunktion während der Trainingsphase noch nicht bekannt. Die Entscheidung für eine Maßnahme basiert also auf unvollständigen Infos. Wenn man mit diesen unvollständigen Infos versucht, das Beste rauszuholen, kann das dazu führen, dass man die wahre Aktionswertfunktion nicht findet und in einem lokalen Optimum hängen bleibt. 

Andererseits wählt eine explorative Strategie manchmal nicht die besten Aktionen, die aber am Ende zu einem besseren Ergebnis führen können. Dies wird als ε -gierige, bei der ε ein kleiner Wert ist. Die Strategie wählt zufällig eine nicht ganz optimale Aktion mit einerWahrscheinlichkeits ε und die Aktion, die den größten Gewinn bringt, mit einer Wahrscheinlichkeit 1 - ε.

Eine Strategie verfolgen, die Ausbeutung und Erkundung , kann der Akteur alternative Wege durch die Umgebung entdecken, was zu besseren Gesamtgewinnen führt.

Grundlagen der RL-Algorithmen

RL-Algorithmen kann man in zwei große Kategorien einteilen: 1) modellbasiert und modellfrei und 2) on-policy und off-policy. 

Modellbasierte und modellfreie Algorithmen

Bei modellbasierten Methoden versucht man, das Wahrscheinlichkeitsverteilungsmodell der Umgebung vorherzusagen. P(r, s' | s, a) – also die Wahrscheinlichkeit, eine Belohnung zu bekommen r und das Erreichen eines Zustands s' zu erreichen, wenn man von einem Zustand s und eine Maßnahme ergriffen wird a.

Diese Methoden nutzen die Interaktionen des Agenten mit der Umgebung, um das Modell (der Umgebung) zu optimieren und die vorhergesagten Belohnungen und Zustände zu verbessern. So kann der Agent die Umgebung über das Modell simulieren, ohne bei jedem Schritt mit der Umgebung interagieren zu müssen. 

Einige modellbasierte Algorithmen wie Dyna-Q aktualisieren die Q-Funktion anhand von simulierten Erfahrungen. Diese Methoden kommen zum Einsatz, wenn es teuer oder nicht praktikabel ist, einen ungeschulten Agenten mit einer großen Anzahl von Interaktionen mit der Umgebung zu konfrontieren. Zum Beispiel ist es echt teuer, wenn ein Roboter, der nicht richtig trainiert ist, immer wieder hinfällt und dabei kaputtgehen könnte. 

Im Gegensatz dazu aktualisieren modellfreie Methoden wie Q-Learning direkt Q(s,a) nach einem iterativen Prozess, um die wahre Aktionswertfunktion zu ermitteln, ohne die Umgebung explizit zu modellieren. Der Agent interagiert in jedem Schritt direkt mit der Umgebung. Sie probieren einfach aus, was funktioniert, bis sie die beste Lösung gefunden haben. Da sie kein Modell der Umgebung brauchen, sind sie einfacher, aber man braucht viele Beispiele dafür, wie die Umgebung funktioniert. 

Modellfreie Algorithmenwie Q-Learning, SARSA (State-Action-Reward-State-Action) und DQNs lernen dieQ-Funktion explizitund nutzen sie, um den Aktionswert bei jedem Schritt zu schätzen.

On-Policy- und Off-Policy-Algorithmen

Off-Policy-Algorithmen (wie DQNs und Q-Learning) nutzen Erfahrungswiederholungen, um den Wert der optimalen Strategie zu lernen. Sie haben viele (echte oder simulierte) Interaktionen mit der Umgebung und nehmen zufällige Stichproben dieser Interaktionen, um die Q-Funktion zu aktualisieren. Sie verwenden nicht die beste Strategie, um die Aktion in jedem Schritt zu bestimmen. Off-Policy-Methoden nutzen die Q-Funktion, um den Aktionswert für die Zielpolitik zu schätzen. Sie wollen die zukünftigen Gewinne maximieren, indem sie die Q-Funktion anhand der höchsten erwarteten Belohnung aus dem nächsten Schritt anpassen. 

Einige On-Policy-Algorithmen (wie SARSA) nutzen die Policy, um die Aktion in jedem Schritt auszuwählen. So hält sich der Agent an die gleiche Richtlinie, die er aktualisiert. Die Q-Funktion wird anhand der Belohnung aktualisiert, die der Agent für das Befolgen der Richtlinie bekommt. Andere On-Policy-Algorithmen, wie Policy Gradients und Actor-Critic, brauchen die Q-Funktion nicht. 

So sind Aktionswertfunktionen die Basis für verschiedene RL-Algorithmen. 

Optimale Auswahl von Maßnahmen

Der Q-Wert Q(s,a) wie hoch der erwartete Gewinn ist, wenn man die Aktion macht. a im Zustand s und dem anschließenden Befolgen der Strategie. Wenn also eine trainierte Q-Tabelle vorliegt, führt die Auswahl der Aktion, die in einem bestimmten Zustand zum maximalen Q-Wert führt, zu einer optimalen Strategie, die auf einer gierigen (ausbeutungsorientierten) Strategie basiert. In jedem Schritt entscheidet der Agent, welche Aktion er macht. a* = arg max a Q(s,a). So wählt es über die ganze Episode hinweg den Weg, der die langfristigen Belohnungen auf der Grundlage der verfügbaren Informationen maximiert. 

Methoden wie Q-Learning aktualisieren die Q-Werte in der Q-Tabelle über viele Iterationen hinweg, bis sie sich ihren optimalen Werten annähern. So findet der Algorithmus nach dem Training die beste Strategie, die aus jedem Zustand die beste Aktion und den besten Weg durch die Episode wählt.

Konzepte der Künstlichen Intelligenz (KI) in Python

Einstieg in die KI
Jetzt starten

Eine Aktions-Wert-Funktion umsetzen

Nachdem wir die Grundlagen und die Verwendung der Aktionswertfunktion besprochen haben, zeige ich dir jetzt, wie du sie in Python umsetzt.

Schritt 1: Die Umgebung festlegen

Importiere die benötigten Pakete, einschließlich Gymnasium und NumPy: 

import gymnasium as gym
import numpy as np
import math
import random

Initialisiere eine RL-Umgebung aus Gymnasium. In diesem Artikel trainieren wir einen RL-Agenten, um die CartPole-Umgebung zu meistern. 

env = gym.make('CartPole-v1')

Schritt 2: Q-Tabelle initialisieren

Der Beobachtungsraum von CartPole hat vier Zustände: Wagenposition, Wagengeschwindigkeit, Stangenwinkel und Stangenwinkelgeschwindigkeit. 

In diesem Beispiel konzentrieren wir uns nur auf die Beobachtungen des Polwinkels und der Polwinkelgeschwindigkeit. So erstellen wir die diskrete Q-Tabelle wie folgt: 

  • Ein einzelner Status für die Position des Wagens – alle möglichen Werte werden in diesem einen Status zusammengefasst. 
  • Ein diskreter Zustand für die Geschwindigkeit des Wagens 
  • Sechs verschiedene Zustände für den Polwinkel
  • Drei verschiedene Zustände für die Polgeschwindigkeit 

Die Anzahl der Spalten hängt von der Größe des Aktionsraums ab, in diesem Fall 2. 

NUM_BUCKETS = (1, 1, 6, 3)
NUM_ACTIONS = env.action_space.n
q_table = np.zeros(NUM_BUCKETS + (NUM_ACTIONS,))

In der CartPole-Umgebung ist der Zustandsraum kontinuierlich. Der Winkel, die Geschwindigkeit und die Position der Wagenstange können sich ständig ändern. Der Aktionsraum ist klar – du kannst den Wagen nach links oder rechts schieben. 

Q-Learning mit Q-Tabellen kann nur in einem diskreten Raum verwendet werden, weil man den Q-Wert für eine Reihe von Zuständen und Aktionen explizit tabellarisch auflisten muss. Also, der erste Schritt ist, den kontinuierlichen Zustandsraum in diskrete Zustände zu zerlegen. 

Zuerst schauen wir uns die oberen und unteren Grenzen der Zustandsraumvariablen an. Wir sehen, dass die Geschwindigkeit des Wagens und die Winkelgeschwindigkeit der Stange unendlich sind. Also haben wir künstlich obere und untere Grenzen für diese Zustandsvariablen festgelegt. 

STATE_BOUNDS = list(zip(env.observation_space.low, env.observation_space.high))
STATE_BOUNDS[1] = [-0.5, 0.5]
STATE_BOUNDS[3] = [-math.radians(50), math.radians(50)]

Wir machen eine Funktion, um die durchgehenden Zustandswerte in diskrete Werte zu zerlegen: 

def discretize_state(state):
    discrete_states = []

    for i in range(len(state)):
        if state[i] <= STATE_BOUNDS[i][0]:
            discrete_state = 0
        elif state[i] >= STATE_BOUNDS[i][1]:
            discrete_state = NUM_BUCKETS[i] - 1
        else:
            bound_width = STATE_BOUNDS[i][1] - STATE_BOUNDS[i][0]
            offset = (NUM_BUCKETS[i] - 1) * STATE_BOUNDS[i][0] / bound_width
            scaling = (NUM_BUCKETS[i] - 1) / bound_width
            discrete_state = int(round(scaling * state[i] - offset))
        discrete_states.append(discrete_state)
    return tuple(discrete_states)

Schritt 3: Aktualisiere die Q-Tabelle

Die Bellman-Gleichungen zeigen, wie man die Q-Werte anhand der Lernrate, des Diskontsatzes, der Belohnung für den nächsten Schritt und des erwarteten maximalen Q-Werts des nächsten Zustands aktualisiert. Es drückt den erwarteten Wert eines Zustands als Summe zweier Teile aus: 

  • Die sofortige Belohnung beim Übergang in den nächsten Zustand
  • Der diskontierte erwartete Wert des nächsten Zustands 

Die Bellman-Gleichung ist rekursiv. So kann man ein Programm schreiben, das immer wieder von einem zufälligen Anfangszustand startet, um die beste Aktionswertfunktion zu finden. 

Die Formel zum Aktualisieren der Q-Tabelle lautet: 

In dem obigen Ausdruck: 

  • Der aktuelle Status ist st, im Code als state_current (Aktiv) bezeichnet.
  • Der nächste Zustand ist st+1 (state_next).
  • Die im aktuellen Status durchgeführte Aktion ist einet (action).
  • F(st, at) ist der aktuelle Q-Wert für den Zustand st und der Aktion at
  • α ist die Lernrate.
  • γ ist der Abzinsungsfaktor.
  • rt+1 ist die Belohnung nach der Aktion at im aktuellen Schritt mit Zustand st. Der Code unten zeigt das als reward “.
  • argmaxa Q(st+1, a) ist der maximale Q-Wert des nächsten Zustands. st+1. Im folgenden Code-Schnipsel wird das so dargestellt: best_q.

Der Code unten macht die Funktion zum Aktualisieren der Q-Tabelle klar.

def update_q(state_current, state_next, action, reward, alpha):
    best_q = np.amax(q_table[state_next])
    q_table[state_current + (action,)] += alpha * (reward + GAMMA*(best_q) - q_table[state_current + (action,)])
    return best_q

Schritt 4: Den Agenten schulen

Erkläre die Parameter des Trainings: 

  • Die maximale Anzahl an Trainingseinheiten
  • Die maximale Anzahl an Schritten pro Episode steht in der Dokumentation der Umgebung. For CartPole-v1, it is 500. 
  • Die Anzahl der Schritte, die der Agent machen muss, damit die Episode als Erfolg gewertet wird. Wir haben es auf 450 eingestellt. 
  • Die Anzahl der erfolgreichen Episoden, die der Agent hintereinander schaffen muss, damit das Training als erfolgreich gilt. Wir haben es auf 50 eingestellt. 
MAX_EPISODES = 5000
MAX_STEPS = 500
SUCCESS_STEPS = 450
SUCCESS_STREAK = 50

Die Hyperparameter angeben:

  • Die minimalen und maximalen Werte der Erkundungsrate ε
  • Die minimalen und maximalen Werte der Lernrate α
  • Die Zerfallsrate von α und γ
  • Der Abzinsungsfaktor γ
EPSILON_MIN = 0.01
EPSILON_MAX = 1
ALPHA_MIN = 0.1
ALPHA_MAX = 0.5
GAMMA = 0.99
DECAY_COEFF = 25

Bevor wir den Agenten trainieren, schreiben wir zwei Funktionen, um die Lernrate und die Erkundungsrate nach und nach zu verringern. Diese Hyperparameter werden im Laufe des Trainings immer kleiner. 

def decay_epsilon(step):
    return max(EPSILON_MIN, min(EPSILON_MAX, 1.0-math.log10((step+1)/DECAY_COEFF)))

def decay_alpha(step):
    return max(ALPHA_MIN, min(ALPHA_MAX, 1.0-math.log10((step+1)/DECAY_COEFF)))

Wir schreiben auch eine Funktion, um die Aktion zufällig auszuwählen. Zuerst machen wir eine Zufallszahl. 

  • Wenn diese Zufallszahl kleiner als ε ist, wählen wir zufällig eine Aktion aus dem Aktionsraum aus. Das ist die Strategie, wie wir das angehen werden. 
  • Wenn die Zufallszahl größer als ε ist, nehmen wir die Aktion, die dem höchsten Q-Wert entspricht. Das ist die Strategie, die ausnutzt. 
def select_action(state, epsilon):
    if random.random() < epsilon:
        action = env.action_space.sample()
    else:
        action = np.argmax(q_table[state])
    return action

Wir bauen eine Schleife auf, um den Agenten anhand der folgenden Schritte zu trainieren:

  • Hol die verfallenen Werte von α, und ε für die aktuelle Episode.
  • Setze die Umgebung zurück und zerlege den Beobachtungsraum, um eine neue Umgebung für die Episode zu starten. 
  • Lass den Agenten in der Umgebung laufen, bis er die maximale Anzahl an Schritten erreicht hat oder beendet wird. 
  • Für jeden Schritt:
    • Wähle die Aktion entsprechend der zuvor deklarierten Funktion „ select_action() aus.
    • Mach die Aktion in der Umgebung, um die Belohnung und den nächsten Zustand zu bekommen. 
    • Hol dir den höchsten Q-Wert aus der Q-Tabelle. 
    • Aktualisiere die Q-Tabelle mit der zuvor definierten Funktion „ update_q() “.

Der Code unten zeigt, wie die Trainingsschleife funktioniert:

def train():
    successful_episodes = 0
    for episode in range(MAX_EPISODES):
        epsilon = decay_epsilon(episode)
        alpha = decay_alpha(episode)
        observation, _ = env.reset()
        state_current = discretize_state(observation)
        for step in range(MAX_STEPS):
            action = select_action(state_current, epsilon)
            observation, reward, terminated, truncated, _ = env.step(action)
            done = terminated or truncated
            state_next = discretize_state(observation)
            best_q = update_q(state_current, state_next, action, reward, alpha)
            state_current = state_next
            if done:
                print("Episode %d finished after %d time steps" % (episode, step))
                print("best q value: %f" % (float(best_q)))
                if (step >= SUCCESS_STEPS):
                    successful_episodes += 1
                    print("=============SUCCESS=============")
                else:
                    successful_episodes = 0
                    print("=============FAIL=============")
                break
            if successful_episodes > SUCCESS_STREAK:
                break

Zum Schluss startest du die Trainingsschleife, schließt die Umgebung und druckst den letzten Wert der Q-Tabelle aus. 

train()
env.close()
print(q_table)

Nutze diese DataLab-Arbeitsmappe als Ausgangspunkt, um den Code für Q-Learning zu bearbeiten und auszuführen. 

Erweiterung auf Deep Q-Learning

Im vorherigen Abschnitt haben wir den kontinuierlichen (Zustands-)Beobachtungsraum diskretisiert, um eine Q-Tabelle zu verwenden. Eine große Q-Tabelle (für komplexe Umgebungen) ist rechnerisch ziemlich ineffizient. In solchen Fällen kann die Q-Funktion mit einem neuronalen Netzwerk angenähert werden. Das nennt man ein Deep Q-Netzwerk, ausgedrückt als Q(s, a; θ), wobei der Parameter θ die Gewichte des neuronalen Netzwerks darstellt. Diese Methode heißt Deep Q-Learning. Allgemeiner wird RL mit tiefen neuronalen Netzen als Deep Reinforcement Learning bezeichnet. 

Anstatt die Q-Tabelle zu benutzen, um die Aktion für jeden Zustand zu wählen, nimmt das DQN-neuronale Netzwerk den Zustand als Input und gibt den Q-Wert für jede mögliche Aktion in diesem Zustand zurück. 

Das Netzwerk wird mit klassischen Methoden (wie Backpropagation) trainiert, um den zeitlichen Differenzfehler (TD-Fehler) zu minimieren. Der TD-Fehler δ ist die Differenz zwischen den vorhergesagten Q-Werten und den Ziel-Q-Werten (berechnet als Summe der Belohnung aus dem aktuellen Zustand und dem diskontierten Wert der erwarteten maximalen Belohnung aus dem nächsten Zustand). 

Wenn man das als neuronales Netzwerk (mit Netzwerkparametern θ) macht, sieht der TD-Fehler so aus:

Beachte, dass sowohl die Q-Werte als auch die Ziel-Q-Werte mit demselben neuronalen Netzwerk berechnet werden. 

Bei jeder Wiederholung werden die Netzwerkparameter (θ) aktualisiert. Das Netzwerk-Update (über Backprop) basiert auf dem Zielwert, der mit dem vor dem Update berechneten θ ermittelt wurde. Berechnung der Zielwerte mit denselben aktualisierten Ergebnissen bei einem sich ständig bewegenden Ziel. Das macht das Training unsicher. 

Um das oben genannte Problem zu vermeiden, erstellen wir ein neues Netzwerk, um die Ziel-Q-Werte zu berechnen. Das ist das Zielnetzwerk. Es basiert auf denselben Parametern wie das Politiknetzwerk, wird aber nicht so oft aktualisiert. So hat der Trainingsprozess ein klares Ziel, auf das die Rückwärtsausbreitung angewendet wird. 

Wenn wir die Gewichte des Zielnetzwerks mit θ- darstellen, sieht die obige Gleichung so aus:

In den nächsten Abschnitten zeigen wir dir, wie du ein einfaches DQN in der CartPole-Umgebung umsetzt und trainierst. 

Beispiel für die Umsetzung

Installier die benötigten Pakete, wie Gymnasium und PyTorch. 

!pip install gymnasium matplotlib torch

Importiere die benötigten Pakete in die Python-Umgebung: 

import gymnasium as gym
import math
import random
import matplotlib
import matplotlib.pyplot as plt
from collections import namedtuple, deque
from itertools import count

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F

Erstell die CartPole-Umgebung: 

env = gym.make("CartPole-v1")

Initialisiere die Umgebung und erkläre Python-Konstanten mit der Größe der Zustands- und Aktionsräume der Umgebung. 

state, info = env.reset()
NUM_OBSERVATIONS = len(state)
NUM_ACTIONS = env.action_space.n

Deklarier eine Python-Klasse für ein einfaches neuronales Netzwerk mit einer einzigen versteckten Schicht. Die Anzahl der Eingabeschichten ist die Größe des Zustandsraums (Beobachtungsraums). Die Anzahl der Ausgabeschichten ist die Anzahl der möglichen Aktionen, die der RL-Agent ausführen kann. Dieses Netzwerk simuliert intern die Q-Tabelle und sagt die Aktionswerte für einen bestimmten Eingabestatus voraus. 

class DQN(nn.Module):

    def __init__(self, NUM_OBSERVATIONS, NUM_ACTIONS):
        super(DQN, self).__init__()
        self.layer1 = nn.Linear(NUM_OBSERVATIONS, 128)
        self.layer2 = nn.Linear(128, 128)
        self.layer3 = nn.Linear(128, NUM_ACTIONS)

    def forward(self, x):
        x = F.relu(self.layer1(x))
        x = F.relu(self.layer2(x))
        return self.layer3(x)

Mach dir ein Netzwerk für deine Richtlinien und ein Zielnetzwerk. Lade das Zielnetzwerk mit den Parametern des Richtliniennetzwerks über das Statuswörterbuch. Starte einen Optimierer, um das neuronale Netzwerk zu trainieren. 

policy_net = DQN(NUM_OBSERVATIONS, NUM_ACTIONS)
target_net = DQN(NUM_OBSERVATIONS, NUM_ACTIONS)
target_net.load_state_dict(policy_net.state_dict())

optimizer = optim.AdamW(policy_net.parameters(), lr=LR, amsgrad=True)

Training mit Wiederholungs-Puffer

Off-Policy-Modellfreie RL-Methoden wie Q-Learning (im vorherigen Abschnitt besprochen) und DQNs werden mit einer zufälligen Auswahl der Interaktionen des Agenten mit der Umgebung trainiert. Die Aktionen des Agenten und die Reaktionen der Umgebung (Belohnung und nächster Zustand) werden gesammelt und gespeichert. In jeder Trainingsrunde wird eine zufällige Auswahl dieser Interaktionen genommen, um einen Trainingsstapel zu bilden. 

Deklarier ein Tupel-Objekt, um den Zustand der Umgebung (Beobachtung) bei jeder Interaktion zu speichern:

Transition = namedtuple('Transition', ('state', 'action', 'next_state', 'reward'))

Erstell eine Python-Klasse für den Wiedergabepuffer:

class ReplayMemory(object):

    def __init__(self, capacity):
        self.memory = deque([], maxlen=capacity)

    def push(self, *args):
        self.memory.append(Transition(*args))

    def sample(self, batch_size):
        return random.sample(self.memory, batch_size)

    def __len__(self):
        return len(self.memory)

Erstell ein Speicherobjekt, um viele Interaktionen zu speichern. Diese Interaktionen werden benutzt, um den Agenten zu trainieren. 

memory = ReplayMemory(10000)

Vor dem Training musst du die Parameter und Hyperparameter angeben:

  • Parameter: 
    • Chargengröße
    • Maximale Anzahl von Trainingseinheiten
  • Hyperparameter:
    • Lernrate (LR)
    • Diskontierungsfaktor (GAMMA)
    • Die Aktualisierungsrate des Zielnetzwerks (TAU)
    • Anfangs- und Endwerte der Erkundungsrate und der Abklingrate (EPS_START, EPS_END und EPS_DECAY)
MAX_EPISODES = 600
BATCH_SIZE = 128

GAMMA = 0.99
EPS_START = 0.9
EPS_END = 0.05
EPS_DECAY = 1000
TAU = 0.005
LR = 1e-4

Schreib eine Funktion, die die Aktion anhand der Erkundungsrate auswählt, und zwar so:

  • Berechne die Erkundungsrate anhand der Anzahl der Schritte in der Episode (sowie der Anfangs- und Endwerte und der Abklingrate der Erkundungsrate). 
  • Erzeuge eine Zufallszahl. 
    • Wenn die Zufallszahl größer als die Erkundungsrate ist, wähle die vom Richtliniennetzwerk vorhergesagte Aktion. 
    • Wenn sie kleiner als die Erkundungsrate ist, wähle eine zufällige Aktion aus dem Aktionsraum aus. 
steps_done = 0
def select_action(state):
    global steps_done
    sample = random.random()
    eps_threshold = EPS_END + (EPS_START - EPS_END) * \
        math.exp(-1. * steps_done / EPS_DECAY)
    steps_done += 1
    if sample > eps_threshold:
        with torch.no_grad():
            action = policy_net(state).max(1).indices.view(1, 1)
            return action
    else:
        action = torch.tensor([[env.action_space.sample()]], dtype=torch.long)
        return action

Schreib die Funktion, um das Modell anhand dieser Schritte zu optimieren:

  • Erstell einen Stapel mit einer zufälligen Auswahl der Interaktionen des Agenten mit der Umgebung. Jeder Punkt in der Probe ist ein Schritt. Es enthält:
    • Der aktuelle Zustand der Umwelt
    • Die Aktion des Agenten
    • Die Belohnung erhalten
    • Der nächste Staat
  • Bei CartPole soll der Agent den Wagenstange weiter bewegen, ohne dass er stoppt (an die Kanten stößt oder umfällt). Deshalb schauen wir nur auf Interaktionen, die nicht zu einem Endzustand führen. Wir erstellen eine Maske (non_final_mask), um die Zustände zu erkennen, auf die kein Endzustand folgt.
  • Finde die Zustände, die nicht von einem Endzustand gefolgt werden (non_final_next_states).
  • Hol dir die Aktionswerte für alle aktuellen Zustände. st , indem du die aktuellen Zustände an das Richtliniennetzwerk weitergibst.
  • Hol dir die erwarteten Zustandsaktionswerte für alle nächsten Zustände. st+1 , indem du die nächsten Zustände an das Zielnetzwerk weitergibst unddie folgende Gleichung verwendest:

  • Berechne den Verlust anhand der Differenz zwischen den Aktionswerten und den erwarteten Aktionswerten:

  • Verteile die Verluste zurück, um dieGradienten zu berechnen.
  • Die Gradientenwerte beschneiden und das Policy-Netzwerk aktualisieren, um ein stabiles Training zu gewährleisten. 

Der Code unten zeigt, wie man den Optimierer einsetzt:

batch = 0
def optimize_model():
    global batch
    if len(memory) < BATCH_SIZE:
        return
    transitions = memory.sample(BATCH_SIZE)
    batch = Transition(*zip(*transitions))

    non_final_mask = torch.tensor(tuple(map(lambda s: s is not None,
                                          batch.next_state)), dtype=torch.bool)
    non_final_next_states = torch.cat([s for s in batch.next_state
                                                if s is not None])
    state_batch = torch.cat(batch.state)
    action_batch = torch.cat(batch.action)
    reward_batch = torch.cat(batch.reward)

    state_action_values = policy_net(state_batch).gather(1, action_batch)
    next_state_values = torch.zeros(BATCH_SIZE )

    with torch.no_grad():
        next_state_values[non_final_mask] = target_net(non_final_next_states).max(1).values

    expected_state_action_values = (next_state_values * GAMMA) + reward_batch

    loss_func = nn.SmoothL1Loss()
    loss = loss_func(state_action_values, expected_state_action_values.unsqueeze(1))

    optimizer.zero_grad()
    loss.backward()

    torch.nn.utils.clip_grad_value_(policy_net.parameters(), 100)
    optimizer.step()

Schreib eine Trainingsschleife, um den Agenten zu trainieren:

  • Mach alles zurück und fang eine neue Folge an.
  • Benutz die Funktion „ select_action() “, um zu entscheiden, was der Agent machen soll.
  • Hol dir die Belohnung der Umgebung und den nächsten Status basierend auf der Aktion.
  • Füge den Zustand, die Aktion, den nächsten Zustand und die Belohnung zum Wiederholungs-Puffer hinzu.
  • Führ den Optimierer aus (wie oben definiert). Der Optimierer berechnet die Q-Werte und den Verlust und nutzt Backpropagation, um das Netzwerk zu aktualisieren. 
  • Aktualisiere das Zielnetzwerk nach dem Richtliniennetzwerk.
  • Mach mit der Episode weiter, bis sie fertig ist.

Der folgende Code macht das klar: 

def train():
    for episode in range(MAX_EPISODES):
        # Initialize the environment and get its state
        state, info = env.reset()
        state = torch.tensor(state, dtype=torch.float32).unsqueeze(0)
        for t in count():
            action = select_action(state)
            observation, reward, terminated, truncated, _ = env.step(action.item())
            reward = torch.tensor([reward])
            done = terminated or truncated

            if terminated:
                next_state = None
            else:
                next_state = torch.tensor(observation, dtype=torch.float32).unsqueeze(0)

            memory.push(state, action, next_state, reward)
            state = next_state
            optimize_model()

            target_net_state_dict = target_net.state_dict()
            policy_net_state_dict = policy_net.state_dict()
            for key in policy_net_state_dict:
                target_net_state_dict[key] = policy_net_state_dict[key]*TAU + target_net_state_dict[key]*(1-TAU)
            target_net.load_state_dict(target_net_state_dict)

            if done:
                episode_durations.append(t + 1)
                print('episode -- ', episode)
                print('count -- ', t)
                #plot_durations()
                break

Mit dieser DataLab-Arbeitsmappe kannst du das DQN-Trainingsprogramm anzeigen, bearbeiten und ausführen. 

Die Handlungswertfunktion visualisieren

Es ist hilfreich, den Fortschritt des Trainingsprozesses visuell auf einem Lernpfad zu verfolgen. Die Werte der Aktionen zu sehen, hilft dabei, zu erkennen, wo das Training nicht so gut läuft und welche Parameter oder Hyperparameter angepasst werden müssen. 

Wenn du zum Beispiel siehst, dass das Modell nicht schnell genug besser wird, solltest du vielleicht die Lernrate erhöhen. Wenn du merkst, dass das Modell zwar lernt, aber noch nicht ganz fertig trainiert ist, kann es helfen, die Anzahl der Trainingseinheiten zu erhöhen. Wenn du merkst, dass das Training nicht so läuft, wie es soll, solltest du vielleicht die Lernrate runterdrehen oder den Erkundungskoeffizienten oder die Aktualisierungsrate des Zielnetzwerks anpassen (TAU).

Zusätzlich zu den Q-Werten kann es auch hilfreich sein, die Anzahl der erfolgreichen Schritte in jeder Episode aufzuzeichnen. Beim Q-Learning mit Q-Tabellen werden die Q-Werte explizit gespeichert. Bei der Verwendung von DQNs werden die Q-Werte aber nicht explizit gespeichert. Das Netzwerk gibt die Aktion je nach ihren Gewichten und dem Status aus. Deshalb kann es für DQN sinnvoller sein, die Anzahl der erfolgreichen Schritte in jeder Episode zu verfolgen. 

Die folgenden Schritte zeigen, wie du die Q-Werte und die Anzahl der erfolgreichen Schritte pro Episode für das Training des Q-Learning-Algorithmus zeichnest:

  • Erstelle zu Beginn des Trainings zwei leere Arrays:
    • q_vals - zum Speichern der Q-Werte in jedem Schritt jeder Episode. 
    • success_steps - zum Speichern der Anzahl der erfolgreichen Schritte in jeder Episode.
  • Bei jedem Schritt (in allen Episoden):
    • Füge den Q-Wert für diesen Schritt zum Array „ q_vals hinzu.
  • Nach jeder Episode füge zum Array „ success_steps “ die Anzahl der erfolgreichen Schritte in dieser Episode hinzu.
  • Zeichne beide Arrays auf. 

Der Code unten zeigt die Q-Learning-Trainingsschleife (mit Q-Tabellen) (siehe vorheriger Abschnitt), die aktualisiert wurde, um die Q-Werte und die Anzahl der erfolgreichen Schritte zu verfolgen:

q_vals = []
success_steps = []

def train():
    global q_vals 
    global success_steps
    successful_episodes = 0

    for episode in range(MAX_EPISODES):
        epsilon = decay_epsilon(episode)
        alpha = decay_alpha(episode)
        observation, _ = env.reset()
        state_current = discretize_state(observation)

        for step in range(MAX_STEPS):
            action = select_action(state_current, epsilon)
            observation, reward, terminated, truncated, _ = env.step(action)
            done = terminated or truncated
            state_next = discretize_state(observation)
            best_q = update_q(state_current, state_next, action, reward, alpha)
            q_vals.append(best_q)
            state_current = state_next

            if done:
                q_vals.append(best_q)
                success_steps.append(step)
                print("Episode %d finished after %d time steps" % (episode, step))
                print("best q value: %f" % (float(best_q)))
                if (step >= SUCCESS_STEPS):
                    successful_episodes += 1
                else:
                    successful_episodes = 0
                break

            if successful_episodes > SUCCESS_STREAK:
                print("Training successful")
                return

Der folgende Ausschnitt zeigt, wie man die Q-Werte in jeder Episode darstellt:

def plot_q():
    plt.plot(q_vals)
    plt.title('Q-values over training steps')
    plt.xlabel('Training steps')
    plt.ylabel('Q-value')
    plt.show()

Der folgende Ausschnitt zeigt, wie du die Anzahl der erfolgreichen Schritte in jeder Episode zeichnest:

def plot_steps():
    plt.plot(success_steps)
    plt.title('Successful steps over training episodes')
    plt.xlabel('Training episode')
    plt.ylabel('Successful steps')
    plt.show()

Die Leistung der Agenten checken

Man muss festlegen, wann der Agent gut trainiert ist. Beim klassischen ML geht's beim Training darum, den Verlust zu minimieren, also den Unterschied zwischen den vorhergesagten und den echten Werten. In RL geht's darum, die Gesamtbelohnung so hoch wie möglich zu machen. Das Training gilt als erfolgreich, wenn der Agent die maximale Belohnung aus der Umgebung bekommt. 

Umgebungen wie CartPole enden erst, wenn sie einen Endzustand erreichen, z. B. wenn sie an die Ränder stoßen oder sich der Cartpole zu stark neigt. In solchen Fällen kann ein geschulter Agent unbegrenzt mit der Umgebung interagieren. So wird die maximale Anzahl erfolgreicher Schritte künstlich begrenzt. Bei CartPole-v1 von Gymnasium wird die Episode beendet, wenn 500 Zeitschritte ohne Abbruch erreicht sind. 

Wir checken, wie gut der Agent in aufeinanderfolgenden Episoden abschneidet, um zu sehen, ob das Training funktioniert. Zum Beispiel: 

  • Der Agent sollte in der Lage sein, im Durchschnitt der letzten N Episoden mehr als eine bestimmte Anzahl von Schritten (SUCCESS_STEPS) zu absolvieren. In den Beispielen in diesem Artikel haben wir diesen Schwellenwert auf 450 gesetzt. 
  • Der Agent kann die Schwelle in N aufeinanderfolgenden Episoden überschreiten (SUCCESS_STREAK). In diesem Beispiel setzen wir N auf 50. 

Schau dir als praktisches Beispiel diesen Ausschnitt aus der zuvor gezeigten DQN-Trainingsschleife an. 

if done:
  episode_durations.append(t + 1)
  print('episode -- ', episode)
  average_steps = sum(episode_durations[-SUCCESS_STREAK:])/SUCCESS_STREAK
  print('average steps over last 50 episodes -- ', average_steps)
  if average_steps > SUCCESS_STEPS:
      print("training successful.")
      return
  break

Es ist hilfreich, die Leistung des Agenten anhand der folgenden Schritte am Ende (Endzustand) jeder Trainingseinheit zu bewerten:

  • Füge die Gesamtzahl der Schritte in dieser Episode (vor ihrem Ende) zu einem Array hinzu. Dieser Array verfolgt die Gesamtzahl der Schritte in jeder Episode. 
  • Berechne den Durchschnitt der letzten N Werte in diesem Array. In diesem Beispiel ist N (SUCCESS_STREAK) gleich 50. Also, wir rechnen die durchschnittlichen Schritte der letzten 50 Folgen aus. 
  • Wenn dieser Durchschnitt über einem Schwellenwert (SUCCESS_STEPS) liegt, beenden wir das Training. In diesem Beispiel ist der Schwellenwert auf 450 Schritte gesetzt. 

Tipps für die Verwendung von Aktionswertfunktionen

Hier sind ein paar Tipps, die du befolgen kannst, um mit deiner Action-Value-Funktion bessere Ergebnisse zu erzielen. 

Erkundung und Nutzung in der richtigen Balance

Mit der richtigen Aktionswertfunktion kann der Agent die erwarteten Erträge maximieren, indem er eine gierige Strategie verfolgt, bei der er in jedem Schritt die Aktion mit dem höchsten Wert wählt. Das nennt man Ausnutzung der verfügbaren Infos. Wenn man aber eine gierige Strategie mit einer ungetraineden Aktionswertfunktion (die noch nicht die echten Aktionswerte zeigt) benutzt, bleibt man in einem lokalen Optimum hängen. 

Während des Trainings ist es wichtig, sowohl die Umgebung zu erkunden als auch die verfügbaren Infos zu nutzen. 

In den ersten Phasen des Trainingsprozesses basieren die verfügbaren Infos auf einer Zufallswertfunktion. Daher sind diese Infos nicht besonders wertvoll (um sie mit einer gierigen Strategie zu nutzen). Es ist wichtiger, die Umgebung zu erkunden, um herauszufinden, was man mit verschiedenen Aktionen in unterschiedlichen Situationen erreichen kann. 

Wenn die Q-Tabelle aktualisiert wird (oder das DQN trainiert wird), kann man die verfügbaren Infos teilweise nutzen, um die Belohnungen zu maximieren. Gegen Ende des Trainings nähert sich der Agent der echten Wertfunktion an; mehr zu suchen könnte schaden. Deshalb konzentriert sich der Agent darauf, die bekannte Wertfunktion zu nutzen. 

Hyperparameter anpassen

Wie bei jedem maschinellen Lernmodell sind Hyperparameter wichtig, um RL-Algorithmen erfolgreich zu trainieren. Bei Q-Learning und DQNs sind die Hyperparameter Epsilon (Erkundungsrate), Alpha (Lernrate) und Gamma (Diskontierungsrate). 

  • ε ( Epsilon) regelt das Gleichgewicht zwischen Exploration und Exploitation (wie oben besprochen). Je höher der Epsilon-Wert, desto wichtiger ist die Exploration im Vergleich zur Ausbeutung. Zu Beginn des Trainings hat er einen hohen Wert wie 0,9, der gegen Ende des Trainings langsam auf einen kleinen Wert wie 0,05 sinkt.
  • α ( alpha) ist die Lernrate (LR). Sie steuert, wie stark sich die Parameter des neuronalen Netzwerks (im Fall von DQNs) oder die Werte der Q-Tabelle bei jeder Trainingsiteration ändern. Wenn der LR-Wert zu hoch ist, wird das Modell instabil und konvergiert nicht. Andererseits führt ein niedriger LR-Wert zu einer langsamen Konvergenz. Es ist auch üblich, zu Beginn des Trainingsprozesses mit einem hohen LR-Wert zu starten, wenn der Agent die Umgebung erkunden muss. Je näher man den echten Werten der Q-Funktion kommt, desto kleiner wird der LR, damit das Netzwerk besser zusammenläuft.
  • γ (Gamma) ist der Diskontsatz. Es entscheidet, wie wichtig Belohnungen in späteren Zeitabschnitten im Vergleich zu sofortigen Belohnungen sind. Ein hoher Gamma-Wert bedeutet, dass spätere Belohnungen wichtig sind.  Ein Gamma-Wert von 0 heißt, dass nur die Belohnung aus dem aktuellen Zeitschritt wichtig ist und spätere Belohnungen keine Rolle spielen. Bei Algorithmen wie Q-Learning hängt der Gesamtertrag von den Belohnungen ab, die während der ganzen Episode erzielt wurden. Daher ist es üblich, einen hohen Diskontsatz wie 0,99 zu verwenden.

Zu guter Letzt solltest du wissen, dass RL-Training empfindlich auf anfängliche Zufallswerte reagiert. Wenn das Training nicht konvergiert, hilft es oft, einen anderen Zufallsstartwert zu verwenden oder das Training neu zu starten, damit es mit anderen zufälligen Anfangswerten beginnt. 

Fang mit einfachen Umgebungen an

Das Training von RL-Agenten für komplexe Umgebungen ist echt eine Herausforderung. Q-Funktionen werden in vielen verschiedenen Algorithmen verwendet, daher ist es wichtig, ein Gefühl dafür zu entwickeln, wie man Q-Learning-basierte RL-Agenten trainiert. Das geht am besten, indem du die Techniken erst mal in einfacheren Umgebungen wie CartPole ausprobierst, bevor du ähnliche Methoden in komplexeren Umgebungen anwendest. 

Außerdem ist das Training in komplizierten Umgebungen teurer, sodass es günstiger ist, einfachere Umgebungen als Lernwerkzeug zu nutzen. 

Fazit

In diesem Artikel haben wir die grundlegenden theoretischen Prinzipien der Aktionswertfunktion und ihre Bedeutung in RL besprochen. Wir haben uns angesehen, wie Aktionswertfunktionen beim Q-Learning und Deep Q-Learning verwendet werden, und beide Methoden Schritt für Schritt in Python umgesetzt.

Um weiterzulernen, empfehle ich dirden Kurs „Deep Reinforcement Learning in Python ”.

Verdiene eine Top-KI-Zertifizierung

Zeige, dass du KI effektiv und verantwortungsbewusst einsetzen kannst.

Häufig gestellte Fragen

Was ist der Unterschied zwischen einer Wertfunktion und einer Aktionswertfunktion in RL?

Die Wertfunktion schätzt den erwarteten Ertrag aus einem Zustand, während die Aktionswertfunktion (Q-Funktion) den Ertrag aus einer bestimmten Aktion in einem Zustand und der anschließenden Umsetzung der Strategie schätzt. Die Aktionswertfunktion gibt dir genauere Tipps für deine Entscheidungen.

Warum ist die Aktionswertfunktion beim Q-Learning so wichtig?

Q-Learning nutzt die Aktionswertfunktion, um den Agenten zu Handlungen zu führen, die die höchsten erwarteten Belohnungen bringen. Die Funktion macht Off-Policy-Lernen möglich und hilft dem Agenten, mit der Zeit die beste Strategie zu finden.

Wie hängt die Aktionswertfunktion mit der Bellman-Gleichung zusammen?

Die Bellman-Gleichung bietet eine rekursive Formel, um die Q-Werte anhand der unmittelbaren Belohnung und der diskontierten maximalen zukünftigen Belohnung zu aktualisieren. Das ist die Basis, um die Handlungswertfunktion immer wieder zu lernen.

Kann ich die Aktionswertfunktion in kontinuierlichen Zustandsräumen verwenden?

Ja, aber Q-Tabellen sind in kontinuierlichen Räumen nicht so praktisch. In solchen Fällen werden Deep Q-Networks (DQNs) verwendet, um die Aktionswertfunktion mit einem neuronalen Netzwerk anstelle von expliziten Tabellen zu approximieren.

Welche Rolle spielt die Erkundung bei der Schätzung der Aktionswertfunktion?

Durch das Ausprobieren wird sichergestellt, dass der Agent nicht zu früh bei einer suboptimalen Strategie bleibt. Es hilft dem Agenten, verschiedene Erfahrungen zu sammeln, die wichtig sind, um die Aktionswertfunktion während des Trainings richtig einzuschätzen.

Wie wirkt sich die ε-greedy-Strategie auf das Q-Wert-Lernen aus?

Die ε-greedy-Strategie sorgt für ein Gleichgewicht zwischen Erkundung und Ausnutzung. Mit einer Wahrscheinlichkeit ε probiert der Agent neue Aktionen aus und mit 1–ε nutzt er die aktuell beste bekannte Aktion. Dieser Kompromiss macht das Lernen stabiler und konvergenter.

Wann solltest du von Q-Learning zu Deep Q-Learning wechseln?

Wenn die Umgebung einen großen oder kontinuierlichen Zustandsraum hat, ist die Pflege einer Q-Tabelle nicht mehr so gut. Deep Q-Learning ersetzt die Tabelle durch ein neuronales Netzwerk, das sich besser an komplexe Umgebungen anpasst.

Wie kann ich mir eine Aktionswertfunktion während des Trainings vorstellen?

Du kannst die maximalen Q-Werte über die Zeit aufzeichnen oder die Belohnungen für Episoden verfolgen, um den Lernfortschritt zu überwachen. Visualisierung hilft dabei, Probleme wie schlechte Konvergenz oder unzureichende Erkundung zu erkennen.

Was sind die größten Herausforderungen beim Training einer Aktionswertfunktion?

Zu den Herausforderungen gehören Instabilität beim Training wegen sich ändernder Ziele, schlechte Erkundung und nicht so tolle Hyperparameter-Einstellungen. Techniken wie Wiederholungsgedächtnis und Zielnetzwerke helfen dabei, diese Probleme zu lösen.

Wird die Aktionswertfunktion in On-Policy-Algorithmen verwendet?

Ja, Algorithmen wie SARSA nutzen die Aktionswertfunktion, aber sie aktualisieren sie anhand der Aktion, die gerade gemacht wurde. Das ist anders als bei Off-Policy-Methoden wie Q-Learning, die den maximalen Q-Wert des nächsten Zustands nutzen.


Arun Nanda's photo
Author
Arun Nanda
LinkedIn

Arun ist ein ehemaliger Startup-Gründer, der Spaß daran hat, neue Dinge zu entwickeln. Derzeit erforscht er die technischen und mathematischen Grundlagen der Künstlichen Intelligenz. Er liebt es, sein Wissen mit anderen zu teilen, also schreibt er darüber.

Neben dem DataCamp kannst du seine Veröffentlichungen auf Medium, Airbyte und Vultr lesen.

Themen

Lerne mit diesen Kursen mehr über KI!

Lernpfad

Grundlagen des maschinellen Lernens in Python

0 Min.
Lerne die Kunst des maschinellen Lernens und werde zum Meister der Vorhersage, der Mustererkennung und der Anfänge des Deep und Reinforcement Learning.
Siehe DetailsRight Arrow
Kurs starten
Mehr anzeigenRight Arrow
Verwandt

Der Blog

Arten von KI-Agenten: Ihre Rollen, Strukturen und Anwendungen verstehen

Lerne die wichtigsten Arten von KI-Agenten kennen, wie sie mit ihrer Umgebung interagieren und wie sie in verschiedenen Branchen eingesetzt werden. Verstehe einfache reflexive, modellbasierte, zielbasierte, nutzenbasierte, lernende Agenten und mehr.
Vinod Chugani's photo

Vinod Chugani

14 Min.

Der Blog

Top 30 Generative KI Interview Fragen und Antworten für 2024

Dieser Blog bietet eine umfassende Sammlung von Fragen und Antworten zu generativen KI-Interviews, die von grundlegenden Konzepten bis hin zu fortgeschrittenen Themen reichen.
Hesam Sheikh Hassani's photo

Hesam Sheikh Hassani

15 Min.

Der Blog

Die 50 besten AWS-Interview-Fragen und Antworten für 2025

Ein kompletter Leitfaden zur Erkundung der grundlegenden, mittleren und fortgeschrittenen AWS-Interviewfragen, zusammen mit Fragen, die auf realen Situationen basieren.
Zoumana Keita 's photo

Zoumana Keita

15 Min.

Der Blog

Lehrer/innen und Schüler/innen erhalten das Premium DataCamp kostenlos für ihre gesamte akademische Laufbahn

Keine Hacks, keine Tricks. Schüler/innen und Lehrer/innen, lest weiter, um zu erfahren, wie ihr die Datenerziehung, die euch zusteht, kostenlos bekommen könnt.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

4 Min.

Der Blog

Q2 2023 DataCamp Donates Digest

DataCamp Donates hat im zweiten Quartal 2023 über 20.000 Stipendien an unsere gemeinnützigen Partner vergeben. Erfahre, wie fleißige benachteiligte Lernende diese Chancen in lebensverändernde berufliche Erfolge verwandelt haben.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

Der Blog

2022-2023 DataCamp Classrooms Jahresbericht

Zu Beginn des neuen Schuljahres ist DataCamp Classrooms motivierter denn je, das Lernen mit Daten zu demokratisieren. In den letzten 12 Monaten sind über 7.650 neue Klassenzimmer hinzugekommen.
Nathaniel Taylor-Leach's photo

Nathaniel Taylor-Leach

8 Min.

Mehr anzeigenMehr anzeigen