Entwicklung & Code

Künstliche Neuronale Netze im Überblick 1: Das künstliche Neuron


Neuronale Netze sind der Motor vieler Anwendungen in KI und GenAI. Diese Artikelserie gibt einen Einblick in die einzelnen Elemente. Der erste Teil stellt das künstliche Neuron vor.




Prof. Dr. Michael Stal arbeitet seit 1991 bei Siemens Technology. Seine Forschungsschwerpunkte umfassen Softwarearchitekturen für große komplexe Systeme (Verteilte Systeme, Cloud Computing, IIoT), Eingebettte Systeme und Künstliche Intelligenz.

Er berät Geschäftsbereiche in Softwarearchitekturfragen und ist für die Architekturausbildung der Senior-Software-Architekten bei Siemens verantwortlich.

Ein künstliches Neuron ist der Grundbaustein jedes neuronalen Netzwerks. Sein Design ist von biologischen Neuronen inspiriert, aber seine mathematische Form ist viel einfacher und für Berechnungen gut geeignet. Im Kern empfängt ein künstliches Neuron eine oder mehrere numerische Eingaben, multipliziert jede Eingabe mit einem entsprechenden Gewicht, summiert die Ergebnisse, addiert einen Bias-Term und leitet die Summe dann durch eine nicht lineare Aktivierungsfunktion. In diesem Teil der Serie werde ich die mathematischen Grundlagen dieses Prozesses untersuchen und zeigen, wie er sich direkt in Code umsetzen lässt.

Betrachten wir ein Neuron mit den Eingaben x₁, x₂, …, xₙ und den lernbaren Parametern w₁, w₂, …, wₙ (die Gewichte) und b (die Vorspannung). Das Neuron berechnet die Größe

z = w₁·x₁ + w₂·x₂ + … + wₙ·xₙ + b

Dieser Ausdruck kann auch in kompakter Vektor-Matrix-Notation geschrieben werden als

z = wᵀ·x + b

wobei w und x n-dimensionale Spaltenvektoren sind. Den Skalar z bezeichnet man oft als Voraktivierung, da das Neuron, bevor es seine endgültige Ausgabe erzeugen kann, z durch eine Aktivierungsfunktion σ leiten muss, was zu

a = σ(z)

führt.

Der Bias-Term b ermöglicht es, die Aktivierungsfunktion nach links oder rechts zu verschieben, sodass das Netzwerk Muster anpassen kann, die nicht durch den Ursprung verlaufen. Die Gewichte wᵢ bestimmen die Stärke und Richtung des Einflusses jeder Eingabe auf die Ausgabe. Während des Trainings passt das Netzwerk diese Parameter an, um eine bestimmte Verlustfunktion zu minimieren.

In der Praxis implementieren wir ein einzelnes Neuron in PyTorch wie folgt:


import torch

# Beispiel-Eingaben und Parameter definieren
x = torch.tensor([0.5, -1.2, 3.3], dtype=torch.float32)
w = torch.tensor([0.1, 0.4, -0.7], dtype=torch.float32)
b = torch.tensor(0.2, dtype=torch.float32)

# Berechne die gewichtete Summe z = w·x + b
z = torch.dot(w, x) + b

# Wende eine Aktivierungsfunktion an (vorerst die Identität)
a = z


Jede Zeile in diesem Ausschnitt hat eine klare Aufgabe. Die erste Zeile importiert PyTorch, eine Bibliothek, die Tensorberechnungen beschleunigt und Operationen für die Gradientenberechnung automatisch durchführt. Die nächsten drei Zeilen erstellen eindimensionale Tensoren für Eingaben, Gewichte und Bias. Durch die Angabe von dtype=torch.float32 stellen wir sicher, dass alle Berechnungen mit 32-Bit-Gleitkommaarithmetik erfolgen, was Präzision und Leistung auf moderner Hardware balanciert.

Der Ausdruck torch.dot(w, x) berechnet das Skalarprodukt der Tensoren w und x und führt die Summe der elementweisen Produkte (w₁·x₁ + w₂·x₂ + w₃·x₃) aus. Durch Hinzufügen von b übertragen wir die skalare Vorspannung auf das Ergebnis, wodurch wir den vollständigen Wert z vor der Aktivierung erhalten. Zu diesem Zeitpunkt ist die Ausgabe des Neurons einfach z, aber sobald wir eine nicht lineare Aktivierungsfunktion σ einführen, ersetzen wir die Zeile a = z durch a = σ(z).

Im Hintergrund zeichnet PyTorch die Operationen auf diesen Tensoren in einem Berechnungsgraphen auf. Wenn wir später z.backward() aufrufen, durchläuft PyTorch diesen Graphen und berechnet automatisch die partiellen Ableitungen ∂z/∂wᵢ und ∂z/∂b. Diese automatische Differentiation ermöglicht es, Millionen von Parametern in großen Netzwerken ohne manuelle Ableitungsberechnungen zu optimieren.

Die mathematische Einfachheit einer einzelnen Nervenzelle täuscht über ihre Ausdruckskraft hinweg, sobald viele Nervenzellen zu Schichten und Netzwerken verbunden sind. Durch Anpassen ihrer Gewichte und Vorspannungen kann eine Nervenzelle lernen, lineare Kombinationen ihrer Eingaben zu erkennen. Wenn wir Dutzende oder Hunderte solcher Nervenzellen kombinieren und mit nicht linearen Aktivierungen verschachteln, kann das Netzwerk beliebig komplexe Funktionen approximieren.

Der nächste Teil der Serie zeigt, wie man viele künstliche Neuronen zu Schichten zusammenfügt, den Datenfluss zwischen ihnen definiert und den Vorwärtslauf eines kompletten Netzwerks in PyTorch implementiert.


(rme)



Source link

Leave a Reply

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Beliebt

Die mobile Version verlassen