σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademySkills
Ctrl K
AO
+1,2 Tsd. Lernende
AnmeldenBeitreten ↗
Skills
AO
+1,2 Tsd. Lernende
Anmelden
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python-Skill›Modul 11 · Produktivsysteme und Spitzenmodelle›Thema 11.11·~1 Std. 30 Min.Experte

Neuronale Netze für Prognosen

Position in der SkillModul 11 von 11 · Thema 11 von 13
11.11 Neuronale Netze für Prognosen
—Lab-Punkte— / 100XP gesamt—Serie—

Eine Funktion mit Reglern und ein Weg, sie zu drehen

Ein neuronales Netz ist nur eine Funktion mit vielen einstellbaren Zahlen, den Gewichten. Eine Schicht multipliziert die Eingaben mit einer Gewichtsmatrix und addiert einen Bias; eine Nichtlinearität wie ReLU (max(x, 0)) wird angewandt; das Ergebnis speist die nächste Schicht. So gestapelt können solche Funktionen sehr komplizierte Zusammenhänge annähern. Training heißt, die Gewichte so zu wählen, dass die Vorhersagen bekannten Zielen entsprechen: Messen Sie die Abweichung mit einem Loss (für die Prognose einer Zahl der mittlere quadratische Fehler), berechnen Sie, wie sich der Loss mit jedem Gewicht ändert, und schieben Sie jedes Gewicht ein Stück in die Richtung, die ihn senkt. Dieser Schubs, tausendfach wiederholt, ist der Gradientenabstieg.

# A one-hidden-layer network: relu(x @ w1 + b1) @ w2 + b2
import numpy as np

def relu(x):
    return np.maximum(x, 0.0)

def mlp_forward(x, w1, b1, w2, b2):
    return relu(x @ w1 + b1) @ w2 + b2

x = np.array([[1.0, 2.0], [0.5, -1.0]])                       # two samples, two features
w1 = np.array([[1.0, -1.0], [0.5, 1.0]])                      # two hidden units
b1 = np.array([0.0, 0.5])
w2 = np.array([1.0, 2.0])
print(relu(np.array([-1.5, 0.0, 2.0])))                       # [0. 0. 2.]
print(mlp_forward(x, w1, b1, w2, 0.1))                        # [5.1 0.1]   a prediction for each sample; the second sample's hidden values are switched off by the relu

Gradientenabstieg am einfachsten Modell

Das Training eines Netzes nutzt Backpropagation für die Gradienten, doch die Idee ist schon für ein lineares Modell y ~ x @ w + b vollständig. Der mittlere quadratische Fehler hat den Gradienten 2/n * x.T @ err bezüglich w und 2 * mean(err) bezüglich b, mit err = Vorhersage - Ziel. Starten Sie bei Nullen, ziehen Sie die Lernrate mal Gradient ab, wiederholen Sie. Eine zu große Lernrate schießt über das Ziel hinaus und divergiert, eine zu kleine kriecht. Standardisieren Sie die Merkmale zuerst (Mittelwert null, Varianz eins), damit eine Lernrate für alle passt. Bibliotheken wie PyTorch berechnen die Gradienten automatisch, tun aber genau diese Schleife.

# Gradient descent on a line: start at zero and walk downhill on the mean squared error
import numpy as np

def mse_loss(pred, target):
    return float(np.mean((pred - target) ** 2))

def train_linear(x, y, lr, epochs):
    n, d = x.shape
    w, b = np.zeros(d), 0.0
    for _ in range(epochs):
        err = x @ w + b - y
        w = w - lr * 2 / n * x.T @ err
        b = b - lr * 2 * float(np.mean(err))
    return w, float(b)

x = np.array([[0.0], [1.0], [2.0], [3.0]])
y = np.array([1.0, 3.0, 5.0, 7.0])                          # exactly y = 2x + 1
for epochs in (0, 10, 2000):
    w, b = train_linear(x, y, 0.05, epochs)
    print(epochs, np.round(w, 3), round(b, 3), round(mse_loss(x @ w + b, y), 6))
# 0 [0.] 0.0 21.0          the zero start
# 10 [2.009] 0.958 0.00092   already close
# 2000 [2.] 1.0 0.0          the line y = 2x + 1 is found

Warum Renditen für ein Netz schwer vorherzusagen sind

Ein Netz kann fast alles anpassen, und das ist die Gefahr bei Finanzdaten: Renditen sind überwiegend Rauschen, ein flexibles Modell merkt sich also das Rauschen der Trainingsperiode und scheitert in der nächsten. Overfitting zeigt sich als Trainingsfehler weit unter dem Fehler auf ungesehenen Daten. Die Abwehr entspricht den früheren Themen: gegen eine einfache Basislinie vergleichen (ein lineares Modell oder Vorhersage null); nur auf späteren Daten mit Walk-forward-Validierung auswerten und die Zeit nie mischen; wenige Merkmale und ein kleines Netz; Regularisierung (Weight Decay, Dropout) und frühes Stoppen ergänzen; und mehrere mit verschiedenen Seeds gestartete Netze mitteln. Schlägt das Netz die lineare Basislinie außerhalb der Stichprobe nicht klar, nehmen Sie das lineare Modell.

