Recurrent Neural Network (RNN)
Ein rekurrentes neuronales Netz (RNN) verarbeitet eine Sequenz Schritt für Schritt und führt dabei einen verborgenen Zustand weiter. Behandelt Rekurrenz, Training, Varianten und Code.
Ein rekurrentes neuronales Netz (RNN) ist ein neuronales Netz, das eine Sequenz Element für Element verarbeitet und dabei einen verborgenen Zustand von einem Schritt zum nächsten weiterführt. So kann seine Ausgabe bei jedem Schritt von allem abhängen, was es bisher gelesen hat. In jedem Schritt werden dieselben Gewichte angewendet. Dadurch kann ein Netz Sequenzen beliebiger Länge verarbeiten – von einem Satz bis zu stundenlangen Sensormessungen. RNNs waren die wichtigste Architektur für die Verarbeitung natürlicher Sprache (NLP), Spracherkennung und Zeitreihenanalyse, bis Transformer sie Ende der 2010er-Jahre bei den meisten Sprachaufgaben ablösten. Ihre Gattervarianten sind für Streaming und Modelle auf dem Gerät weiterhin verbreitet. Rekurrenz erlebt mit Zustandsraummodellen (SSMs) wie Mamba ein Comeback.
Funktionsweise eines RNN#
Ein einfaches RNN, nach Jeffrey Elmans Arbeit aus dem Jahr 1990 auch Elman-Netz genannt, aktualisiert seinen verborgenen Zustand mit hₜ = tanh(Wxₜ + Uhₜ₋₁ + b) und kann bei jedem Schritt eine Ausgabe yₜ = Vhₜ + c erzeugen. Der verborgene Zustand ist ein Vektor fester Größe, der die bisherige Sequenz zusammenfasst. tanh hält seine Werte zwischen −1 und 1, während der Zustand zurückgeführt wird. Zeichnet man für jeden Schritt eine Kopie des Netzes, lässt sich die Schleife zu einem tiefen Feedforward-Netzwerk entfalten, dessen Schichten dieselben Gewichte verwenden:
Das folgende Snippet führt PyTorchs nn.RNN über eine Sequenz aus und wiederholt dieselbe Rekurrenz in einer einfachen Schleife:
import torch
from torch import nn
torch.manual_seed(0)
rnn = nn.RNN(input_size=3, hidden_size=4, batch_first=True)
x = torch.randn(1, 6, 3) # one sequence: 6 time steps, 3 features each
# PyTorch runs the whole sequence; output holds the hidden state after every step
output, h_n = rnn(x)
# The same recurrence by hand, reusing one set of weights at every step
h = torch.zeros(1, 4)
for t in range(x.shape[1]):
h = torch.tanh(x[:, t] @ rnn.weight_ih_l0.T + rnn.bias_ih_l0 + h @ rnn.weight_hh_l0.T + rnn.bias_hh_l0)
print(f"Output shape: {tuple(output.shape)}, final state shape: {tuple(h_n.shape)}")
print(f"Hand-written loop matches nn.RNN: {torch.allclose(h, h_n[0], atol=1e-6)}")Die Ausgabe lautet Output shape: (1, 6, 4), final state shape: (1, 1, 4) und Hand-written loop matches nn.RNN: True. Die Ausgabe enthält für jeden Zeitschritt einen verborgenen Zustand mit vier Dimensionen. Die Schleife berechnet den abschließenden Zustand mit nur einer Gewichtsmatrix für die Eingabe und einer für den vorherigen Zustand.
Sequenzaufgaben#
Dieselbe Rekurrenz eignet sich für Aufgaben mit unterschiedlich langen Eingabe- und Ausgabesequenzen:
- Viele zu eins: Eine vollständige Sequenz lesen und anhand des abschließenden Zustands klassifizieren, etwa bei der Sentimentanalyse oder der Kennzeichnung eines Zeitfensters mit Sensordaten.
- Viele zu viele: Bei jedem Schritt eine Ausgabe erzeugen, etwa für die Kennzeichnung jedes Worts eines Satzes oder jedes Audioframes.
- Sequenz zu Sequenz: Ein Encoder-RNN liest die Eingabe, und ein Decoder-RNN erzeugt eine Ausgabe anderer Länge. Dieses Design kam bei der frühen maschinellen Übersetzung und anderen Sequenz-zu-Sequenz-Modellen zum Einsatz.
- Eins zu viele: Eine Sequenz aus einer einzelnen Eingabe erzeugen, beispielsweise eine Bildbeschreibung aus dem Feature-Vektor eines Bildes bei frühen Modellen zur Bildbeschreibung.
Bidirektionale RNNs ergänzen ein zweites RNN, das die Sequenz rückwärts liest, und kombinieren bei jedem Schritt beide Zustände. So sieht jede Ausgabe den Kontext der Vergangenheit und der Zukunft. Bei gestapelten RNNs werden die verborgenen Zustände einer Schicht als Eingabesequenz an die nächste weitergegeben.
Training mit Backpropagation durch die Zeit#
RNNs werden mit Backpropagation durch die Zeit (BPTT) trainiert: Das Netz wird über die Sequenz entfaltet, der Verlust über die Schritte hinweg summiert und Backpropagation auf den entfalteten Graphen angewendet. Der Gradient, der bei Schritt t von Schritt T ankommt, durchläuft T − t Kopien der rekurrenten Schicht und wird jedes Mal mit U und der Ableitung von tanh multipliziert. Sind diese Faktoren meist kleiner als 1, nimmt der Gradient geometrisch ab. Dieses Problem des verschwindenden Gradienten untersuchten Yoshua Bengio, Patrice Simard und Paolo Frasconi 1994. Sind die Faktoren größer als 1, nimmt der Gradient geometrisch zu. Das ist das Problem des explodierenden Gradienten. Das folgende Snippet misst, wie stark jede Eingabe einer Sequenz mit 50 Schritten den abschließenden verborgenen Zustand beeinflusst:
import torch
from torch import nn
torch.manual_seed(0)
rnn = nn.RNN(input_size=8, hidden_size=32, batch_first=True)
x = torch.randn(1, 50, 8, requires_grad=True) # one 50-step sequence
# Backpropagate from the final hidden state to the input at every step
output, h_n = rnn(x)
h_n.sum().backward()
grad_norms = x.grad[0].norm(dim=1)
for distance in [0, 10, 20, 30, 40]:
print(f"Input {distance:>2} steps before the end: gradient {grad_norms[-1 - distance]:.1e}")Es gibt die Gradienten von 1.6e+00, 3.4e-03, 6.2e-06, 1.2e-08 und 1.1e-11 für Eingaben mit 0, 10, 20, 30 und 40 Schritten vor dem Ende aus. Alle zehn Schritte kosten etwa drei Größenordnungen, sodass das Training die Gewichte kaum anpassen kann, um eine Eingabe von einigen Dutzend Schritten zuvor zu nutzen. Gradientenbeschneidung, die Razvan Pascanu und Kollegen 2013 für RNNs untersuchten, begrenzt explodierende Gradienten. Abgeschnittenes BPTT beschränkt die Rückpropagation auf ein festes Fenster, um den Speicherbedarf zu begrenzen. Verschwindende Gradienten erfordern eine Änderung der Architektur. Genau das ermöglichen die Gates von LSTM und GRU.
RNNs und verwandte Architekturen im Vergleich#
- LSTM und GRU: Gate-basierte RNNs mit einer additiven Zustandsaktualisierung, durch die Informationen und Gradienten viele Schritte lang weitergegeben werden können. In der Praxis bezeichnet „RNN“ oft sowohl diese Modelle als auch das einfache RNN.
- Transformer: Berücksichtigt jede vorherige Position direkt, statt den Verlauf in einem Zustand zusammenzufassen, und verarbeitet alle Positionen parallel. Der Aufwand für die Attention wächst mit der Sequenzlänge. Bei einem RNN bleiben Rechenaufwand und Speicherbedarf für jeden neuen Schritt gleich.
- Faltungsneuronales Netz (CNN): Es verknüpft benachbarte Positionen mithilfe von Filtern fester Größe – räumlich in Bildern oder zeitlich mit 1D-Faltungen – und sein rezeptives Feld wird durch seine Tiefe bestimmt.
- Zustandsraummodelle: Lineare Rekursionen wie Mamba lassen sich mit einem Scan parallel trainieren und laufen bei der Inferenz wie ein RNN schrittweise ab. Flüssige neuronale Netze sind RNNs in kontinuierlicher Zeit, deren Neuronen Differentialgleichungen folgen.
Anwendungen#
- Tastaturvorhersage: Das Wortvorhersagemodell von Gboard basierte auf einem LSTM mit gekoppeltem Eingabe- und Vergessens-Gate, einer schlankeren LSTM-Variante. Es wurde mit föderiertem Lernen auf den Smartphones der Nutzer trainiert, wie Google-Forscher 2018 beschrieben.
- Nachfrageprognose: Amazons DeepAR trainiert ein autoregressives RNN für viele verwandte Zeitreihen und gibt für jeden zukünftigen Wert eine Wahrscheinlichkeitsverteilung aus.
- Audio-Streaming: Erkennungssysteme für Aktivierungswörter und Rauschunterdrücker verarbeiten Audio mit kleinen rekurrenten Schichten Frame für Frame. So bleiben Speicherbedarf und Latenz auf Smartphones und Ohrhörern konstant.
- Objektverfolgung: Ein Tracker führt für jedes Objekt einen Zustand von Frame zu Frame fort – ähnlich wie der verborgene Zustand eines RNN. Jeder in den Track-Modus von YOLO26 integrierte Tracker, von ByteTrack und BoT-SORT bis zum standardmäßigen TrackTrack, aktualisiert diesen Zustand mit einem Kalman-Filter. Dieser arbeitet mit einer linearen Rekursion und festgelegten Gleichungen für konstante Geschwindigkeit statt mit trainierten Gewichten.










