Classic Games Reloaded – Teil 9

Klassische KI gegen neuronales Netzwerk - Runde 1

Klassische KI gegen neuronales Netzwerk - Runde 1

Classic Games Reloaded – Teil 9

Klassische KI gegen neuronales Netzwerk - Runde 1


Spieleklassiker erfreuen sich heutzutage einer großen Beliebtheit unter KI-Forschern und Programmierern, da die einfach strukturierten Spielewelten unter anderem ideale Testumgebungen für die Erforschung und Entwicklung von künstlichen neuronalen Netzwerken darstellen. Selbstverständlich werden auch wir uns diesem Trend nicht verschließen. Da wir jedoch die KI-Routinen unserer Spiele nicht von jetzt auf gleich völlig umkrempeln können, werden wir uns in diesem Artikel zunächst einmal mit den grundlegenden Aspekten von einfachen neuronalen Netzen beschäftigen.

Die vielen Zeitungsartikel, die sich oberflächlich mit dem Thema künstliche Intelligenz (KI) auseinandersetzen, sind langsam aber sicher nicht mehr zählbar. Mit einer selten gekannten Einigkeit werden Politiker, Wissenschaftler und Wirtschaftslenker nicht müde zu betonen, wie wichtig es ist, im weltweiten Wettlauf um die Vorreiterrolle auf diesem Technologiesektor nicht abgeschlagen auf einem der hinteren Plätze zu landen. Ob die diesbezüglich in Deutschland getroffenen Maßnahmen allerdings wirklich zielführend sind, steht auf einem anderen Blatt. Ihre große Popularität verdankt die künstliche Intelligenz Bildern von autonom fahrenden Fahrzeugen oder den Schlagzeilen über selbstständig lernende Go- und Schachprogamme, die einem menschlichen Spieler überlegen sind. Dinge wie Schrifterkennung, Bilderkennung und Spracherkennung sind für uns bereits zur Normalität geworden.

Dank ihrer vielfältigen Einsatzmöglichkeiten ist die KI aus unserem Alltag nicht mehr wegzudenken und hat unsere Welt bereits stärker verändert, als es zunächst den Anschein hat. Haben Sie sich in diesem Zusammenhang beispielsweise schon einmal die Frage gestellt, warum die mit einem Smartphone aufgenommenen Bilder eigentlich so verdammt gut aussehen? Nun, als man früher auf den Auslöseknopf eines Fotoapparats gedrückt hat, hat das Gerät genau ein einziges Foto aufgenommen. Ein Smartphone hingegen nimmt gleich eine ganze Serie von Bildern auf, wobei sich bei den einzelnen Bildern die jeweiligen Belichtungszeiten und Fokussierungen leicht voneinander unterscheiden. Im Anschluss daran hat die künstliche Intelligenz ihren großen Auftritt und kombiniert die einzelnen Bilder zu einer Art Superbild. Sie sehen also, dass die heutigen Smartphones nicht ohne Grund eine so hohe Rechenleistung und einen so großzügig dimensionierten Arbeitsspeicher besitzen. So weit, so gut – dann müssen wir eigentlich nur noch klären, was genau künstliche Intelligenz überhaupt ist und wie sich die zugrunde liegenden Algorithmen implementieren lassen.

Klassische künstliche Intelligenz (KI) versus künstliche neuronale Netzwerke

Ein zentraler Aspekt bei der Entwicklung eines KI-Systems dreht sich um die beiden Fragen, auf welche Weise man das für eine Entscheidungsfindung erforderliche Wissen im System hinterlegen sollte und auf welche Weise sich das besagte Wissen so effizient wie möglich abrufen lässt. Bei einem klassischen KI-System handelt es sich genau genommen um eine regelbasierte KI, die als eine Art Expertensystem fungiert. Sämtliches Wissen und alle Regeln, die den jeweiligen Entscheidungsprozessen zugrunde liegen, sind entweder hartcodiert oder werden aus einer separaten Datei ins Programm eingelesen. Es muss wohl nicht extra betont werden, dass eine solche regelbasierte KI nur in begrenztem Maße lernfähig ist, da der Regelsatz von den Programmierern vorgegeben wird und sich einzig der Umgang mit den einzelnen Regeln unter Berücksichtigung der in der Praxis gewonnenen Erfahrungen ein wenig optimieren lässt. Vereinfacht ausgedrückt führt ein regelbasiertes KI-System lediglich eine mehr oder weniger große Anzahl von Wenn-dann-Entscheidungen aus, die sich in Form eines endlichen Zustandsautomaten (FSM, Finite State Machine) implementieren lassen. Wenn die Anzahl der zu berücksichtigenden Regeln und Zustände nicht allzu groß ist, kann man den betreffenden Zustandsautomaten unter Zuhilfenahme einiger weniger if-, else if- und else-Anweisungen programmieren. Bei umfangreicheren Systemen bietet sich hingegen der Einsatz von Funktions- bzw. Methodenzeigern an.