# Overfitting in miniature: a flexible fit to pure noise looks great in-sample and useless afterwards
import numpy as np

rng = np.random.default_rng(5)
x_train, x_test = rng.normal(size=(30, 12)), rng.normal(size=(1000, 12))      # 12 features that mean nothing
y_train, y_test = rng.normal(0, 0.01, size=30), rng.normal(0, 0.01, size=1000)  # next-day returns: pure noise

w = np.linalg.lstsq(x_train, y_train, rcond=None)[0]                          # a model with 12 free weights fitted to 30 points
train_mse = np.mean((x_train @ w - y_train) ** 2)
test_mse = np.mean((x_test @ w - y_test) ** 2)
baseline_mse = np.mean(y_test ** 2)                                           # predict zero
print(train_mse < baseline_mse, test_mse > baseline_mse)                      # True True   better in-sample, worse than zero out of sample
# The learning rate matters: a small one settles, one that is too large overshoots and the error blows up
import numpy as np

x = np.array([[1.0], [2.0], [3.0]])
y = np.array([2.0, 4.0, 6.0])

def final_errors(lr, epochs):
    w, b, errors = np.zeros(1), 0.0, []
    for _ in range(epochs):
        err = x @ w + b - y
        errors.append(float(np.mean(err ** 2)))
        w = w - lr * 2 / len(y) * x.T @ err
        b = b - lr * 2 * float(np.mean(err))
    return errors

small, large = final_errors(0.05, 30), final_errors(0.5, 30)
print(small[-1] < small[0])                          # True   the error shrinks
print(large[-1] > 1000 * large[0])                   # True   the error explodes: the steps are too big
Beginnen Sie mit der langweiligen BasisliniePassen Sie vor jedem Netz ein lineares Modell mit denselben Merkmalen an und behalten Sie dessen Fehler außerhalb der Stichprobe als die zu schlagende Zahl. Protokollieren Sie Seed, Datenfenster und Hyperparameter jedes Laufs, denn neuronales Training ist zufällig und Ergebnisse ändern sich von Lauf zu Lauf. Skalieren Sie Merkmale nur mit den Statistiken der Trainingsperiode, nie der ganzen Stichprobe, sonst lecken Sie die Zukunft. Und bedenken Sie: Ein kleiner Prognosevorteil ist nichts wert, wenn die Handelskosten größer sind.
  • Eine Schicht ist relu(x @ w + b); ein Netz stapelt Schichten, und der Loss (bei einer Prognose der mittlere quadratische Fehler) misst, wie weit Vorhersagen von den Zielen entfernt sind.
  • Training ist Gradientenabstieg: beim linearen Modell w -= lr * 2/n * x.T @ err und b -= lr * 2 * mean(err); Merkmale skalieren, Lernrate abstimmen.
  • Renditen sind überwiegend Rauschen: Vergleichen Sie mit einer linearen Basislinie, validieren Sie walk-forward, nutzen Sie kleine regularisierte Netze und hören Sie auf, wenn der Gewinn außerhalb der Stichprobe verschwindet.

Als Nächstes: Reinforcement Learning für den Handel, eine Strategie aus Belohnungen statt aus beschrifteten Antworten lernen.

Lab: Was bewertet wird

  • Negative mit relu abschalten25 Pkt.
  • Das Netz mit mlp_forward vorwärts rechnen25 Pkt.
  • Den Fehler mit mse_loss messen25 Pkt.
  • Mit train_linear durch Abstieg lernen25 Pkt.
Explorer · lab-140-1
▾ lab-140-1
…
bash · im Browser
learner@quantcraft:~/lab-140-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

Alles in lab-140-1 wird auf die Startdateien zurückgesetzt und das Terminal geleert. Ihre aktuelle Lösung geht verloren – das lässt sich nicht rückgängig machen.

Wird zurückgesetzt
  • main.py → Startcode
  • Terminal-Verlauf und Testausgabe
  • Nicht eingereichte Änderungen
Bleibt erhalten
  • Beste Lab-Punktzahl
  • Ihre XP und Ihre Serie
  • Vorlesungsfortschritt und Notizen

Melde dich an, um deinen Code auszuführen.

Alle Lektionen kannst du kostenlos lesen. Erstelle ein Konto oder melde dich an, um Code auszuführen, Tests zu starten und dieses Lab abzugeben.

  • IDE im Browser mit Bash-Terminal — nichts zu installieren
  • Sofortige Bewertung, XP und dein Platz auf der Skill
Konto erstellenAnmelden
ODER
Weiter mit GitHub