Duale Hochschule Baden-Württemberg Standort Stuttgart, Campus Horb Florianstraße 15 72160 Horb am Neckar TIT 2008/NS 6. Semester Data-Mining Prof. Peter Schubert Data-Mining Algorithmen Clusteranalyse und Genetische Algorithmen Yves Fischer 12. April 2011 1 Einleitung Im Bereich des Data-Mining ist das Clustering (Klassenbildung) ein Unterdisziplin der Datenaufbereitung und -Selektion. Genetische Algorithmen sind Analyseverfahren die nach der Klassenbildung angewendet werden können. Genetische Algorithmen orientieren sich an der Natur und im speziellen an der Evolutionstheorie und Erkenntnissen der modernen Molekulargenetik. Im Wesentlichen den Vorgängen der Mutation, Vermischung/Crossover und Selektion. 2 Clustering Clustering-Algorithmen identifizieren Gruppierungen innerhalb von Daten. Ziel ist es, möglichst stark getrennte Gruppen zu finden, deren Elemente einander möglichst ähnlich sind. 2.1 K-Means k-means ist ein partitionierendes Minimaldistanz- Verfahren zum Clustering, bei dem die Menge an Elementen in die Anzahl k-verschiedene Klassen unterteilt wird [4, S.27]. Das Vorgehen nach Peterson [4, S.97] ist wie folgt: 1. Vorgabe der Anfangspartition, 2. Berechnung der Klassenzentroide, 3. Verschiebung des erstgefundenen Objektes in die Klasse kr1, zu dessen Zentroid dieses Objekt die kleinste euklidische Distanz besitzt, 4. Neuberechnung der Klassenzentroide nach jedem Klassenwechsel und.. 5. Weiter mit dem nächsten Objekt bei 3. Oder beenden, wenn z-mal hintereinander kein Objekt in eine andere Klasse verschoben wurde. Dann befindet sich jedes der n-objekte in ei- 1
10 5 Debian Package sizes clustered with k-mean (k=5,n=29373) 10 4 10 3 10 2 10 1 118.5 kb 1.5 MB 7.2 MB 41.9 MB 260.4 MB Paketgroesse Abbildung 1: Debian Paketgrößen, geclustert ner Klasse, zu deren Zentroid es im Vergleich zu den übrigen Klassen die kleinste euklidische Distanz aufweist. Abbildung 2.1 zeigt die Größe von Paketdateien des Debian Betriebssystems in 5 mit k-means ermittelten Gruppen (siehe Listing 1). 2.2 Kohonen Netze/SOM Als Alternative zum k-means Verfahren existiert mit dem Kohonen-Netzwerk (auch SOM, self organizing map) ein Ansatz dessen Funktionsweise an ein künstliches Neuronales-Netz angelehnt ist. Abbildung 2.2 zeigt den Aufbau eines Kohonen Netzes. Es ist unten der Eingabevektor o dargestellt, welche alle Eingangswerte enthält. Oben sind die Kartenneuronen K j dargestellt. Ihre Anzahl ist bestimmt durch die gewünschte Klassenanzahl. Vom Eingangsvektor o gibt es für jedes Kartenneuron K j einen Gewichtsvektor w j. Darüber geht von jedem Eingangswert o k eine Verbindung über das entsprechende Element des Gewichtsvektor (w jk ) an ein Kartenneuron K j. Der Abstand (Euklidische Distanz) zwischen Eingangsvektor o und dem Gewichtsvektor w j wird im Abbildung 2: Aufbau einer selbstorganisierenden Karte (Aus [4, S. 74]) Durchgang t bestimmt durch ED j (t) = m (o i w ji ) 2 [4, S. 74] i=1 Mithilfe der ED wird das System im Schritt t + 1 gelernt. Der Gewichtungsvektor w j (t + 1) wird gebildet aus dem alten w j, einer definierten Lernrate η(t) mal der Nachbarschaftsfunktion (e zj (t)) des Kartenneurons und der zugehörigen ED: w j (t + 1) = w j (t) + η(t) e zj (t) ED j (t) [4, S. 75] Nach einer als genügend angesehenen Anzahl an durchläufen wird die Klasse eines Eingangsvektors durch das Kartenneuron mit der kleinsten Distanz ED bestimmt. 3 Genetische Algorithmen In der Familie der Suchalgorithmen bieten GA (Genetische Algorithmen) eine Alternative zu berechnenden, aufzählenden und zufallsbasierten Algorithmen [1]. Berechnende (calculus) Algorithmen versuchen die optimale Lösung durch Lösen von Gleichungssys- 2
temen zu errechnen (indirekt) oder durch das ablaufen der Funktion in die Richtung der stärksten lokalen Steigung (direkt, hill-climbing). Dieses Vorgehen ist anfällig, nicht die optimale Lösung sondern ein lokales Optimum zu errechnen, falls einmal der falsche Weg eingeschlagen wurde. Aufzählende (enumerative) Algorithmen betrachten den gesamten Parameterraum. Dieser muss dafür finit oder zumindest diskret einschränkbar sein. Beim durchprobieren wird jeweils der bisher höchste/beste Wert gespeichert. Auf diese Art wird garantiert der allerbeste gefunden, jedoch auf Kosten der Geschwindigkeit. Zufällige (random) Algorithmen durchsuchen den Parameterraum an zufälligen Punkten und könnte auf diese Weise viel früher eine akzeptable Lösung finden. GA verwenden ebenfalls den Zufall als Hilfsmittel, jedoch lediglich als Einflussgröße. GAs unterscheiden sich in Ihrer Funktionsweise von den drei vorgestellten Algorithmen-Typen. GAs arbeiten mit einer kodierten Form der Funktionsparameter, nicht den Parametern selbst. Das bedeutet der Algorithmus ist sich keiner Bedeutung der Parameter bewusst, sodass er Rechenoperationen darauf ausführen könnte. Aus diesem Grund werden Parameter auch als Strings (Werte-Ketten) bezeichnet. Dem GAs ist grundsätzlich gleichgültig wieviele Parameter ein einzelner String kodiert. Alle drei vorgestellten Algorithmen-Typen Arbeiten auf Punkten im Parameterraum. GAs arbeiten auf einer evolutionären Population von Punkten. Um die einzelnen Punkte im Parameterraum qualitativ zu bewerten, arbeiten GAs anstatt mit Funktionsableitungen mit einer Ergebnisfunktion [1, S. 7]. Wie bei den zufälligen Algorithmen ist das Verhalten von GAs nicht deterministisch sondern probalibistisch. 3.1 Funktionsweise Ein simpler GA ist definiert durch die Ausführung drei verschiedener Operationen: Reproduktion Kreuzen (Crossover) Mutation Der GA startet mit einer Population möglicher Lösungen (oder Punkte ). Mutation manipuliert die Strings der Lösungen sodass jede eine verschiedenen Wert in der Ergebnisfunktion liefert. Dieser Wert entscheidet über die Fähigkeit der Lösung weiterzuexistieren (Fitness). Diese ist das künstliche äquivalent zur natürlichen Selektion. Die selektierten Lösungen durchlaufen folgend einen Prozess der Kreuzung. Dieser kann bei GA recht komplex oder auch sehr einfach sein. Zum Beispiel kann man eine Lösung sehr simpel mit einer weiteren kreuzen, indem der Anfang bzw. das Ende getauscht wird. Für den Erfolg des Prinzips der Kreuzung findet sich neben Anlehnung an die Biologie auch eine andere Erklärung. Goldberg [1, S. 13, dort [2]] zitiert den Mathematiker Hadamard wie folgt:... Indeed, it is obvious that invention or discovery, be it in mathematics or anywhere else, takes place by combining ideas. Vereinfacht gesagt, bauen GAs mithilfe der Kreuzung eine überlegene Lösung aus den besten Teillösungen. Dieses combining der Ideen lässt sich teils auch menschlich, anhand eines erfolgreichen Meetings zwischen kompetenten Personen versinnbildlichen. Die bisher nicht vorgekommene Mutation spielt, wie auch in der Natur, eine eher untergeordnete Rolle. Durch die Anwendung der Krezungsoperation kann es immer wieder vorkommen, das essentielle Merk- 3
male für immer verloren gängen. Die Mutation sorgt dafür, dass für jedes Merkmal die Chance besteht wieder zufällig aufzutauchen [1, S. 14]. 3.1.1 Merkmalskodierung und -Kreuzung Wie bereits erwähnt wurde arbeiten GA mit einer kodierten Form der Parameter. Es gibt verschiedene Methoden Parameter zu kodieren, welche je nach Anwendungsfall gewählt werden. Die einfachste und klassische Form ist die Binärkodierung der Merkmale. Das heisst man kodierte seine Merkmale als eine Folge von 0 - und 1 -Zeichen. Übertragen auf das Rucksack-Problem würde das bedeuten, dass es n-symbole gibt, wobei n die Anzahl der Dinge ist. Hier wird deutlich, dass GAs nicht die Bedeutung der Parameter nutzt: Die Gewichte und Größe der Dinge kennt, nur die Bewertungs (Fitness) Funktion kann die Parameter interpretieren. Die Binärkodierung ermöglicht auch besonders einfache, jedoch effektive Kreuzungsoperatoren. Beispielsweise kann zufällig oder fest eine Position im Binarystring definiert werden, ab welcher String 1 in String 2 kopiert wird und so Nachkommen erzeugt. 3.2 Anwendungen Mit GAs lassen sich grundsätzlich alle Probleme verarbeiten, deren Parameter in einzelne Merkmale zerlegt werden können und auf die dann, zusammengesetzt als String, die Mutation und Kreuzung angewendet werden kann. Ein Beispiel ist die Suche nach der kleinsten Wechselgeldzusammenfassung [3, Getting Started Tutorial]. Hierbei sind die Parameter die Anzahl der Münzen vom jeweiligen Typ und die Ergebnisfunktion bewertet einerseits ob die Zusammensetzung den gewünschten Betrag ergibt und lässt die Anzahl den genutzten Münzen in die Bewertung der Lösung mit einfliessen. Abbildung 3: Metamorphose eines Pixel-Bild (Listing 2) Ein anderes Beispiel ist genetische Manipulation von Bilder wie in Trist u. a. [7] beschrieben. Dabei stellt der Parameterraum alle möglichen Bilder anhand ihrer Pixelwerte dar und die Ergebnisfunktion/Fitness wird durch den Abstand zwischen einer Lösung und dem Ziel-Bild errechnet. Ein Beispiel für eine solche Bildmanipulation zeigt Abbildung 3.2. Es wurde mit einem sehr simplen Python-Programm erzeugt, wobei nur die Beschriebenen Methoden verwendet wurden. 3.3 Fazit Genetische Algorithmen sind vielseitig einsetzbar und im Gegensatz zu anderen Optimierungsalgorithmen sehr robust. Mithilfe von genetischen Algorithmen ist es nicht immer möglich die beste Lösung zu finden, jedoch eine vielleicht hinreichend akzeptable. 4
Literatur [1] Goldberg, David: Genetic Algorithms in Search, Optimization and Machine Learning. 1989 [2] Hadamard, J.: The psychology of invention in the mathematical field. 1949 [3] Meffert, Klaus ; Rotstan, Neil: A Brief Introduction to Genetic Algorithms. 2010. http://jgap.sourceforge.net/ doc/gaintro.html [4] Petersohn, Helge: Data-Mining. 2005 [5] Sivanandam, S. N. ; Deepa, S.N.: Introduction to genetic algorithms. 2008 [6] The Scipy community: K-means clustering and vector quantization (scipy.cluster.vq). http://docs.scipy.org/doc/ scipy/reference/cluster.vq.html [7] Trist, Karen ; Ciesielski, Vic ; Barile, Perry: Can t See the Forest: Using an Evolutionary Algorithm to Produce an Animated Artwork. 2010. http://www.cs.rmit.edu.au/~vc/ papers/cant-see-the-forest.pdf Listings Erzeugung der Grafik zu Paketgrößen: 1 from s c i p y. c l u s t e r. vq import kmeans, whiten, vq 2 import numpy a s np 3 4 # [ [ " dpkg dev ", 1 2 3 4 2 1 3 ], [... ],... ] 5 p a c k a g e s = g e t _ p a c k a g e s _ n a m e _ s i z e ( ) 6 7 k =5 8 f e a t u r e s = np. a r r a y ( 9 map ( lambda f : [ f [ 1 ] ], p a c k a g e s ) ) 10 11 f _ s t d = np. s t d ( f e a t u r e s ) 12 f e a t u r e s = f e a t u r e s / f _ s t d 13 # k mean 14 codebook, d i s t o r t = kmeans ( f e a t u r e s, k ) 15 # G r u p p e n z u g e h ö r i g k e i t 16 code, d i s t a n c e = vq ( f e a t u r e s, codebook ) 17 codebook = codebook f _ s t d 18 19 # G r u p p e n e l e m e n t e z ä h l e n 20 c o u n t s = np. b i n c o u n t ( code ) 21 b a r s = map ( lambda i : ( 22 codebook [ i ] [ 0 ] f _ s t d, 23 h u m a n i z e _ b y t e s ( codebook [ i ] ), 24 c o u n t s [ i ] ), r a n g e ( l e n ( codebook ) ) ) 25 b a r s. s o r t ( ) 26 27 p l o t ( map ( lambda f : f [ 1 ], b a r s ), 28 map ( lambda f : f [ 2 ], b a r s ), 29 k ) Listing 1: Erzeugt Abb. 2.1 Erzeugen der Bild-Verwandlung: 1 import image 2 import random 3 4 c l a s s GenImage ( image. PGMImage ) : 5 def mutate ( s e l f, x = 0. 0 0 1 ) : 6 " " " x : m u t a t o i n s w a h r s c h e i n l i c h k e i t i n p r o z e n t " " " 7 rand = lambda : random. r a n d i n t ( 0, 10 ) == 1 8 f o r x, y, v a l u e in s e l f : 9 i f rand ( ) : 10 wheight = random. r a n d i n t ( 1 0, 1 0 ) 11 s e l f [ x, y ] = min ( 2 5 5, max ( v a l u e + wheight, 0 ) ) 12 13 def sad ( s e l f, o t h e r ) : 14 sad = 0 15 f o r x in r a n g e ( min ( s e l f. width, o t h e r. width ) ) : 16 f o r y in r a n g e ( min ( s e l f. h e i g h t, o t h e r. h e i g h t ) ) : 17 sad += abs ( s e l f [ x, y ] o t h e r [ x, y ] ) 18 r e t u r n sad 19 20 def x_over ( s e l f, o t h e r ) : 21 " r e t u r n s new " 22 new = o t h e r. copy ( ) 23 f o r x, y, v a l u e in s e l f : 24 i f random. r a n d i n t ( 0, 1 ) == 0 : 25 new [ x, y ] = v a l u e 26 r e t u r n new 27 28 t a r g e t = image. PGMImage ( " d a t a / b u c h s t a b e n / c. pgm " ) 29 30 p o o l = [ ( f l o a t ( " i n f i n i t y " ), GenImage ( " d a t a / b u c h s t a b e n / a. pgm " ) ) f o r x in r a n g e ( 2 0 ) ] 31 # I n i t i a l m u t a t i o n 32 map ( lambda i : i [ 1 ]. mutate ( ), p o o l ) 33 34 # C a l c u l a t e SAD 5
35 p o o l = map ( lambda i : ( i [ 1 ]. sad ( t a r g e t ), i [ 1 ] ), p o o l ) 36 p o o l. s o r t ( ) 37 38 i, j = 0, 0 39 while p o o l [ 0 ] [ 0 ] > 2 0 0 0 : 40 i += 1 41 i f i % 15 == 0 : 42 j += 1 43 p r i n t i, p o o l 44 p o o l [ 0 ] [ 1 ]. s a v e ( " run %04d. pgm " % j ) 45 46 # Cross Over f i t t e s t 47 p o o l = p o o l [ : 3 ] 48 49 new_pool = [ ] 50 f o r i 1 in p o o l : 51 f o r i 2 in p o o l : 52 i f i 1 i s not i 2 : 53 new_pool. append ( ( 0, i 1 [ 1 ]. x_over ( i 2 [ 1 ] ) ) ) # i m l a z y 54 # Mutate 55 map ( lambda i : i [ 1 ]. mutate ( ), new_pool ) 56 57 # C a l c u l a t e SAD 58 new_pool = map ( lambda i : ( i [ 1 ]. sad ( t a r g e t ), i [ 1 ] ), new_pool ) 59 new_pool. s o r t ( ) 60 61 p o o l = new_pool Listing 2: Erzeugt Abb. 3.2 6