Im Unterschied zu einer regelbasierten KI können künstliche neuronale Netzwerke die anzuwendenden Regeln und Verhaltensweisen im Verlauf einer mehr oder weniger aufwendigen Trainingsphase selbstständig erlernen, oder sie können zu einem späteren Zeitpunkt durch ein erneutes Training „umgeschult“ werden. Man spricht in diesem Zusammenhang vom sogenannten maschinellen Lernen (Machine Learning). Im weiteren Verlauf dieses Artikels werde ich noch ausführlich auf die unterschiedlichen Methoden zu sprechen kommen, mit denen sich künstliche neuronale Netze trainieren lassen. Nichtsdestotrotz sollte klargestellt werden, dass neuronale Netze trotz ihrer Anpassungsfähigkeit genauso wenig intelligent sind wie die klassischen KI-Systeme, da sich beide lediglich so verhalten, wie sie programmiert bzw. trainiert worden sind. Echte Intelligenz basiert hingegen auf eigenständigen Denkprozessen.

Aufbau und Funktionsprinzip einfacher neuronaler Netze

Die meisten Menschen, die zum ersten Mal etwas über das Thema künstliche Intelligenz hören, stellen sich unter einem künstlichen neuronalen Netzwerk eine Art Simulation vor, mit deren Hilfe man die biologischen Prozesse nachbilden möchte, die innerhalb eines Nervensystems oder Gehirns ablaufen. Aber genau genommen gehören derartige Vorstellungen zumindest im Augenblick noch in das Reich der Science-Fiction. Von künstlichen Elektronengehirnen, die nach der Weltherrschaft streben, werden wir daher auf absehbare Zeit höchstwahrscheinlich noch verschont bleiben. Auch wenn sich viele wissenschaftliche Pioniere auf dem Gebiet der künstlichen neuronalen Netze von dem Grundgedanken der „Informationsverarbeitung nach dem Vorbild der Natur“ haben leiten lassen, finden sich für die Netzwerke, mit denen man heutzutage arbeitet, genau genommen überhaupt keine biologischen Vorbilder, sondern allenfalls entfernte Analogien.

Im Unterschied zu einem biologischen neuronalen Netz, in welchem beständig Nervenimpulse weitergeleitet und neue Nervenbahnen angelegt werden, besteht ein künstliches neuronales Netz lediglich aus einer mehr oder weniger großen Anzahl von vernetzten Rechenautomaten. Die Funktionsweise einer künstlichen Nervenzelle (eines Neurons) lässt sich anhand von Abbildung 1 nachvollziehen: Man ordnet den einzelnen Neuronen eine Funktion zu, mit deren Hilfe sich aus den eingehenden Signalen (Inputs) ein Ausgangssignal (Output) berechnen lässt. Da nicht jedes Eingangssignal zwangsläufig auch zu einem Ausgangssignal führt (also eine Nervenzelle aktiviert), spricht man in diesem Zusammenhang von einer sogenannten Aktivierungsfunktion.

Während die Aktivierung einer biologischen Nervenzelle immer dann erfolgt, wenn die Summe der eingehenden Signale einen physiologisch festgelegten Schwellenwert (das sogenannte Aktivierungspotenzial) überschreitet, können wir bei der Ausgestaltung unserer künstlichen Netzwerke auf ganz unterschiedliche Aktivierungsfunktionen zurückgreifen. Hier einmal eine kleine Auswahl von möglichen Funktionen:

