It is about time to write something on the broader topics I covered in my diploma thesis "Improving a Hierarchical Evolutionary Algorithm with Applications in Optimization and Machine Learning". Even so, the word Graph does not appear in the title, the thesis was mainly about optimizing graphs, more specifically (spiking) neural networks.
- But what is Evolutionary Graph Optimization actually?
- What is it good for?
- What were the challenges we had to face? (part 2)
- Did we come up with something new? (part 2)
Many questions, to which there are even more answers. In case you are able to understand german language, feel free to read through the 150 pages of my thesis (it covers a lot more than just the four questions above).
To keep you motivated, let's first take a look at the screenshot below, showing HyperNSGA in action, a graphical software written in Rust that I created as part of the thesis to visualize and interact with the process of evolutionary graph optimization. HyperNSGA is an abbreviation in the style of HyperNEAT and stands for "Hyper-cube based neural net optimization using NSGA-II", the latter which is again an abbreviation for "Non-Dominated Sorting Genetic Algorithm II". In the top half of the screenshot, you see the the individual genomes, whereas in the bottom half you see the final networks. The genomes itself are a special kind of graph, so-called Compositional pattern-producing networks or CPPNs. These are smaller networks that we use to produce larger graphs with hierarchical and repetetive patterns. The pane on the right shows settings and performance metrics. Most settings can be modified in real-time, while an optimization is running.
What is Evolutionary Graph Optimization?
Evolutionary algorithms are a class of randomized algorithms, which are more or less based upon Darwin's theory of biological evolution. They use three concepts: A population of solutions, selection of solutions ("Survival of the Fittest") and reproduction of new, "child" solutions. The genetic algorithm (GA) is one of the best-known variants of an EA. It uses a binary representation for each solution in the population, called the "genome", and genetic operators like crossover and mutation to produce new genomes from existing genomes.
In evolutionary graph optimization, we make use of an evolutionary algorithm (EA) to optimize some, or all attributes of a graph. Graphs are made from nodes and edges, both of which can be attributed or weighted. So what a graph optimization algorithm has to accomplish, is to modify the node and edge weights in order to make the graph more "optimal" according to some function, which we call the fitness function. To make things more complex, the fitness function can be multivariate (i.e. not a single scalar value), in which case we are talking about Pareto-optimization. More advanced algorithms not only optimize the weighting of graphs but also modify their topology. The topology is the structure of the graph, the information, which nodes are connected to which other nodes via edges. Optimizing either the weighting or the topology of a graph while keeping the other constant is "easy", whereas doing both at the same time is a lot more "complex". What I tried to accomplish in my thesis is to find or develop an algorithm that is able to optimize both, topology and weighting of graphs, at the same time.
What is it good for?
An algorithm that optimizes the topology of a graph can also be used to create graphs. And indeed, the main application for our evolutionary graph optimization algorithm was as a graph generation algorithm.
In our case, we did research on spiking neural networks. Spiking neural networks try to model and simulate biological neural networks, like the ones that make up your nervous system (brain, medulla, etc.). In contrast to artificial neural networks (buzz word "deep learning"), the propagation of signals between connected neurons in spiking neural networks is not immediate, it takes time. This timing contains further information, for instance, the "phase" of a signal, and resembles the biological behavior. The actual biological behavior is a very complex electro-chemical physiological interaction and there are mathematical models, like the Hodgkin-Huxley model, that model the processes inside biological neurons (the flow of ions in both directions through the cell membrane). Obviously, this requires a lot of computational power, so that scientists have invented alternative mathematical models. The one I have chosen was the model of Izhikevich, which is biologically plausible, very well described in numerous papers, easy to implement correctly and most importantly, computational efficient.
Spiking neural networks would be perfect if we would only know how to create them. While crafting small networks by hand is a challenge, for larger networks, this becomes an impossible undertaking. Because of that, artificial neural networks use a regular, often fully-connected, multi-layered topology, and back-propagation to "tune" the synapse weights. With spiking neural networks, this is just not possible. While you can use a layered topology, you would still have to tune the synaptic delays. And what about multiple connections between two neurons with different delays? It started in the 1990's, when researchers first employed evolutionary algorithms to create and optimize those networks. But they quickly realized that by using simple genetic algorithms, too soon you run into limits, as the search-space explodes exponentially (you can optimize graphs with less than 100 nodes this way).
In short: Evolutionary graph optimization can be employed to create and optimize any kind of attributed graph, in our case, spiking neural networks. Spiking neural networks itself can be used for classification of data, in the same way as artifical neural networks are widely used today.
In the second part of this article I will talk about the challenges we had to face and whether we came up with new solutions.