Sie sind auf Seite 1von 6

Fachartikel, Philipp Mathis

NEURONALE NETZWERKE
für nicht-spielbare Charaktere

Titel: Neurale Netzwerke für NPC`s


Fachmagazin: Heise ( https://www.heise.de/)

Quellen:
https://towardsdatascience.com/an-exploration-of-neural-networks-playing-video-games-3910dcee8e4a
https://www.heise.de/tp/features/Bio-inspired-Computing-4876451.html
https://towardsdatascience.com/an-exploration-of-neural-networks-playing-video-games-3910dcee8e4a
https://www.innovecsgames.com/blog/neural-networks-games/
https://software.intel.com/content/www/us/en/develop/articles/an-introduction-to-neural-networks-with-an-
application-to-games.html
https://www.techradar.com/news/what-is-a-neural-network
https://www.datasciencecentral.com/profiles/blogs/crash-course-on-multi-layer-perceptron-neural-networks-1
http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture6.pdf
http://pages.cs.wisc.edu/~dpage/cs760/ANNs.pdf
http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf
Inhalt

1.1 Einleitung
1.2 Neurale Netzwerke für NPC`s
1.3 Beispiele
1.4 Theorem

2.1 Für Gegenersteuerung


2.2 Für Entscheidungswahl
2.3 Aufbau Neuronaler Netzwerke
2.4 Ein Gehirn ein NPC
2.5 Gruppen von NPC`s
2.6 Genetische Algorithmen, Fitness
2.7 Backpropagation und Reinforcement Learning
2.8 Supervised and unsupervised Learning

3.1 Fazit
3.2 Quellenangaben

Struktur

Einleitung: Zuerst wird das Ziel des Artikels untersucht; wo machen neurale Netzwerke für
NPC`s Sinn, um anspruchsvollere Gegner zu erschaffen. Wo wurden ANN schon
eingesetzt für NPC`s und auch Spieler? Der lernende Gegner – nicht nur für Schwärme.

Hauptteil: Wo eignen sich neurale Netzwerke, spezifisch NEAT (ANN mit genetischen
Algorithmen), Spezies-Entwicklung, Supervision durch den Spieler.. Einzelne Intelligente
Gegner mit komplexem Verhalten, Übergeordnetes NEAT mit vielen Agents, (Evt erwähnt:
ANN als Spieler, Rennspiele, Strategie, Funktionsweise des ANN), und reguläre NPC`s.
Decision-Makers* und Anpassung an Spielerverhalten.

Endteil: Neue Erkenntnisse über die Verwendung von ANN, Ausarbeitung einer der oben
genannten Bereiche (Species, racing, strategy, all kinds of genres). Testen einer KI welche
Decision-Makers nutzt um sich den Angriffen des Spielers anzupassen(hide-camp, frontal
attacks, flanking, nest building), und sich dann spezialisiert.
Schwerpunkte Steuerung mit Rays, Pixeln, Entscheidungstreffen, Supervision durch den
Spieler und Reinforcement Learning, Beispiel an eigenem ANN Projekt.

Beispiel für Decision-Maker AI: „More likely than not, you're going to use a traditional state
machine for the majority of AI decisions but you may be able to use neural nets to
complement the decisions or to enhance the hard-coded state machine. An example of
this might be a neural net that takes as input such things as health of the character,
available ammunition, and perhaps health and ammunition of the human opponent. Then,
the network could decide whether to fight or flee at which point the traditional AI would
take over to do the actual movement, path-finding, etc. Over several games, the network
could improve its decision making process by examining whether each decision produced
a win or a loss (or maybe less globally, an increase or decrease in health and/or
ammunition)...

...The use of neural nets for pattern recognition of various forms is their ultimate strength.
Even in the problems described, the nets would be used for recognizing patterns, whether
health and ammunition, forces acting on an object, or something else, and then take an
appropriate action. The strength lies in the ability of the neural nets to be trained on a set
of well-known patterns and then be able to extract meaningful decisions when presented
with unknown patterns. This feature of extrapolation from existing data to new data can be
applied to the areas of speech recognition, handwriting recognition and face recognition
mentioned in the introduction... “

Artikel https://software.intel.com/content/www/us/en/develop/articles/an-introduction-to-
neural-networks-with-an-application-to-games.html