rudolph_neuronales_netz_1.tif_fmt1.jpgAbb. 1: Künstliches Neuron (Berechnungsautomat)
  • Linearer Output (neuronOutput == neuronInput, Wertebereich von -unendlich bis unendlich):


    inline float LinearOutput(float neuronInput)
    { return neuronInput; }
  • Rectified Linear Unit (ReLU, Wertebereich von 0.0f bis unendlich):


    inline float ReLUOutput(float neuronInput)
    { return max(0.0f, neuronInput); }
  • binärer Output (0.0f oder 1.0f):


    inline float BinaryOutput(float neuronInput)
    { if (neuronInput > 0.9999f) return 1.0f; return 0.0f; }
  • Sigmoid- bzw. Schwanenhalsfunktion (S-Funktion, Wertebereich von 0.0f bis 1.0f):


    inline float SigmoidOutput(float neuronInput)
    { return 1.0f / (1.0f + exp(-neuronInput)); }
  • Tangens hyperbolicus (Wertebereich von -1.0f bis 1.0f):


    inline float TanHOutput(float neuronInput)
    { return tanh(neuronInput); }
  • Weniger rechenintensive Alternative zur tanh()-Funktion (Wertebereich von -1.0f bis 1.0f):


    inline float FastTanHReplacementOutput(float neuronInput)
    { return neuronInput / (1.0f + abs(neuronInput)); }

Die biologischen Prozesse, die sich an der Verknüpfungsstelle zweier Nervenzellen – der sogenannten Synapse – abspielen, sind alles andere als trivial. Um von einer Nervenzelle zu einer anderen zu gelangen, muss jedes Signal zunächst einmal den synaptischen Spalt überwinden. Dieser Spalt stellt bildlich gesprochen den Endpunkt einer möglichen Abfahrt von der zelleigenen Schnellstraße (dem Axon) dar, welche ihren Ursprung im sogenannten Zellkörper hat. Sobald das elektrische Ausgangssignal den synaptischen Spalt erreicht hat, wird die Synapse dazu angeregt, ein chemisches Signal auszusenden, das den besagten Spalt überbrücken kann.

Treffen die chemischen Botenstoffe auf der gegenüberliegenden Seite des Spalts schließlich auf die Rezeptoren einer anderen Nervenzelle (die Zellfortsätze, an denen sich die Rezeptoren befinden, werden als Dendriten bezeichnet), wird dort ein neues elektrisches Eingangssignal generiert und zum Zellkörper weitergeleitet. Im Verlauf eines Lernvorgangs verändert sich nun die Sensitivität, mit der die einzelnen Synapsen auf die ausgehenden Signale einer Nervenzelle reagieren. Wissenschaftlich ausgedrückt spricht man in diesem Zusammenhang von der sogenannten synaptischen Plastizität (synaptische Übertragungsstärke).

rudolph_neuronales_netz_2.tif_fmt1.jpgAbb. 2: Neuronale Verknüpfungen
rudolph_neuronales_netz_3.tif_fmt1.jpgAbb. 3: Neuronale Verknüpfungen und Bias-Neuronen

Das Funktionsprinzip einer künstlichen Synapse lässt sich nun anhand der Abbildungen 2 und 3 nachvollziehen. In diesem Zusammenhang genügt es zu wissen, dass die Synapsen mit einer hohen Plastizität die ausgehenden Nervenimpulse mit einer höheren Intensität weiterleiten als die Synapsen mit einer geringeren Plastizität. Mathematisch gesehen handelt es sich bei der Plastizität daher lediglich um einen simplen Gewichtungsfaktor: Eingangssignal = synaptische_Plastizität * Ausgangssignal. Im Unterschied zu einem biologischen Nervensystem, in dem die Synapsen entweder erregend oder hemmend auf eine Nervenzelle einwirken, können die synaptischen Plastizitäten in einem künstlichen Netzwerk sowohl positive (signalverstärkende) als auch negative (signalhemmende) Werte annehmen. Darüber hinaus ist es unter biologischen Gesichtspunkten absoluter Nonsens, sich unter der Plastizität eine Art von Gewichtungsfaktor vorzustellen. In Anbetracht der Funktionsweise eines biologischen neuronalen Netzes sollte man die synaptischen Plastizitäten besser als ein Maß für die Wahrscheinlichkeit begreifen, mit der ein Nervenimpuls innerhalb eines bestimmten Zeitintervalls von einer Nervenzelle zu einer anderen weitergeleitet wird.

