Das Neuron
Kurz gesagt: Ein Neuron ist die Summe seiner Eingaben mal Gewichte plus ein Bias, durch eine Aktivierung wie Sigmoid oder ReLU geschickt.
Problem
Das Netz hat die Zahlung gestoppt. Warum?
Der Shop ersetzt seine alte Betrugsregel durch ein „neuronales Netz“ einer externen Firma. Am ersten Tag zahlt ein Kunde 230 € von einem neuen Konto mit einer ausländischen Karte, und die Zahlung wird für eine manuelle Prüfung angehalten. Der Kunde schreibt an den Support: „Warum?“
Niemand weiß es. Für das Team ist das Netz eine Black Box: Die Merkmale der Zahlung gehen hinein, eine Zahl kommt heraus. Und solange du nicht weißt, was innen passiert, kannst du die Entscheidung nicht erklären, einen Fehler nicht beheben und nicht einmal sagen, ob die Zahl sinnvoll ist.
Die Box geht auf. Innen ist nichts, was du nicht schon gesehen hast: Multiplikation, Addition und eine Funktion.
Die Idee
Ein Neuron: eine Summe mit Gewichten
Ein künstliches Neuron bekommt ein paar Zahlen (seine Eingaben). Jede Eingabe hat ihr eigenes Gewicht: wie stark sie zählt und in welche Richtung. Das Neuron multipliziert jede Eingabe mit ihrem Gewicht, addiert alles und addiert noch eine Zahl, den Bias. Das Ergebnis heißt z.
Dann geht z durch eine Funktion, die entscheidet, was herauskommt. Sie heißt Aktivierungsfunktion. Vorerst ist es die Sigmoid-Funktion: Sie drückt jedes z zu einer Zahl zwischen 0 und 1 zusammen.
Kommt dir das bekannt vor? Es ist die logistische Regression: eine gewichtete Summe, eine Sigmoid-Funktion, eine Wahrscheinlichkeit und ein Schwellenwert. Ein Neuron mit Sigmoid-Funktion ist genau das. Ein neuronales Netz besteht aus vielen solchen Neuronen, die hintereinander verbunden sind.
Sieh es dir an
Das Neuron im Code
Die drei Funktionen: die gewichtete Summe, die Sigmoid-Funktion und das Neuron, das beide verbindet.
static double weightedSum(double[] x, double[] w, double b) { double z = b; // der Bias for (int i = 0; i < x.length; i++) { z += x[i] * w[i]; // Eingabe × Gewicht } return z;}
static double sigmoid(double z) { return 1 / (1 + Math.exp(-z));}
static double neuron(double[] x, double[] w, double b) { return sigmoid(weightedSum(x, w, b));}Die Zahlungen haben drei Merkmale: den Betrag in Hunderten von Euro, ein neues Konto (1 oder 0) und eine ausländische Karte (1 oder 0). Die Gewichte sind von Hand gesetzt, damit du im Kopf rechnen kannst. Wie ein Netz sie selbst findet, zeigt die Lektion über Backpropagation.
// Betrag (Hunderter €), neues Konto, ausländische Kartedouble[] w = {0.9, 1.4, 1.8};double b = -4.0;double[][] payments = { {0.40, 0, 0}, {1.20, 1, 0}, {8.90, 1, 1}, {0.60, 0, 1}, {6.40, 0, 0}, {2.30, 1, 1},};System.out.println("Betrag € neu Ausland z p");for (double[] x : payments) { double z = weightedSum(x, w, b); double p = sigmoid(z); String verdict = p >= 0.5 ? "prüfen" : "ok"; System.out.printf("%8.0f %5.0f %7.0f %6.2f %6.3f %s%n", x[0] * 100, x[1], x[2], z, p, verdict);}Betrag € neu Ausland z p 40 0 0 -3.64 0.026 ok 120 1 0 -1.52 0.179 ok 890 1 1 7.21 0.999 prüfen 60 0 1 -1.66 0.160 ok 640 0 0 1.76 0.853 prüfen 230 1 1 1.27 0.781 prüfenJetzt kannst du dem Kunden antworten. Die Zahlung über 230 € steht in der letzten Zeile: z = −4 + 2,3 × 0,9 + 1 × 1,4 + 1 × 1,8 = −4 + 2,07 + 1,4 + 1,8 = 1,27. Die Sigmoid-Funktion ergibt 0,781, über dem Schwellenwert von 0,5. Das neue Konto und die ausländische Karte haben 3,2 zur Summe beigetragen. Ohne sie wäre z gleich −1,93 und die Wahrscheinlichkeit etwa 0,13.
Sieh es dir an
Das Signal geht durch das Neuron
static double weightedSum(double[] x, double[] w, double b) { double z = b; // der Bias for (int i = 0; i < x.length; i++) { z += x[i] * w[i]; // Eingabe × Gewicht } return z;}
static double sigmoid(double z) { return 1 / (1 + Math.exp(-z));}
static double neuron(double[] x, double[] w, double b) { return sigmoid(weightedSum(x, w, b));}Schritt für Schritt, in Worten
- Eine Zahlung über 230 € von einem neuen Konto mit einer ausländischen Karte. Die Eingaben sind 2,30, 1 und 1.
- z beginnt beim Bias: −4,00.
- Jede Eingabe mal ihr Gewicht: 2,30 × 0,9 = 2,07, 1 × 1,4 = 1,40, 1 × 1,8 = 1,80.
- Die Summe: z = −4 + 2,07 + 1,40 + 1,80 = 1,27.
- Die Sigmoid-Funktion drückt z zwischen 0 und 1: σ(1,27) = 0,781.
- 0,781 liegt über dem Schwellenwert von 0,5: Die Zahlung geht in die Prüfung.
- 40 € von einem alten Konto mit einer bulgarischen Karte: z = −4 + 0,36 = −3,64, p = 0,026. Ok.
- Ein Neuron: eine Summe mit Gewichten, ein Bias und eine Sigmoid-Funktion. Das ist logistische Regression.
Zuerst kommt der Bias, dann trägt jede Eingabe ihren Teil bei. Die Sigmoid-Funktion ändert die Reihenfolge nicht: Ein größeres z ergibt ein größeres p. Sie drückt es nur zwischen 0 und 1, damit es sich wie eine Wahrscheinlichkeit lesen lässt.
Probier es aus
Finde den Fehler
Ein Kollege schreibt die gewichtete Summe selbst. Mit einem Bias von −4 kommt jede Zahlung mit einem viel kleineren z heraus, als sie sollte, und nichts erreicht die Prüfung. In welcher Zeile steckt der Fehler?
Wähle die Zeile mit dem Fehler.
Der Bias wird für jede Eingabe addiert, nicht einmal: Bei drei Eingaben geht er dreimal ein. Mit b = −4 ist die Summe um 8 kleiner, als sie sein sollte. Richtig ist, z mit b zu beginnen und in der Schleife nur Eingabe × Gewicht zu addieren.
Problem
Drei Neuronen, so viel wert wie eins
Ein Kollege will, dass das Netz kompliziertere Regeln erfasst. Er fügt zwei Neuronen hinzu, die die Zahlung lesen, und ein drittes, das ihre Ausgaben liest. Nirgends gibt es eine Aktivierung: Jedes Neuron gibt die Summe z selbst zurück.
Das Programm berechnet die drei Neuronen und, getrennt davon, ein Neuron, dessen Gewichte aus ihren berechnet sind:
// zwei Neuronen lesen die Zahlung, ohne Aktivierungdouble[] w1 = {0.5, 1.0, 1.5};double b1 = -1.0;double[] w2 = {1.0, -0.5, 0.5};double b2 = 0.5;// ein drittes Neuron liest ihre Ausgabendouble[] v = {1.5, -0.5};double c = 0.5;// dasselbe wie ein Neuron mit diesen Gewichtendouble[] w3 = new double[3];for (int i = 0; i < 3; i++) { w3[i] = v[0] * w1[i] + v[1] * w2[i];}double b3 = v[0] * b1 + v[1] * b2 + c;System.out.printf("w = [%.2f, %.2f, %.2f], b = %.2f%n", w3[0], w3[1], w3[2], b3);
double[][] payments = {{0.40, 0, 0}, {1.20, 1, 0}, {8.90, 1, 1}};System.out.println("Betrag € drei Neuronen ein Neuron");for (double[] x : payments) { double a1 = weightedSum(x, w1, b1); double a2 = weightedSum(x, w2, b2); double out = weightedSum(new double[] {a1, a2}, v, c); double one = weightedSum(x, w3, b3); System.out.printf("%8.0f %13.4f %12.4f%n", x[0] * 100, out, one);}w = [0.25, 1.75, 2.00], b = -1.25Betrag € drei Neuronen ein Neuron 40 -1.1500 -1.1500 120 0.8000 0.8000 890 4.7250 4.7250Die Spalten stimmen bis zur letzten Stelle überein. Die drei Neuronen sind so viel wert wie eins. Der Grund ist Schulalgebra: Eine Summe von Summen ist immer noch eine Summe. Was du auch hintereinanderschaltest, ohne Aktivierung ist das Ergebnis eine gerade Linie (genauer: eine Ebene) mit anderen Gewichten.
Die Idee
Die Aktivierung biegt die Linie
Etwas Neues entsteht erst, wenn zwischen den Neuronen eine Funktion steht, die nicht gerade ist. Die zwei häufigsten:
- Sigmoid: Drückt z zwischen 0 und 1. Praktisch für die Ausgabe, wenn du eine Wahrscheinlichkeit willst.
- ReLU (rectified linear unit): max(0, z). Das Positive geht durch, das Negative wird 0. Sie ist die häufigste Aktivierung in den verborgenen Neuronen heutiger Netze.
static double relu(double z) { return Math.max(0, z);}double[] zs = {-3, -1, 0, 1, 3};System.out.println(" z sigmoid ReLU");for (double z : zs) { System.out.printf("%6.2f %8.4f %5.2f%n", z, sigmoid(z), relu(z));} z sigmoid ReLU -3.00 0.0474 0.00 -1.00 0.2689 0.00 0.00 0.5000 0.00 1.00 0.7311 1.00 3.00 0.9526 3.00Beide sind gebogen. Die Sigmoid-Funktion ist ein „S“, und ReLU ist eine Gerade mit einem Knick bei null. Eine Summe gebogener Linien ist nicht mehr gerade, deshalb können Neuronen mit Aktivierung hintereinander eine Regel beschreiben, die ein einzelnes Neuron nicht schafft. Eine solche Regel kommt in der nächsten Lektion.
Probier es aus
Sag die Ausgabe voraus
Ein Neuron mit ReLU schätzt, wie viele Tage eine Lieferung zu spät ist. Die Eingaben sind die Entfernung in Hunderten von Kilometern und ob das Paket schwer ist. Eine Verspätung kann nicht negativ sein, deshalb ReLU. Was wird ausgegeben?
double[] w = {0.5, 1.0}; // Hunderte km, schweres Paket (1 oder 0)double b = -1.0;double near = relu(weightedSum(new double[] {1.5, 0}, w, b));double far = relu(weightedSum(new double[] {4.4, 0}, w, b));double heavy = relu(weightedSum(new double[] {3.0, 1}, w, b));System.out.printf("%.1f %.1f %.1f%n", near, far, heavy);Die nahe Lieferung: 0,5 × 1,5 − 1 = −0,25, und ReLU macht daraus 0. Die weite: 0,5 × 4,4 − 1 = 1,2. Das schwere Paket: 0,5 × 3 + 1 − 1 = 1,5. Mit einer Sigmoid-Funktion wären es 0,4 0,8 0,8, und ohne ReLU wäre die erste Zahl negativ: −0,25.
Probier es aus
Ergänze
Vervollständige ReLU.
static double relu(double z) {
return (0, z);
}Math.max(0, z) gibt das Größere von 0 und z zurück: Das Positive geht durch, das Negative wird 0.
Die Idee
Wann ein Neuron reicht und wann es schadet
- Die Regel ist fast gerade. Wenn die Merkmale die Antwort von allein verraten (ein größerer Betrag, mehr Risiko), macht ein Neuron, also die logistische Regression, es so gut wie ein großes Netz. Es lernt schneller und braucht weniger Daten.
- Es gibt wenige Daten. Ein Netz mit Hunderten von Gewichten und 200 Beispielen lernt sie auswendig. Das ist Überanpassung.
- Du musst die Entscheidung erklären. Die Gewichte eines Neurons lassen sich lesen: „das neue Konto hat 1,4 dazugegeben“. In einem Netz mit vielen Schichten ist die Antwort auf „warum“ viel schwerer, und bei einer gestoppten Zahlung oder einem abgelehnten Kredit wird sie verlangt.
- Die Regel ist bekannt und fest. „Über 5.000 € immer eine manuelle Prüfung“ ist ein
if, kein Modell. - Die Eingaben haben verschiedene Größenordnungen. Ein Betrag in Euro (40, 890) neben Merkmalen aus 0 und 1 ergibt Gewichte, die schwer zu lernen sind. Deshalb steht der Betrag hier in Hunderten von Euro. In einem echten Modell werden die Eingaben normalisiert.
Genauer, für Neugierige
Die Formeln. Für ein Neuron mit den Eingaben x₁, x₂, x₃:
z = w₁·x₁ + w₂·x₂ + w₃·x₃ + b
p = σ(z) = 1 / (1 + e^(−z))
In Worten: jede Eingabe mal ihr Gewicht, plus der Bias, dann die Sigmoid-Funktion. e ist die Eulersche Zahl (etwa 2,718), und Math.exp(-z) ist e hoch −z.
Warum drei Neuronen ohne Aktivierung eins sind. Wenn a₁ = w₁·x + b₁ und a₂ = w₂·x + b₂, dann ist v₁·a₁ + v₂·a₂ + c = (v₁·w₁ + v₂·w₂)·x + (v₁·b₁ + v₂·b₂ + c). Das ist ein Neuron mit den Gewichten v₁·w₁ + v₂·w₂. Genau das berechnet das Programm mit den drei Neuronen.
Andere Aktivierungen: tanh (wie die Sigmoid-Funktion, aber zwischen −1 und 1), Leaky ReLU (das Negative ist nicht 0, sondern klein, zum Beispiel 0,01·z), Softmax (an der Ausgabe, wenn es mehr als zwei Klassen gibt: Es macht aus mehreren Zahlen Wahrscheinlichkeiten, die sich zu 1 summieren). Es gibt noch viele mehr, aber ReLU und die Sigmoid-Funktion reichen, um alles in diesem Modul zu verstehen.
Womit echte Netze gebaut werden. Hier sind es Schleifen und Arrays, damit du jede Zahl siehst. Echte Netze haben Millionen von Gewichten, und die Mathematik läuft mit Matrizen auf einer Grafikkarte. Die Praxis des maschinellen Lernens läuft meist in Python: NumPy für Arrays, scikit-learn für klassische Modelle, PyTorch für neuronale Netze. Auch andere Sprachen haben Werkzeuge: ML.NET für C#, DJL und Tribuo für Java, TensorFlow.js und ONNX Runtime für JavaScript. Oft wird ein Modell in Python trainiert und aus einem Programm in einer anderen Sprache benutzt (zum Beispiel über ONNX).
Der Name. „Neuron“ kommt aus der Biologie: eine Zelle, die Signale sammelt und „feuert“, sobald ihre Summe eine Schwelle überschreitet. Die Ähnlichkeit hört da auf. Ein künstliches Neuron ist eine Funktion von Zahlen.
Übung
Ein Neuron für Rezensionen
Löse es in deinem Editor.
Der Shop will Rezensionen in gute und schlechte sortieren. Für jede Rezension sind die guten Wörter („schnell“, „Qualität“) und die schlechten Wörter („kaputt“, „spät“) schon gezählt. Schreibe ein Neuron mit einer Sigmoid-Funktion, mit einem Gewicht von 1,1 für die guten Wörter, −1,7 für die schlechten und einem Bias von 0,2. Lass es auf den fünf Rezensionen laufen (gute, schlechte): (3, 0), (1, 2), (0, 0), (2, 1), (0, 3). Eine Rezension ist gut, wenn p mindestens 0,5 ist.
gute Wörter 3, schlechte Wörter 0: p = 0.971 → gutgute Wörter 1, schlechte Wörter 2: p = 0.109 → schlechtgute Wörter 0, schlechte Wörter 0: p = 0.550 → gutgute Wörter 2, schlechte Wörter 1: p = 0.668 → gutgute Wörter 0, schlechte Wörter 3: p = 0.007 → schlechtDie Rezension ganz ohne Wörter kommt mit 0,550 als gut heraus: Das ist allein der Bias. Ohne weitere Anhaltspunkte hält das Modell die Rezension leicht für gut.
Weitere Aufgaben
- Ein drittes Merkmal. Füge die Ausrufezeichen als Merkmal mit einem Gewicht von −0,3 hinzu und schau, welche Rezensionen ihre Entscheidung ändern.
- Der Schwellenwert. Nimm einen Schwellenwert von 0,7 statt 0,5. Welche Rezensionen werden schlecht?
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Was maschinelles Lernen ist · Lineare Regression · Klassifikation: Betrug oder nicht · Überanpassung: Das Modell, das auswendig lernt
- Geht weiter in: Schichten · Backpropagation · Das Training von Anfang bis Ende · Die Ziffern auf dem Kassenbon
- Aufgaben zum Thema: Ein neuronales Netz von innen