Ebenfalls interessant wäre die Evolution eines player supervised NEAT, welches sich
weiter entwickelt und je nachdem welche Parameter zum Erfolg führten, sich verschiedene
Stats (STR, CON, DEX, INT) weiter entwickeln und sich spezialisieren – bei meiner
Kampfdrohne (siehe Titelbild) könnten je nach Entwicklung ein Tech-Tree verwendet
werden, der je nachdem verschiedene Module (Beine, Sensoren, Waffen) anbaut an
gewissen Slots, zB alle 2 Generationen.

NEATs könnten in gewissen Spielen sogar die FSM ersetzen durch Decision Makers,
welche verschiedene Parameter wie Health, Energy, Ammunition, Threat und weitere
Berücksichtigen (bevorzugte Spielerwaffe?) und dabei immer effizientere Entscheidungen
treffen auf gewisse Verhalten, wenn zB der Spieler die KI immer mit der selben Waffe
erwischt ein entsprechendes Verhalten wählen dass die Gewinnchancen der KI erhöht –
verschiedene Waffen testen usw.

Denkbar dabei wären persönliche Decision-Makers auf jeder Einheit welche auf das
jeweilige NEAT zugreifen und per forward feed Entscheidungen trifft, unter
Berücksichtigung einiger ausgewählter Parameter. Dadurch passt sich die KI auch dem
Spielerverhalten an, und je nach Spielstil des Spielers entwickelt sich das NEAT
unterschiedlich.
/////**************************************////////
/////* inputs hidden layers outputs *////////
/////**************************************////////
/////* x1 * - i1 - * *////////
/////* * ji * *////////
/////* x2 * - i2 - * - k1 *////////
/////* * j2 * *////////
/////* x3 * - i3 - * - k2 *////////
/////* * j3 * *////////
/////* x4 * - i4 - * *////////
/////**************************************////////

Sigmoid Funktion : f(x) = 1/(1+e^-x)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MathNet.Numerics.LinearAlgebra;
using System;
using Random = UnityEngine.Random;

public class NEAT : MonoBehaviour