Während man neuronale Netze mit einer einzigen verdeckten Schicht von Neuronen (Hidden Layer) als flache Netzwerke (Shallow Neural Nets, siehe hierzu die Abb. 4 bis 6) bezeichnet, handelt es sich bei dem in Abbildung 7 gezeigten Netzwerk um ein sogenanntes tiefes neuronales Netz (Deep Neural Net), da es über mehrere verdeckte Schichten verfügt. Sofern sich die Anzahl der Outputneuronen von der Anzahl der Inputneuronen unterscheidet, spricht man von einem heteroassoziativen Netzwerk (Abb. 5). Bei einem autoassoziativen neuronalen Netz ist die Anzahl der Outputneuronen hingegen genauso groß wie die Anzahl der Inputneuronen (Abb. 6).

rudolph_neuronales_netz_4.tif_fmt1.jpgAbb. 4: Neuronales Netz für die Handhabung zweistelliger logischer Verknüpfungen
rudolph_neuronales_netz_5.tif_fmt1.jpgAbb. 5: Heteroassoziatives neuronales Netz
rudolph_neuronales_netz_6.tif_fmt1.jpgAbb. 6: Autoassoziatives neuronales Netz
rudolph_neuronales_netz_7.tif_fmt1.jpgAbb. 7: Ein einfaches tiefes neuronales Netz

In Abhängigkeit davon, in welche Richtungen der Informationsfluss innerhalb eines Netzwerks erfolgt, unterscheidet man überdies zwischen sogenannten Feed-Forward- und rekurrenten Netzen (rückgekoppelte Netze, Recurrent Networks). Bei einem Feed-Forward-Netz erfolgt der Informationsfluss von den Inputneuronen über die Neuronen der einzelnen verdeckten Schichten bis hin zu den Outputneuronen. Rückkopplungen zwischen einzelnen Neuronen, wie beispielsweise eine Verbindung von einem verdeckten Neuron hin zu einem Inputneuron, sind nicht vorgesehen. Nach Abschluss der Berechnungen befindet sich das Netzwerk im gleichen Zustand wie vor der Ausführung der Berechnungen. Ein Feed-Forward-Netz verfügt demzufolge über keinerlei Erinnerungen an die vorangegangenen Berechnungen.

Im Unterschied dazu befindet sich ein rekurrentes Netzwerk aufgrund seiner Rückkopplungen nach Abschluss der Berechnungen in einem anderen Zustand als vor der Ausführung der Berechnungen. Das Netz verfügt im übertragenen Sinne, wie in Abbildung 8 gezeigt wird, über eine Art Kurzzeitgedächtnis.

rudolph_neuronales_netz_8.tif_fmt1.jpgAbb. 8: Ein einfaches rekurrentes (rückgekoppeltes) neuronales Netz

Aus dem Blickwinkel eines Mathematikers lassen sich sämtliche Signale bzw. Zahlenwerte, die an eine Neuronenschicht weitergeleitet bzw. von einer Neuronenschicht ausgegeben werden, als sogenannte Signalvektoren (Ein- und Ausgabevektoren) auffassen. Die Gesamtheit der Verbindungen zwischen zwei Neuronenschichten lässt sich hingegen mit Hilfe einer Matrix beschreiben. Da die einzelnen Matrixelemente die jeweiligen synaptischen Plastizitäten, also die Gewichtungsfaktoren, repräsentieren, spricht man in diesem Zusammenhang auch von einer Gewichtungsmatrix. Eine Matrix mit vier Spalten und drei Zeilen würde beispielsweise den Übergang von einer Schicht mit vier Neuronen in eine Schicht mit drei Neuronen widerspiegeln. Sämtliche Parameter eines primitiven neuronalen Netzes, das lediglich aus einer Eingabeschicht (Input Layer) und einer Ausgabeschicht (Output-Layer) besteht, lassen sich zu einer einzelnen Gewichtungsmatrix zusammenfassen. Die Signalweiterleitung von einer Schicht zur nächsten entspricht der Multiplikation des Signalvektors mit der Gewichtungsmatrix.

Die Verwendung von Gewichtungsmatrizen bietet gegenüber anderen Herangehensweisen den Vorteil, dass wir den Speicherbedarf für ein austrainiertes neuronales Netz so gering wie nur irgend möglich halten können. Zugegeben, Programmierer, die über wenig Erfahrung im Umgang mit Vektoren und Matrizen verfügen,...