{
public Matrix<float> inputLayer = Matrix<float>.Build.Dense(1, 3);
public List<Matrix<float>> hiddenLayers = new List<Matrix<float>>();
public Matrix<float> outputLayer = Matrix<float>.Build.Dense(1, 2);
public List<Matrix<float>> weights = new List<Matrix<float>>();
public List<float> biases = new List<float>();
private int neuronCount;
public float fitness;

//initialize the neuronal network


public void Initialise(int hiddenLayerCount, int hiddenNeuronCount)
{

inputLayer.Clear();
hiddenLayers.Clear();
outputLayer.Clear();
weights.Clear();
biases.Clear();
neuronCount = hiddenNeuronCount;

for (int i = 0; i < hiddenLayerCount + 1; i++)


{
Matrix<float> f = Matrix<float>.Build.Dense(1, hiddenNeuronCount);
hiddenLayers.Add(f);
biases.Add(Random.Range(-1f, 1f));
//assign weights
if (i == 0)
{
Matrix<float> inputToH1 = Matrix<float>.Build.Dense(3, hiddenNeuronCount);
weights.Add(inputToH1);
}
Matrix<float> HiddenToHidden = Matrix<float>.Build.Dense(hiddenNeuronCount, hiddenNeuronCount);
weights.Add(HiddenToHidden);
}

Matrix<float> HiddenLayers = Matrix<float>.Build.Dense(hiddenNeuronCount, hiddenNeuronCount);


//Debug.Log("neurons: " + HiddenLayers);

Matrix<float> OutputWeight = Matrix<float>.Build.Dense(hiddenNeuronCount, 2);


weights.Add(OutputWeight);
biases.Add(Random.Range(-1f, 1f));
RandomiseWeights();
}
public void GetFitness(float fit)
{
fitness = fit;
}

public NEAT InitialiseDeepCopy(int hiddenLayerCount, int hiddenNeuronCount)


{
NEAT n = new NEAT();
List<Matrix<float>> newWeights = new List<Matrix<float>>();

//copy weights
for (int i = 0; i < this.weights.Count; i++)
{
Matrix<float> currentWeight = Matrix<float>.Build.Dense(weights[i].RowCount, weights[i].ColumnCount);

for (int x = 0; x < currentWeight.RowCount; x++)


{
for (int y = 0; y < currentWeight.ColumnCount; y++)
{
currentWeight[x, y] = weights[i][x, y];
}
}

newWeights.Add(currentWeight);
}

List<float> newBiases = new List<float>();


newBiases.AddRange(biases);
n.weights = newWeights;
n.biases = newBiases;
n.InitialiseHiddenLayers(hiddenLayerCount, hiddenNeuronCount);

//return neural network


return n;
}

//initialize the hidden layers and neurons of the network


public void InitialiseHiddenLayers(int hiddenLayerCount, int neuronCount)
{
inputLayer.Clear();
hiddenLayers.Clear();
outputLayer.Clear();
Genetic.genetic.colors.Clear();

for (int i = 0; i < hiddenLayerCount + 1; i++)


{
Matrix<float> newHiddenLayer = Matrix<float>.Build.Dense(1, neuronCount);
hiddenLayers.Add(newHiddenLayer);
}
}

//*********************************************************************************************************

//override weights
public void RandomiseWeights()
{
for (int i = 0; i < weights.Count; i++)
{
for (int x = 0; x < weights[i].RowCount; x++)
{
for (int y = 0; y < weights[i].ColumnCount; y++)
{

weights[i][x, y] = Random.Range(-1f, 1f);

}
}
}
}

//mutate the values fourfold


public void mutate()
{
for (int i = 0; i < weights.Count; i++)
{
for (int j = 0; j < weights[i].ColumnCount; j++)
{
for (int k = 0; k < weights[i].RowCount; k++)
{
float weight = weights[i][j, k];

//mutate weight value


float randomNumber = UnityEngine.Random.Range(0f, 100f);
if (randomNumber <= 2f)
{ //if 1
//flip sign of weight
weight *= -1f;
}
else if (randomNumber <= 4f)
{ //if 2
//pick random weight between -1 and 1
weight = UnityEngine.Random.Range(-0.5f, 0.5f);
}
else if (randomNumber <= 6f)
{ //if 3
//randomly increase by 0% to 100%
float factor = UnityEngine.Random.Range(0f, 1f) + 1f;
weight *= factor;
}
else if (randomNumber <= 8f)
{ //if 4
//randomly decrease by 0% to 100%
float factor = UnityEngine.Random.Range(0f, 1f);
weight *= factor;
}

weights[i][j,k] = weight;
}
}
}
}

//this feeds input from the unitNEAT into the Neural Network
//it feeds the values of the 3 sensors into a hyperbolic tangens
//and sigmaoid function to generate an output forward and right/left
public (float, float) feedNeurons(float a, float b, float c)
{
inputLayer[0, 0] = a;
inputLayer[0, 1] = b;
inputLayer[0, 2] = c;

//a is left, b forward, c right


inputLayer = inputLayer.PointwiseTanh();
hiddenLayers[0] = ((inputLayer * weights[0]) + biases[0]).PointwiseTanh();

for (int i = 1; i < hiddenLayers.Count; i++)


{
hiddenLayers[i] = ((hiddenLayers[i - 1] * weights[i]) + biases[i]).PointwiseTanh();
}

outputLayer = ((hiddenLayers[hiddenLayers.Count - 1] * weights[weights.Count - 1]) + biases[biases.Count -


1]).PointwiseTanh();
//First output is acceleration and second output is steering
return (Sigmoid(outputLayer[0, 0]), (float)Math.Tanh(outputLayer[0, 1]));
}

//needed for tangens hyperbolicus


private float Sigmoid(float s)
{
return (1 / (1 + Mathf.Exp(-s)));
}

//*********************************************************************************************************

public float GetFitness() { return fitness; }


public int GetNeuronCount() { return neuronCount; }
public int GetInputCount() { return inputLayer.RowCount * inputLayer.ColumnCount; }
public int GetOutputCount() { return outputLayer.RowCount * outputLayer.ColumnCount; }

public float[][] getConnections()


{
//copy gene count
int geneNumber = Genetic.genetic.currentGenome;
//2D connections
float[][] connections = null;
List<float[]> connectionList = new List<float[]>();
for (int i = 0; i < geneNumber; i++)
{

}
//convert to 2D connection array
connections = connectionList.ToArray();
return connections;
}