Fakultät für Informatik und Automatisierung Fachgebiet Datenbanken und Informationssysteme Studienarbeit Lernen von Entscheidungsbäumen auf Datenströmen Alexander Hoffmann Matrikelnr. 31386 Betreuer: Prof. Kai-Uwe Sattler Abgabedatum: 15.12.2004 -2- Abstrakt Im Rahmen dieser Studienarbeit sollte sich der Student in das Thema Mustererkennung auf Datenströmen in Echtzeit (online data mining) einarbeiten. Dabei wird ein Verfahren der Mustererkennung mit Entscheidungsbäumen vorgestellt. Konkret wird auf den Hoeffding Tree Algorithmus eingegangen. Dieser wurde auch in Java implementiert, wobei die Javabibliothek XXL mit ihrer Infrastruktur PIPES zum Einsatz kam. Alexander Hoffmann Studienarbeit -3- Inhaltsverzeichnis 1. Einleitung 2. Vorarbeit 2.1. Das Klassifikationsproblem 2.2. Datenströme 2.3. Entscheidungsbaumverfahren (Decision Tree Learning) 2.4. Der Informationsgewinn (Information Gain) 2.5. Mining auf Datenströmen 3. Hoeffding Tree 3.1. Idee 3.2. Algorithmus 4. Implementierung 4.1. PIPES 4.1.1 Überblick 4.1.2 Die Laufzeitumgebung 4.1.3 Das Paket PIPES 4.2. Meine Implementierung 4.2.1. Allgemeiner Programmablauf 4.2.2. Aufbau und Klassifikation 4.2.3. Neue Klassen 4.2.4. Tests und Ergebnisse 4.2.5. Mögliche Ressourcenoptimierung 5. Zusammenfassung 6. Literaturverzeichnis Alexander Hoffmann Studienarbeit -4- 1 Einleitung Jeder kennt das Wold Wide Web(WWW). Seit sich das WWW vor 20 Jahren etabliert hat stehen auch Themen wie Netzwerksicherheit, Privatsphäre und Verschlüsselung im Mittelpunkt der Diskussionen. Denn durch die ständig vorschreitende Vernetzung der Welt, sind geographische Entfernungen uninteressant geworden. Alle Menschen haben die Möglichkeit über das WWW miteinander zu kommunizieren. Allerdings sind die Absichten einiger Menschen nicht besonders ehrbar. Daher müssen Systeme her die die Privatsphäre des Einzelnen schützen können, als auch sensible Daten dem Zugriff Dritter entziehen und deren Verfälschung unterbinden. Solche Systeme sind Intrusion Detection Systeme(IDS)[1,2]. Ihre Aufgabe ist der Schutz eines IT-Systems. Dazu muss ein IDS in der Lage sein so genannte intelligente Angriffe zu erkennen. Zumeist bestehen diese IT-Systeme aus einer Gruppe von Rechnern die über ein LAN miteinander verbunden sind, und einem Gateway der die Verbindung zum Internet darstellt. Zur Sicherung des LANs verfolgen IDS zwei verschiedene Ansätze. • Anomalieerkennung: Netzwerkdaten am Gateway und im LAN werden auf ungewöhnliche Daten(Anomalien) hin untersucht • Missbrauchserkennung: Unterbinden des Missbrauchs von Ressourcen und Daten durch ungewöhnliche Systemnutzung Systemen, Die musterbasierte Angriffserkennung wurde schon 1986 im Rahmen eines Modells zur Angriffserkennung vorgestellt[3]. Die Idee dabei ist, wenn man die Signaturen bekannter Angriffe hat kann im Datenverkehr des LAN nach gleichen Signaturen gesucht werden. Mit dieser Angriffserkennung überwacht man vor allen bekannte Schwachstellen, konnte aber leicht abweichende Angriffsmuster nicht identifizieren. Daher ist es zwingend notwendig diese Technik weiter zu entwickeln. IDS sollen ja imstande sein bekannte und ähnliche Angriffe zu erkennen. Die Leistungsfähigkeit der heutigen IDS wird maßgeblich daran gemessen wie sie auf neuartige Angriffsversuche reagieren. Eins haben aber alle diese Systeme gemeinsam: sie arbeiten alle auf den Datenströmen die zwischen den Rechnern fließen, und sie müssen diese Daten so genau wie möglich Klassifizieren können. Alexander Hoffmann Studienarbeit -5- 2 Vorarbeit 2.1 Das Klassifikationsproblem Das Klassifikationsproblem kann so erklärt werden: Es gibt, Datensätze anhand einer Beispielmenge zu analysieren. Diese Datensätze werde ich im Weiteren mit Tupel oder Trainingsbeispiel bezeichnen. Jedes Tupel besitzt mehrere Merkmale, und ist einer Klasse zugeordnet. Diese Merkmale werden auch Attribute genannt. Die Beispielmenge wird benutzt um ein Modell zu erstellen. Dieses Modell soll hinterher in der Lage sein, neue Tupel aufgrund ihrer Attribute in die Klassen einzuordnen. Beispiel: Es gebe eine Beispielmenge mit N Trainingsbeispielen der Form (x,y). Dabei sei y der Bezeichner der Klasse zu der das jeweilige Tupel gehört, und x sei der Attributvektor der Form, x = (x1, x2, … , xm). Jedes xi repräsentiert hier ein Merkmal oder Attribut des Tupels. Ziel ist es nun ein Modell (y = f(x)) zu erzeugen, das für zukünftige Attributvektoren die Klasse vorhersagen kann, also Klassifizieren kann. Das Modell soll dies natürlich mit der größtmöglichen Genauigkeit tun. 2.2 Datenströme Da wir uns im Informationszeitalter befinden, mehr und mehr Daten ansammeln und die weltweite Vernetzung immer weiter zunimmt, gibt es auch immer mehr Datenströme die überwacht und kontrolliert werden müssen. Das charakteristische an Datenströmen ist, dass sie kein definierten Anfangs- und Endpunkt haben, das heißt sie sind unendlich. Daraus ergibt sich das man keine Datenströme speichern kann. Maximal kann man eine Sequenz eines Datenstromes speichern, da uns keine Möglichkeit bekannt ist unendlich viele Daten zu speichern. Außerdem macht das ja auch keinen Sinn, denn auf solchen großen Datenmengen Mustererkennungsverfahren einzusetzen ist im Aufwand wesentlich größer als im Nutzen. Man hat also ein definiertes Zeitfenster für die Arbeit auf Datenströmen. Algorithmen die hier Anwendung finden sollen, müssen mindestens eine so schnelle Verarbeitung der Daten garantieren wie die Datenankunftsrate des Datenstromes. Denn Daten die nicht gleich bei ihrer Ankunft verarbeitet werden konnten sind unwiederbringlich verloren. 2.3 Entscheidungsbaumverfahren (Decision Tree Learning) Der Zweck von Entscheidungsbäumen ist es Wissen kompakt und strukturiert zu speichern. Mit ihrer Hilfe kann man entscheiden zu welcher Kategorie(Klasse) ein Element(Tupel) mit welcher Wahrscheinlichkeit zuzuordnen ist. Ein Entscheidungsbaum besteht aus den Komponenten Wurzel, Knoten und Blatt. Jeder Entscheidungsbaum hat genau einen Wurzelknoten. Dieser Knoten unterscheidet sich von den Anderen dadurch, dass er keinen Vorgänger hat. Alle Knoten eines Entscheidungsbaums enthalten den Test eines Attributes, das sogenannte Aufteilungsattribut. Jeder Zweig eines Knotens entspricht einem möglichen Testergebnis. Die Blätter des Baumes enthalten die Klassenvorhersagen. Sie bilden außerdem die unterste Ebene des Baumes, denn Blätter haben keine Nachfolger. Die Abbildung 1 zeigt den Grundaufbau eines Entscheidungsbaumes. Alexander Hoffmann Studienarbeit -6- Attributtest X<4 Aufteilungsattribut Wurzel ... Knoten Y>0 Klasse Blatt ... Abb. 1: Grundaufbau eines Entscheidungsbaumes Zu klassifizierende Beispiele(Tupel) durchlaufen den Baum von der Wurzel bis zu einem Blatt. Den Pfad den ein solches Tupel durch den Baum nimmt nennt man auch den Einsinkpfad des Tupels. Der Aufbau von Entscheidungsbäumen wird mit maschinellem Lernen realisiert. Prinzipiell werden dabei rekursiv die Blätter des Baumes, von der Wurzel beginnend, durch Knoten ersetzt. Zum Lernen eines Baumes braucht man aber noch genügend klassifizierte Trainingsbeispiele. Das sind Tupel die von Hand einer Klasse zugeordnet wurden. Genügend Trainingsbeispiele sind deshalb erforderlich, weil sonst der sich ergebende Entschidungsbaum zu ungenau klassifiziert. Das Aufteilungsattribut eines Knotens wird mittels eines heuristischen Verfahrens bestimmt. Man kann dazu den Informationsgewinn oder auch den Gini Index benutzen. Bei den klassischen Lernverfahren werden zuerst alle Trainingsbeispiele eingelesen, und dann wird entschieden welches Attribut der Tupel die beste Aufteilung der Tupelmenge liefert. Das so ermittelte Attribut wird zum Aufteilungsattribut der Wurzel gemacht. Aus den entstandenen Teilmengen werden dann die Aufteilungsattribute für die jeweiligen Folgeknoten der Wurzel ermittelt. Ziel ist es hierbei irgendwann einmal Blätter zu bekommen die nur Tupel einer Klasse repräsentieren. Dann spricht man von reinen Blättern. Solche Blätter können nicht noch einmal geteilt werden. Ein zu klassifizierendes Tupel wird also bei der Wurzel abgegeben. Der Weg zu einem Blatt wird durch Tests in jedem Knoten bestimmt. Jeder Knoten besitzt dazu ja ein Aufteilungsattribut. Der Wert den das jeweilige Aufteilungsattribut bei dem Tupel hat bestimmt darüber, an welchen Kindknoten das Tupel weitergereicht wird. Da ein Baum per Definition kreisfrei ist, erreicht irgendwann jedes Tupel ein Blatt. Die Klasse die das Blatt repräsentiert wird dann auch dem zu klassifizierenden Tupel zu gewiesen. Und jedes Blatt gibt die Wahrscheinlichkeit weiter mit der das Tupel zu seiner Klasse gehört. Diese Wahrscheinlichkeit wird beim Trainieren eines Baumes erzeugt und kann für jedes Blatt anders sein. Bei reinen Blättern ist diese Wahrscheinlichkeit 100%. 2.4 Informationsgewinn (Information Gain) Die Berechnung des Informationsgewinnes ist für einen Entscheidungsbaum deshalb wichtig, weil damit das Aufteilungsattribut jedes Knotens bestimmt wird. Der Informationsgewinn soll somit ein Maß sein, das angibt wie gut die Aufteilung einer Alexander Hoffmann Studienarbeit -7- Tupelmenge ist. Er wird immer für ein Attribut berechnet. Je höher der Informationsgewinn eines Attributes ist umso besser eignet sich dieses zur Aufteilung einer Tupelmenge. Im Folgenden soll erklärt werden, auf welche Weise sich der Informationsgewinn berechnen lässt[10]. Sei S eine Tupelmenge die aus s Tupeln besteht. Angenommen das Klassenattribut habe m verschiedene Werte Ci (mit i= 1,...,m). Weiterhin sei si die Menge an Tupeln aus S die der Klasse Ci angehören. Somit ergibt sich der Informationswert um ein gegebenes Tupel zu klassifizieren wie folgt: m I(s1, s2, s3, …, s m) = - ∑ pilog2(pi) i=1 Hierbei muss beachtete werden, dass der duale Logarithmus verwendet wird, und dass die Wahrscheinlichkeit pi Wahrscheinlichkeit angibt mit der das Tupel zu Klasse Ci gehört. Die Wahrscheinlichkeit berechnet sich mit si/s. Habe das Attribut A nun v verschiedene Werte, { a1, a2, ... , av }. Soll Attribut A zum Aufteilen der Tupelmenge S benutzt werden, entstehen aufgrund seiner Werte v verschiedene Teilmengen, { S1, S2, ... , Sv }. Dabei enthält Sj die Tupel aus S die bei Attribut A den Wert aj haben. Ein Knoten der A als Aufteilungsattribut gewählt hat, würde v neue Zweige mit Blättern bekommen. Nun sei sij die Anzahl an Tupeln die zur Klasse Ci gehören und in Teilmenge Sj liegen. Weitere Repräsentanten der Klasse Ci können auch noch in den anderen Teilmengen liegen. Um den Informationsgehalt der Aufteilung der Menge S mittels Attribut A zu berechnen bedient man sich der Entropie. v E(A) = ∑ ( j=1 s1j + … + s mj s ) I(s1j, s2j, s3j,…, s mj) Dabei ist der Term nach dem Summenzeichen das Gewicht der j-ten Teilmenge. Dazu teilt man die Anzahl der Tupel der Teilmenge Sj durch die Gesamtzahl der Tupel in S. Je kleiner dabei der Entropiewert der Teilmenge ist, um so größer ist ihre Reinheit. Wendet man nun die Formel für den Informationswert auf diese Teilmenge an bekommt man diese Formel. m I(s1j, s2j, …, s mj) = - ∑ pijlog2(pij) i=1 sij pij = |Sj| Die Wahrscheinlichkeit pij gibt nun an wie groß die Chance ist, das ein Tupel aus Sj zur Klasse Ci gehört. Letztendlich ergibt sich der Informationsgewinn den die Aufteilung von S über ein Attribut A erzielt so: Gain(A) = I(s1, s2, s3, …, sm) – E(A) Mit anderen Worten, der Gain ist der Informationswert der übrig bleibt, wenn man die Entropie abzieht die das Attribut A erzeugt. Am besten lässt sich der Prozess anhand eines Beispiels nachvollziehen. Beispiel: Gegeben sei eine Tupelmenge mit 14 Tupeln. Die Tupel gehören 2 verschiedenen Klassen {ja, nein} an. 9 Tupel sind der Klasse ja und 5 der Klasse nein zugeordnet. Der Informationswert der Gesamtmenge ist daher: I(s1, s2) = I(9, 5) = -9/14*log2(9/14) - 5/14*log2(5/14) = 0,94 Alexander Hoffmann Studienarbeit -8- Bei der Aufteilung der Tupelmenge durch ein beliebiges Attribut mögen 3 Teilmengen entstehen, {(2; 3), (4; 0), (3; 2)}. Um die Vorteilhaftigkeit dieser Aufteilung zu messen, muss jetzt erst der Informationswert der Teilmengen ermittelt werden. I(s11, s21) = -2/5*log2(2/5) - 3/5*log2(3/5) = 0,971 I(s12, s22) = 0 I(s13, s23) = 0,971 Die Entropie und der Gesamtinformationsgewinn über diese Aufteilung ist dann dies: E(Attribut) = 5/14I(s11, s21) + 4/14I(s12, s22) + 5/14I(s13, s23) = 0,694 Gain(Attribut) = I(s1, s2) – E(Attribut) = 0,246 2.5 Mining auf Datenströmen Das Lernen von Entscheidungsbäumen auf Datenströmen ist ein Online Lernverfahren und gehört damit in die Kategorie des Online Data Mining. Das liegt im Trend, denn war in der Vergangenheit der Fokus der Entwicklung auf das Offline Mining gerichtet, beschäftigt man sich heute hauptsächlich mit dem Online Mining. Mining Anwendungen haben drei Hauptressourcen mit denen sie arbeiten. Das sind die Laufzeit der Anwendung, der benötigte Speicherbedarf und die Anzahl der zur Verfügung stehenden Trainingsbeispiele. Offline Mining: Die Trainingsbeispiele befinden sich im Speicher. Zum Lesen der Beispiele und zum Lernen des Klassifikators stehen der Anwendung keine Zeitschranken im Weg. Natürlich sollen auch diese Verfahren schnellstmöglich zu Ende kommen, da ihre Nutzer ja auch mit dem Ergebnis arbeiten wollen. Trotz ihrer großen Kapazität liegt der Flaschenhals dieser Verfahren in der Begrenztheit ihrer Trainingsbeispiele die sie lernen können. Das Lernen komplexer Bäume ist auch mit ihnen möglich aber teuer. Online Mining: Bei diesen Verfahren befinden sich die Trainingsbeispiele nicht im Speicher, weil sie da ja nicht reinpassen. Dadurch müssen Online Verfahren ihre Trainingsbeispiele so schnell verarbeiten, wie sie im Datenstrom ankommen. Der Flaschenhals umfasst also den Speicher und die Laufzeit der Anwendungen. Da die zu analysierenden Daten nicht mehr in den Speicher passen ist der Wandel von Offline Mining zum Online Mining keine Überraschung. Hauptproblem bleibt hier der Umgang mit dem Datenstrom. Wo die Offline Verfahren für ihre gespeicherten Daten einfach das beste Attribut zur Aufteilung der Menge aus der Kenntnis aller Tupel gezogen haben, sind den Online Verfahren Grenzen gesetzt. Sie haben eben nicht den Überblick über die gesamte Menge an Trainingsbeispielen, sondern sehen allenfalls eine Sequenz davon. Die größte Hürde die also zu nehmen ist, ist es eine geeignete Methode zu finden für die Wahl des Aufteilungsattributes für die Knoten des Entscheidungsbaumes. Weiterhin ist es wichtig den richtigen Zeitpunkt für die Aufteilung eines Blattes zu finden. Man bekommt verschiedene Bäume, wenn die Zeitpunkte der Aufteilung von Blättern unterschiedlich Bedingungen unterliegen. Daran schließt sich an, ohne die Alexander Hoffmann Studienarbeit -9- anderen möglichen Entscheidungsbäume explizit zu kennen, will man immer den besten Klassifikator bekommen. Als drittes hat die Reihenfolge in der die Tupel im Datenstrom auftauchen Einfluss auf das Aussehen des Entscheidungsbaumes. Obwohl man darauf wenig Einfluss hat, muss gewährleistet sein das immer der Baum am Ende gelernt wurde der neue Tupel am besten klassifizieren kann. Um eine Überanpassung von Bäumen an ein gegebenes Klassifikationsproblem zu vermeiden, muss es bei den Online Verfahren eine Möglichkeit geben, zwischen aktuell eingelesenen Tupeln und Tupeln die schon vor längerer Zeit eingelesen wurden zu unterscheiden. Ziel soll sein das der Baum aktuell und angepasst bleibt. Dazu müssen natürliche neue Tupel einen größeren Einfluss auf die Klassifikationsfähigkeit des Baumes haben als Ältere. Zu große und komplexe Bäume sind schwierig zu händeln. Außerdem könnte es sein, dass sie das Zeitfenster zwischen zwei ankommenden Tupeln beim Klassifizieren nicht einhalten. Dann muss es eine Möglichkeit geben die Bäume zu verkleinern. In der Regel wendet man hier Pruningtechniken an. Meist muss man gleichzeitig in Kauf nehmen das ein so verkleinerter Baum ungenauer klassifiziert. Je nach Anforderung die man an den Klassifikator stellt muss hier jeder seinen Königsweg finden. Alexander Hoffmann Studienarbeit - 10 - 3 Hoeffding Tree 3.1 Idee Die Zielvorgabe bei der Entwicklung des Hoeffding Tree war es, ein Lernverfahren auf Basis eines Entscheidungsbaumes zu entwickeln, zur Bearbeitung unendlich großer Datenmengen. Dabei soll das Lernverfahren jedes Datum nur einmal lesen und für dessen Bearbeitung nur soviel Zeit benötigen, bis das nächste Datum zur Bearbeitung zur Verfügung steht. Weiterhin soll kein Datum nicht bearbeitet werden[7]. Somit kann der Hoeffding Tree auch auf einem Datenstrom arbeiten. Das Hauptproblem vor dem man bei der Entwicklung des Hoeffding Tree’s stand war, wie wähle ich das Spaltungsattribut über einen Knoten? Da man einen Datenstrom nicht komplett in den Speicher eingelesen kann, muss es möglich sein das bestmögliche Spaltungsattribut eines Knotens aus einem Teilbereich der Datenmenge richtig zu wählen. Das wird mit der so genannten Hoeffding bound(additive Chernoff bound) realisiert. R2 * ln(c) ε= 2n Beispiel: Angenommen man hätte eine Variable r deren Wertebereich R(für eine Wahrscheinlichkeit ist R =1, und für einen Informationsträger ist R = log c wobei c die Klassenanzahl ist) ist. Es seien nun schon n unabhängige Werte von r verarbeitet worden, wobei der derzeitiger Mittelwert r’ sei. Der wahre Mittelwert von r ist aber noch nicht bekannt da noch nicht alle Werte von r verarbeitet worden sind. Dann garantiert die Hoeffding bound, dass mit Wahrscheinlichkeit 1-δ der wahre Mittelwert von r höchstens r’-ε ist[7]. Übertragen auf die Klassifizierung von Tupeln bedeutet dies: Ohne alle Tupel eingelesen zu haben kann man nicht mit Sicherheit sagen, welches Attribut sich am besten als Spaltungsattribut eignet. Wenn allerdings folgende Bedingungen eingehalten werden, versichert die Hoeffding bound, dass mit Wahrscheinlichkeit 1-δ das gleiche Attribut zur Spaltung eines Knotens gewählt wird wie bei einer statischen Ermittlung. • ΔG = G(Xfb) – G(Xsb) > 0 • ΔG > ε Sei hierbei G(Xi) die heuristische Methode die benutzt wird um Kandidaten für das Spaltungsattribut zu ermitteln. Möglichkeiten wären die Berechnung des Informationsgewinnes(information gain) oder die Ermittlung des Gini Indexes. Bezeichne Xfb das Attribut mit dem höchsten ermittelten G, dann wird Xfb als Firstbest-Lösung bezeichnet. Und sei Xsb das Attribut mit dem zweithöchsten G, und somit die Sekondbest-Lösung. Die ermittelten G sind nach n verarbeiteten Tupeln generiert worden. Zur Erhaltung der Aktualität des Hoeffding Tree hat man eine sehr simple Lösung gefunden. Erstmal registriert jedes Blatt die Trainingstupel die während des Alexander Hoffmann Studienarbeit - 11 - Baumaufbaues bei ihm ankommen. Ist es dann irgendwann einmal soweit und ein Blatt erfüllt alle Bedingungen und kann aufgeteilt werden, gibt das Blatt keines der erhaltenen Tupel an seine Kindblätter weiter. So müssen erst wieder genügend aktuellere Tupel gesammelt werden um die Kindblätter aufzuteilen. Eine weitere Eigenheit des Hoeffding Tree ist dies: Man lässt einfach nicht zu, dass auf einem Einsinkpfad zweimal über das gleiche Attribut eine Aufteilung vorgenommen werden kann. Dadurch erreicht man den Vorteil, dass der Baum nicht unkontrolliert in die Tiefe wachsen kann. Dazu erhält jedes Blatt nach seiner Erzeugung eine diskrete Menge X an Attributen. Diese Menge enthält alle Attribute über die das jeweilige Blatt noch eine Aufteilung durchführen kann. Hat der Algorithmus nun entschieden ein Blatt zu teilen, wird das Aufteilungsattribut aus der Menge X entfernt und der Rest der Attribute wird an die neuen Blätter des Knoten weitergegeben. Ist der Vorrat an Attributen aufgebraucht kann das letzte Blatt keine Teilung mehr durchführen und der Baum hat seine maximale Tiefe erreicht. Alexander Hoffmann Studienarbeit - 12 - 3.2 Algorithmus Nachfolgend ist der Algorithmus des Baumaufbaus dargestellt. Es gibt ein Trainingsbeispiel S, das eingefügt werden soll. Die Menge X bezieht sich immer auf das Blatt in welches das Beispiel S letztlich einsortiert wird. Diese Menge ist also unterschiedlich von Blatt zu Blatt. G() stellt die gewählte Aufteilungsfunktion dar, und δ ist die Wahrscheinlichkeit, die sich aus der gewünschten Genauigkeit der Auswahlattribute ergibt. Eingaben: S X G() δ ein Trainingsbeispiel der Art (x,y) Menge der möglichen Teilungsattribute Aufteilungsfunktion Wahrscheinlichkeit, ist Eins minus die gewünschte Wahrscheinlichkeit mit der das richtige Aufteilungsattribut gewählt werden soll Ausgaben: HT der Entscheidungsbaum Procedure HoeffdingTree(S,X,G,δ) • Für jedes Trainingsbeispiel S tue Folgendes: o Sortiere S in den bestehenden Baum ein o Für jedes Attribut in x, für das gilt: XiЄXl tue: Inkrementiere nijk(l) o Benenne Blatt l mit der Mehrheitsklasse der bis jetzt erhaltenen Trainingsbeispiele o Wenn die bis jetzt erhaltenen Trainingsbeispiele nicht alle der selben Klasse angehören tue: Erzeuge für jedes Attribut aus Xl: Gl(Xi) durch Benutzung der Zähler nijk(l) Sei Xfb das Attribut mit größtem Gl Sei Xsb das Attribut mit zweitgrößtem Gl Erzeuge ε Wenn Gl(Xfb) - Gl(Xsb) > ε tue: ◊ Ersetze Blatt l durch einen Knoten mit Aufteilungsattribut Xfb ◊ Für jedes neu entstehende Blatt lm sei Xm = Xl – Xfb ◊ Benenne lm mit der Mehrheitsklasse der Trainingsbeispiele aus seiner Partition in l • Gib HT zurück Alexander Hoffmann Studienarbeit - 13 - 4 Implementierung 4.1 PIPES 4.1.1 Überblick Im Folgenden soll die Infrastruktur PIPES (Public Infrastructure for Processing and Exploring Streams) vorgestellt werden. PIPES ist ein Bestandteil der Javabibliothek XXL für komplexe Anfrageverarbeitung über heterogenen Datenquellen[8,9]. Die Infrastruktur stellt Algorithmen bereit zur Konstruktion prototypischer Datenstrom Management Systeme (DSMS). Abbildung 2 gibt einen Überblick über die wesentlichen Bestandteile von PIPES. Abb. 2.: Architektur von PIPES [9] Zur Modellierung von Operatorgraphen, die sowohl gerichtet als auch azyklisch sind, stellt PIPES die folgenden Typen von Knoten bereit: Quellen, Operatoren und Senken. Eine Quelle sendet ihre Elemente (Tupel) an die bei ihr registrierten Senken. Eine Senke kann allerdings bei mehreren Quellen registriert sein. Sie konsumiert die ankommenden Elemente, solange sie bei einer Quelle registriert ist. Ein Operator vereint Quellen und Senken. Er verarbeitet eintreffende Elemente und reicht sie an bei ihm registrierte Senken weiter. In Abbildung 3 wird der klassische Publish- und Subscribe-Mechanismus dargestellt. Quelle Quelle Operator Quelle Senke Operator Quelle Senke Senke Senke Abb. 3: Publish- und Subscribe-Mechanismus Alexander Hoffmann Studienarbeit - 14 - Generell stellt PIPES vorgefertigte Gerüste für die individuelle Implementierung von Quellen, Operatoren und Senken zur Verfügung. Es ist allerdings noch wichtig zwischen statusbehafteten und nicht statusbehafteten Operatoren zu unterscheiden. Ein Operator der ohne weiteres Vorwissen Elemente verarbeiten kann wird als nicht statusbehaftet bezeichnet. Muss ein Operator aber für die Bestimmung eines Ergebnisses vorher schon Elemente konsumiert haben spricht man von einem statusbehafteten Operator. Die Selektion und Projektion sind Beispiele für nicht statusbehaftete Operatoren, wohingegen der Join und die Aggregation Vertreter statusbehafteter Operatoren sind. Aus der Kombination der Komponenten die in PIPES verfügbar sind, soll es nun möglich sein ein Datenstrom Management System zu erstellen. Dieses System soll voll funktionsfähig und auf beliebige Applikationen abstimmbar sein. Daher müssen charakteristische Eigenschaften von Datenströmen, wie etwa fluktuierende Datenraten, besonders berücksichtigt werden. Ein bibliotheksorientierter Ansatz bietet daher Vorteile gegenüber einer monolithischen Architektur, da diese schwerer an unterschiedliche Applikationen anpassbar ist. 4.1.2 Die Laufzeitumgebung Zudem verfügt PIPES über eine Laufzeitumgebung, die sich aus den Komponenten Ablaufsteuerung, Speicherverwaltung und Anfrageoptimierung zusammensetzt. Die verfügbaren CPU-Ressourcen eines Systems werden von der Ablaufsteuerung verwaltet. Sie steuert wie oft, wie lange und in welcher Reihenfolge die jeweiligen Knoten eines Operatorgraphen die CPU benutzen dürfen. Die Ablaufsteuerung ist eine 3-Schicht-Architektur. In der untersten Schicht werden zusammenhängende Operatoren zu komplexen virtuellen Operatoren zusammengefasst. Die mittlere Schicht enthält Threads die Strategien enthalten, die die Bildung der komplexen Operatoren der untersten Schicht steuert. Die Steuerung dieser Thread übernimmt die oberste Ebene. Dadurch werden nicht alle Operatoren durch einen globalen Thread gesteuert, aber es ist auch nicht jeder Operator einen Thread zugeordnet. Die Speicherverwaltung ist für die laufzeitgebundene und dynamische Aufteilung des verfügbaren Speichers unter den statusbehafteten Operatoren zuständig. Um aber auch auf veränderte Systemlasten reagieren zu können sind Verfahren zur Behandlung von Speicherüberläufen vorhanden. Das Ziel des Anfrageoptimierers ist die Erstellung des optimalen Anfragegraphen. Dies passiert unter Verwendung eines relativ einfachen Kostenmodells. Aufgrund der kontinuierlichen Anfragen liegt ein besonderes Augenmerk, auf der Umformung von Teilgraphen des Operatorbaumes zur Laufzeit. Alexander Hoffmann Studienarbeit - 15 - 4.1.3 Das Paket PIPES Sinn dieses Abschnittes soll es sein, einmal die Struktur und den Aufbau des Paketes zu erläutern. Als Referenz fungiert hier das Paket pipes wie es in der Releaseversion 1.1 Beta 1 im Juni 2004 zum Download zur Verfügung stand. Unterteilt ist das Paket in die folgenden Unterpakete: • memoryManager • operators • processors • scheduler • sinks • sources Die Unterpakete memoryManager, processors und scheduler gehören zur Realisierung der Laufzeitumgebung. Die Unterpakete operators, sinks und sources beinhalten die Klassen der Komponenten aus denen ein Datenstrom Management System zusammengesetzt wird. Die Speicherverwaltungskomponenten stecken im memoryManager. Hier ist eine Speicherstrategie implementiert, die die Verwaltung von physisch verteiltem Speicher erleichtert. Auch eine Strategie zur Behandlung von Speicherüberläufen ist hier verfügbar. Im Paket processors steckt die Ablaufsteuerung der Laufzeitumgebung. Verfügbar sind zwei Typen von Prozessoren. Einmal einen Prozessor mit hoher Priorität und dann noch den niedrig priorisierten Prozessor. Prozessoren hoher Priorität stellen immer Quellelemente eines Anfragegraphes dar, da diese vom Scheduler immer vorrangig behandelt werden müssen. Das scheduler-Paket enthält schließlich die Komponenten der Anfrageoptimierung. Hier sind schon einige Schedulingstrategien implementiert, so zum Beispiel Round Robin und eine zufällige Schedulingstrategie. Das Paket sink enthält die Senken. Es gibt eine Senke die ihre konsumierten Elemente auf der Konsole ausgibt, und eine Senke die ihre Elemente in einem separaten Fenster ausgibt. Diese Senke kann der Benutzer mittels einiger Buttons in ihrem Ausgabeverhalten steuern. Die Quellen befinden sich natürlich im Paket sources. Es gibt eine Quelle die zufällig gewählte Integerwerte zu einem Datenstrom verbindet. Eine zweite Quelle kann aufsteigende oder absteigende Integerwerte eines gegebenen Intervalls zu einem Datenstrom verknüpfen. Die dritte verfügbare Quelle entspricht dem Design Pattern “Adapter“. Sie kann Elemente die sie bekommt in ein nutzerdefiniertes Format transferieren. Die große Gruppe der Operatoren stecken im Paket operators. Dieses Paket ist in weitere Teilpakete unterteilt. Vorhanden sind hier die Operatoren für die Funktionen Union, Join, Group, Map, Sort, Differenz, Identität, Filter und Abstand. Alexander Hoffmann Studienarbeit - 16 - 4.2 Meine Realisierung 4.2.1 Allgemeiner Programmaufbau Diese Implementierung des Hoeffding Tree arbeitet nur auf numerischen Werten. Es müssen also, durch eine geeignete Vorverarbeitung, von eventuellen linguistischen Werten, rein numerische Trainings- und Testtupel erzeugt werden. Ansonsten braucht man im Wesentlichen für die Realisierung des Hoeffding Tree nur eine Quelle, eine Senke und einen Operator. Die Quelle sollte die Fähigkeit besitzen Tupel die in einer Datei gespeichert sind einzulesen und daraus einen Datenstrom zu erzeugen. Eine solche Quelle war in PIPES nicht verfügbar und wurde daher implementiert. Ein geeigneter Operator und eine geeignete Senke waren dagegen schon vorhanden und konnte entsprechend genutzt werden. Für den Baumaufbau benutzt man einen statusbehafteten Operator, um den Zustand des aktuellen Baumes von der Verarbeitung eines Tupels zur Nächsten weitergeben kann. Hier ist es der Operator Aggregator, der Verwendung findet. Da bei der Klassifikation von Tupeln irrelevant ist, was mit dem vorherigen Tupel passiert ist, benutzt man den nicht statusbehafteten Operator Mapper. Die Operatoren Aggregator und Mapper erwarten als Input einen Datenstrom und eine Funktion, die ihnen mitteilt wie die Elemente des Datenstromes verarbeitet werden sollen. Abbildung 4 soll dies verdeutlichen. Funktion (HT_construct) Datenstrom (klassifiziert) Funktion (HT_classify) Datenstrom (nicht klassifiziert) Operator (Aggregator) Operator (Mapper) Datenstrom (klassifiziert) Abb. 4: Erzeugung des Baumes & Klassifikation mit dem Baum Ein Beispilaufruf sieht damit wie folgt aus: Senke ( Operator ( Quelle, Funktion ) ) Dieser Ausdruck wird von Innen nach Außen aufgelöst. Die Quelle gibt ihre erzeugten Elemente an den Operator. Dieser nimmt mit Hilfe der Funktion eine Verarbeitung der Tupel vor. Danach leitet er die Elemente weiter an die Senke. Diese verkonsumiert die Elemente schlußendlich. Verwaltet wird der Hoeffding Tree in einem Vektor. Die Elemente des Vektors sind die Knoten und Blätter des Baumes. Dabei hat jedes Element des Vektors(die Knoten also) einen Bezeichner der den Knoten eindeutig identifiziert, und gleichzeitig seine Position im Vektor angibt. Jeder Elternknoten besitzt ein Feld das die Bezeichner seiner Kinder enthält. Anhand dieser Verbindungen kann man durch den Baum navigieren. Wobei es nur möglich Alexander Hoffmann Studienarbeit - 17 - ist von der Wurzel zu den Blättern zu wandern, da es sich um einen gerichteten Graphen handelt. Neue Blätter die im Verlauf des Baumaufbaus entstehen, werden an das Ende des Vektors angehängt. Wenn ein Blatt des Baumes nun durch Aufteilung in einen Knoten gewandelt wird, braucht der Knoten keine Informationen mehr über die Tupel zu speichern. Das übernehmen von jetzt an die Kinder der Knotens. Daher wird bei der Aufteilung eines Blattes auch der zugehörige Cube gelöscht. Alle Informationen die im Cube gespeichert waren gehen damit verloren. Das ist auch so gewollt, weil aktuelle Tupel einen größeren Einfluß auf die Gestalt des Entscheidungsbaumes haben müssen als ältere Tupel. Die Kindblätter bekommen nur eine Klassenzugehörigkeit von ihren Elternknoten zugewiesen. Informationen über Tupel müssen die Kindknoten seit ihrer Erzeugung selbst sammeln. Im Folgenden soll näher auf die Speicherung des Wissens eines Entscheidungsbaumes eingegangen werden. Die Informationen über die Tupel eines Datenstromes speichert der Hoeffding Tree in einem 3 dimensionalem Feld, im weiteren auch als Cube bezeichnet. Registrieren eines Tupels Nur für die Blätter des Entscheidungsbaumes existiert ein Cube. Jede Zelle des Cubes enthält einen Zähler der nach belieben inkrementiert werden kann. Bei einem Tupel, das in den Cube eines Blattes einsortiert werden soll, wird für jedes Attribut der Zähler einer Zelle inkrementiert. Zum Beispiel sei das Attribut Körpergröße bei einem Tupel Z mit 184 cm angegeben. Das Attribut Körpergröße sei das 4. Attribut des Tupels. Also sucht man sich im Cube die Ebene die für die Klasse des Tupels Z zuständig ist. Siehe dazu Abbildung 5. Klasse A t t r i b u t A t t r i b u t Attribut = Körpergröße Attributwert = 184 cm Attributwert Attributwert Abb. 5: Speichercube In dem relevanten zweidimensionalen Feld sucht man sich jene Zelle, die für Attribut Körpergröße und Attributwert 184 cm zuständig ist, und inkrementiert den Wert der Zelle um Eins. Alexander Hoffmann Studienarbeit - 18 - Benötigt werden die Informationen des Cubes für die Berechnung des Informationsgewinnes und die Bestimmung der Bereiche der Kindknoten bei einer Aufteilung eines Blattes. Aufteilung eines Blattes Für die Aufteilung von Blättern kann man verschiedene Ansätze verfolgen. Ich habe mich dafür entschieden, dass jedes Blatt so viele Kindknoten erzeugt, wie es Klassen gibt nach denen Tupel klassifiziert werden können. Sei nun über den Informationsgewinn ein Attribut Z ermittelt worden, das für die Aufteilung geeignet ist. Dann nimmt sich der Algorithmus aus dem Speichercube das zweidimensionale Feld her, welches zu dem ermittelten Attribut Z gehört. Ein Beispiel ist in Abbildung 6 gezeigt. 1 4 Anschließend wird mittels Mittelwertbildung der K 3 l Schwerpunkt jeder Klasse im Wertebereich a 2 1 2 2 des Attributes Z bestimmt. Im Beispiel ist der s 2 3 s 1 Schwerpunkt der Klasse 2: e C2 = (1*4+2*6+2*7)/(1+2+2) = 6 1 2 3 4 5 6 7 8 9 10 Attributwert C3 ~ 8 und C1 ~ 5 für Klasse 3 und 1. Abb. 6: Beispiel Die Schwerpunkte werden jetzt noch numerisch geordnet. Es kommen immer so viele Schwerpunkte raus, wie man Klassen hat. Deshalb bestimmt man den Mittelpunkt zwischen zwei benachbarten Klassenschwerpunkten und nimmt den so ermittelten Wert einmal als Ober- und als Untergrenze der benachbarten Bereiche. Zusammen mit der absoluten Untergrenze Null aller Attributwerte und der Obergrenze aller Attributwerte aus preferences hat man genug Werte um die Bereiche festzulegen. Veranschaulicht ist der Sachverhalt in Abbildung 7, am Beispiel Körpergröße. 3 Kindknoten -> 3 Ober- und 3 Untergrenzen Ci – Schwerpunkt der Klasse i Oi – Obergrenze der Klasse i Ui – Untergrenze der Klasse i U1 Kind2 O1&U2 Kind1 O2&U3 Kind3 O3 Körpergröße in cm 0 100 C1 C2 C3 200 Abb. 7: Bereiche der Kindknoten bei Aufteilung 4.2.2 Aufbau und Klassifikation Training eines Hoeffding Trees Soll ein neuer Hoeffding Tree erzeugt werden, muss ein Aufruf der folgenden Art realisiert werden: Printer( Aggregator( FileSource(“Dateiname”), HT_construct )) Alexander Hoffmann Studienarbeit - 19 - Strukturierter, aber im Grunde genauso steht dieser Aufruf in HT_Driver.java. Die Quelle FileSource liest die Tupel die in der angegebenen Datei stehen ein, und gibt sie an den Operator Aggregator weiter. Der Operator ist die eigentliche Pipe. Deshalb sind auch alle Operatoren von der Klasse Pipe abgeleitet. Der Aggregator bekommt die Quelle der Tupel und eine Funktion übergeben. Mittels der Funktion führt der Aggregator Operationen auf dem Datenstrom aus. Die Printersenke gibt die Elemente die sie vom Aggregator bekommt dann in der Konsole aus. Wie sieht nun die Verarbeitung der Elemente durch den Aggregator aus? Der Aggregator startet für jedes Tupel des Datenstromes die Funktion HT_construct. Dabei übergibt er der Funktion das aktuelle Tupel des Datenstromes und den aktuellen Baum. Da dieser Operator statusbehaftet ist bekommt er immer den aktuellen Baum vom vorherigen Durchlauf der Funktion zurück, außer beim ersten Aufruf der Funktion. Zu diesem Zeitpunkt hat der Operator noch keinen Baum und übergibt an der Stelle nichts an die Funktion. Auch kann der Operator die Elemente des Datenstromes nur nacheinander verarbeiten, da er jedes Mal den aktuellen Baum mit an die Funktion übergibt. Beim ersten Aufruf der Funktion HT_construct initialisiert diese den Baum. Der besteht zu diesem Zeitpunk nur aus der Wurzel. Diese wiederum ist hier ein Blatt das standardmäßig der Klasse 0 zugeordnet ist. Nach diesem Durchlauf der Funktion wird sie das Blatt an den Aggregator übergeben, und bekommt es beim nächsten Aufruf zusammen mit einem Neuen Tupel wieder zurück. Um ein Tupel korrekt in den Baum einzusortieren, muss natürlich zuerst dasjenige Blatt ermittelt werden in welches das Tupel einsortiert werden soll. Dazu beginnt der Algorithmus mit dem Test den die Wurzel jedem neuen Attribut unterzieht, um zu entscheiden an welches der Wurzelkinder das Tupel weitergereicht wird. Das heißt, in der Wurzel steht drin(im Testattribut) welches Attribut des Tupels getestet wird. Der Wertebereich dieses Attributes ist unter den Wurzelkindern aufgeteilt, und anhand des Wertes den das Testattribut bei dem einzuordnenden Tupel hat wird es an eins der Kinder weitergegeben. Jeder Knoten entlang des Einsinkpfades führt einen solchen Test durch und gibt immer den Namen des Knotens zurück, der das Tupel als nächstes bekommt. Der Algorithmus terminiert, wenn ein Knoten eine -1 zurückgibt. Dann nämlich hat das Tupel ein Blatt erreicht. Die -1 ist ein Standardwert der immer zurückgegeben wird, wenn ein Knoten keine Kinder hat und somit ein Blatt darstellt. Ist das Blatt nun ermittelt, in dessen Bereich das einzuordnende Tupel fällt, wird es im Cube des Blattes registriert. Nachdem die Informationen über das Tupel gespeichert sind, wird getestet ob sich die Mehrheitsverhältnisse der Klassen geändert haben. So ein Blatt sagt immer den Namen der Klasse voraus von der die meisten Tupel bei diesem Blatt angekommen sind. Hat durch das neue Tupel eine andere Klasse echt mehr Tupel in dem Blatt, als die bisherige Hauptklasse, dann wird dieser Wert aktualisiert. Im nächsten Schritt wird getestet ob es günstig ist das Blatt jetzt zu teilen. Dazu werden die Informationsgewinne über alle Attribute berechnet, über die das Blatt noch geteilt werden darf. Die Attribute die nicht mehr benutzt werden dürfen sind im Feld impossibleAttributes mit 1 gekennzeichnet. Das sind alle Attribute die auf dem Pfad von der Wurzel bis zu diesem Blatt schon als Testattribut benutzt worden sind. Alexander Hoffmann Studienarbeit - 20 - Nachdem alle Informationsgewinne ermittelt worden sind, wird die Differenz zwischen den größten Beiden berechnet. Ist die Differenz größer als die Hoeffding Schranke ε, wird das Blatt geteilt. Als letztes wird noch geprüft ob der aktuelle Baum in der Datei HoEfFdInGtReE.txt gespeichert werden soll. Der Zeitraum zwischen den Sicherungen kann in der Datei preferences.java eingestellt werden. Die Funktion HT_construct besitzt einen Zähler (updated). Dieser wird bei jedem Attribut das verarbeitet wurde inkrementiert. Ist die eingestellte Anzahl an Tupeln verarbeitet worden wird der Baum in die Datei gesichert, wobei er den alten Baum überschreibt. Als Letztes wird der Vektor mit dem aktuellen Baum an den Operator zurückgegeben. Klassifizieren mit dem Hoeffding Tree Der Aufruf um mit einen Hoeffding Tree zu klassifizieren sieht so aus: Printer( Mapper( FileSource(“Dateiname”), HT_classify )) Auch dieser Aufruf steht in der HT_Driver.java. Die Quelle FileSource erzeugt wieder einen Datenstrom aus den Tupeln der angegebenen Datei. Zusammen mit der Funktion sind das die Eingaben für den Operator. Auch der Mapper übergibt jedes Tupel der Reihe nach der Funktion, und wartet bis er das bearbeitete Tupel von der Funktion zurückbekommt. Das klassifizierte Tupel wird dann an die Quelle weitergeleitet. Wurde die Funktion HT_classify mit einem Tupel aufgerufen, liest sie als erstes den Baum der in der Datei HoEfFdInGtReE.txt steht in den Vektor HTreeV ein. Danach wird das übergebene Tupel in ein Stringfeld zerlegt, wobei jede Zelle des Feldes ein Attribut beinhaltet. Um das Tupel zu klassifizieren muss es den Baum von Wurzel bis zu einem Blatt durchlaufen. Hierbei werden dieselben Methoden und Algorithmen benutzt wie beim Training des Baumes. Wurde die Klasse bestimmt, wird das Tupel in einen String zurück verwandelt. Dabei wird die gefundene Klasse an das Tupel drangehängt. Das fertige Tupel wird an den Operator zurückgegeben. 4.2.3 Neue Klassen Meine Implementierung umfasst folgende Dateien: • FileSource.java Quelle • Node.java Knotenklasse; alle Knoten und Blätter gehören zu dieser Klasse • HT_construct.java Funktion für den Baumaufbau • HT_classify.java Funktion zum Klassifizieren • Preferences.java Enthält alle wichtige Konstanten eines Baumes • HT_driver.java Klasse über die der Aufruf erfolgt Tabelle 1: neue Klassen Alexander Hoffmann Studienarbeit - 21 - Die Klasse FileSource ist vom Typ Source, und damit ist sie eine Quelle. Ihre Funktionalität beschränkt sich darauf Tupel zeilenweise aus einer Datei zu lesen, und diese weiter an den Operator zu reichen. Dazu erwartet FileSource als Übergabeparameter den Namen der Datei, aus der gelesen werden soll, in Form eines Strings. Die Quelle besitzt noch eine Variable für das Zeitfenster zwischen zwei Tupeln. Standardmäßig ist dieses auf 100 Millisekunden eingestellt. Wünscht man ein anderes Zeitfenster muss man das explizit als zweite Übergabevariable bei der Erzeugung der Quelle angeben. Node beschreibt einen Knoten im Baum. Für jeden Knoten im Baum erzeuge ich also ein Objekt dieser Klasse. Bei der Initialisierung werden die Werte aller Variablen mit -1, für nicht gesetzt, erzeugt. Verwaltet werden die Nodes in einem Vektor. Zur eindeutigen Identifizierung besitzt jede Node einen Identifikator. In meinem Fall ist es eine positive ganze Zahl, wobei die Wurzel immer den Identifikator Null hat. Weiterhin hat jeder Knoten eine Variable die seine aktuelle Mehrheitsklasse angibt. Falls es sich um einen Inneren Knoten handelt ist seine Variable für das Aufteilungsattribut gesetzt. Handelt es sich dagegen um ein Blatt, dann ist seine Wahrscheinlichkeit der entsprechenden Mehrheitsklasse gesetzt. Während des Trainings des Entscheidungsbaumes sammelt ein Blatt alle Tupel die bei ihm ankommen. Sind die Tupel nicht alle von derselben Klasse, drückt dieser Parameter das Verhältnis der Mehrheitsklasse zu allen Tupeln des Blattes aus. Ist die Wahrscheinlichkeit nicht berechenbar, wird eine -1 zurückgegeben. Jeder Knoten hat also ein Feld (seenTupleCounter), das die Tupel in Abhängigkeit von der Klasse mitzählt. Zum Beispiel könnte in diesem Feld stehen: Dieses Blatt hat 2 Tupel der Klasse Null, 1 Tupel der Klasse Eins und 3 Tupel der Klasse Zwei gesehen. Für die Menge an Diskreten Attributen, die noch zur Aufteilung eines Tupel zur Verfügung stehen, ist ein weiteres Feld (impossibleAttributes) nötig. Dazu erzeuge ich ein Feld der Länge eines Tupels, und markiere darin die Stellen mit einer 1, wo die Attribute nicht mehr zur Aufteilung des jeweiligen Blattes zur Verfügung stehen. Ein weiteres Feld(next) braucht der Knoten um seine Kindknoten abzuspeichern. Dazu ist ein zweidimensionales Feld nötig. Gespeichert werden der Identifikator des Kindknotens und zwei Werte für das Werteintervall des Aufteilungsattributes für das der Kindknoten zuständig ist. Ein letztes dreidimensionales Feld (counter) wird gebraucht um die Werte der Tupelattribute mitzuzählen. Die drei Dimensionen werden benötigt für die Klassenzugehörigkeit, das jeweilige Attribut und die möglichen Werte des Attributes. Die Klasse – Attribut – Abhängigkeit wird gebraucht zur Bestimmung der Entropie bei der Berechnung des Informationsgewinnes. Die Wert – Klasse – Abhängigkeit ist wichtig für die Ermittlung der Bereiche der Kindknoten bei der Aufteilung eines Blattes. In der Funktion HT_construct ist beschrieben wie der Baumaufbau durchzuführen ist. Sie hat eine Methode die den aktuellen Baum nach einer festgelegten Zeitspanne in der Datei HoEfFdInGtReE.txt speichert. Der Vorteil dieses Mechanismus ist, dass man gleichzeitig Trainieren und Klassifizieren kann. Denn nachdem der Baum das erste Mal abgespeichert wurde kann der Klassifikator schon anfangen mit Klassifizieren obwohl der Baum noch nicht fertig trainiert wurde. Alexander Hoffmann Studienarbeit - 22 - HT_classify ist die Funktion, die für das Klassifizieren eines Tupels zuständig ist. Dabei wird als erstes der aktuelle Baum aus der Datei HoEfFdInGtReE.txt eingelesen. Danach lässt man das Tupel von der Wurzel aus durch den Baum wandern, bis ein Blatt erreicht wird. Dem Tupel wird die jeweilige Klasse angehängt und an den Operator zurückgegeben. In Preferences sind alle Konstanten und Parameter, die für einen Baumaufbau relevant sind, festgelegt. Es ist daher immer sinnvoll vor dem Start diese Parameter zu aktualisieren. Zum Beispiel sind hier die Anzahl der Attribute eines Tupels, die Anzahl der Klassen nach denen klassifiziert werden soll und andere Parameter festgehalten. HT_driver ist die Klasse über welche der Baumaufbau und die Klassifikation gestartet werden. Übergibt man dieser Klasse den Wert construct startet der Algorithmus für den Baumaufbau. Bei einer Übergabe von classify startet der Klassifikator. Als zweiter Wert an die Klasse HT_driver, muss noch der Klassenname der Datei übergeben werden, aus der ein Datenstrom erzeugt werden soll. 4.2.4 Tests und Ergebnisse Bei den Tests mit dem Hoeffding Tree sollte der Vergleich mit anderen Klassifikationsbäumen angestrebt werden. Zum Vergleich wurde die Data Mining Software Weka von der University of Waikato, aus Neu Seeland herangezogen. Es handelt sich dabei um eine Algorithmensammlung die sich unter einer Systemoberfläche vereinigen. Weka enthält neben Algorithmen zur Klassifikation auch welche die mit Assoziationsregeln und Clusteringverfahren arbeiten. Zusätzlich ist Weka ebenfalls in Java geschrieben. Um den Hoeffding Tree mit den anderen Bäumen vergleichbar zu machen, mussten einige Annahmen getroffen werden. Da der HoffdingTree keine Pruningtechniken beherrscht, wurden auch bei den anderen Bäumen keine eingesetzt. Die Tests wurden auf zwei unterschiedlichen Datensätzen durchgeführt. Wobei jeweils der Trainingsdatensatz und der Testdatensatz dieselben Tupel enthielten. Datensatz Weather Das ist ein sehr kleiner Datensatz. Er enthält nur 14 Tupel. Die Tupel bestehen aus 5 Attributen. Die Daten sollen nach 2 Klassen klassifiziert werden. Knoten gesamt Blätter j48 8 5 100 0 NBTree 1 1 78,6 21,4 REPTree 1 1 64,3 35,7 RandomTree 12 7 100 0 10 Bäume trainiert 100 0 7 81,5 28,5 RandomForrest HoeffdingTree 4 Richtige Falsche Vorhersage(%) Vorhersage(%) Tabelle 2: Ergebnisse mit dem Datensatz Weather Alexander Hoffmann Studienarbeit - 23 - Datensatz Iris Dieser Datensatz ist da schon größer. Er enthält 150 Tupel. Wie beim Weatherdatensatz bestehen auch hier die Tupel aus 5 Attributen. Die Tupel kommen aber aus 3 Klassen. Knoten gesamt Blätter j48 9 5 98 2 NBTree 9 5 98 2 REPTree - - - - 37 19 100 0 10 Bäume trainiert 100 0 7 90 10 RandomTree RandomForrest HoeffdingTree 5 Richtige Falsche Vorhersage(%) Vorhersage(%) Tabelle 3: Ergebnisse mit dem Datensatz Iris Die Tests zeigen, dass der Hoeffding Tree für viel größere Trainingsbeispiele konzipiert ist. Bei so kleinen Datensätzen kann er sich gar nicht zu einem guten Klassifikator entwickeln. Aber man kann doch schon erkennen, dass mit steigender Anzahl der Trainingsbeispiele auch die Genauigkeit des Klassifikators wächst. 4.2.5 Mögliche Ressourcenoptimierung Optimierungen die noch in den Hoeffding Tree eingebaut werden können umfassen Pruningtechniken oder eine dynamische Speicheranpassung des Baumes. Da der Baum bis jetzt keine Möglichkeit hat ineffiziente Teilbäume rauszuschmeißen, könnte man darüber nachdenken über Postpruning den Baum sinnvoll zu verkleinern. Pruning zieht aber immer eine ungenauere Klassifizierung nach sich. Die meisten Ressourcen vernichtet der Speichercube der pro Blatt erzeugt wird. Abhängig von der Größe des Baumes und der Tupelattributwerte wird hier Speicher belegt bis zum Cash Overflow. Daher könnte man um Platz zu sparen, an der Achse der Attributwerte Attributbereiche zusammenfassen. Je nach Einsparbedarf muss die Größe der Bereiche gewählt werden. Eine weitere Möglichkeit ist es den Datencube mit der diskreten Menge an Attributen zu koppeln. Diese diskrete Menge enthält nur die Attribute die noch als Aufteilungsattribute zur Verfügung stehen. Daher nimmt sie auch kontinuierlich ab, je tiefer man im Baum kommt. Der Vorteil dabei ist: Der Datencube braucht nur die Attribute zu erfassen die noch für die Aufteilung eines Blattes relevant sind. Das heißt je tiefer ein Blatt im Baum angesiedelt ist umso kleiner währe auch sein Datencube. Alexander Hoffmann Studienarbeit - 24 - 5 Zusammenfassung In dieser Studienarbeit wurde ein baumbasierter Klassifikator der auf Datenströmen arbeitet implementiert. Benutzt wurde hierzu der Hoeffding Tree Algorithmus. Eine geeignete Vorverarbeitung der Daten wird vorausgesetzt. • Funktionalität Der Algorithmus ist in der Lage aus einem Datenstrom einen Entscheidungsbaum aufzubauen. Die Anwendung des Algorithmus findet in Echtzeit statt. Die Generierung des Baumes erfolgt unter Einbeziehung der Entropie und des Informationsgewinnes. Deformierte oder korruptierte Tupel beeinträchtigen die Funktionalität des Algorithmus nicht. Die Funktionalität konnte in Tests gezeigt werden. • Einschränkungen Der Algorithmus läuft nur auf nichtlinguistischen Tupeln. Aufgrund des riesigen Ressourcenverschleißes des Datencubes kann der Algorithmus noch nicht auf großen Beispielen getestet werden. Eine dynamische Anpassung des Baumes zur Laufzeit ist nicht möglich. • Erweiterbarkeit Bezüglich der Speicherung des Baumes und des Wissens im Baum, sollte der bestehende Algorithmus noch erweitert werden. In Zusammenhang mit der Einsetzbarkeit des Algorithmus, kann durch eine Vorverarbeitung des Datenstromes, der Algorithmus auf Datenströmen aller Art angewandt werden. Durch Lösen der angesprochenen Probleme kann man einen exzellenten Klassifikator erhalten, der Anwendung im Bereich des Online-Mining findet. Alexander Hoffmann Studienarbeit - 25 - 6 Literaturverzeichnis [1] Lee, W.; Stolfo, S.J.; Data Mining Approaches for Intrusion Detection, Columbia University, New York Bloedorn, E.; Christiansen, A.D.; Hill, W.; Skorupka, C.; Talbot, L.M.; Tivel, J.; Data Mining for Network Intrusion Detection: How to Get Started; The MITRE Corporation Lüdorf, St.; Verblockendes Angebot – IDS/IPS: Von der Angriffserkennung zur Abwehr; Report der iX, heise Verlag, August 2004 Chen, Y.; Dong, G.; Han, J.; Pei, J.; Wah, B.W.; Wang, J.; Online Analytical Processing Stream Data: Is It Feasible?; In Proc. of the 2002 ACM DMKD June 2002 Dobra, A.; Garofalakis, M.; Gehrke, J.; Rastogi, R.; Processing Complex Aggregate Queries over Data Streams; In Proc. of the 2002 ACM SIGMOD, June 2002 Guha, S.; Mishra, N.; Motwani, R.; O’Callaghan; Clustering Data Streams; Stanford University, CA Domingos, P.; Hulten, G.; Mining High-Speed Data Streams; In Proc. Of the Department of Computer Science & Engineering, University of Washington, 2001 Cammert, M.; Heinz, Ch.; Krämer, J.; Seeger, B.; Anfrageverarbeitung auf Datenströmen; Technischer Report, Fakultät für Mathematik und Informatik, Universität Marburg Cammert, M.; Heinz, Ch.; Krämer, J.; Markowetz, A.; Seeger, B.; PIPES: A Multi-Threaded Publish-Subscribe Architecture for Continuous Queries over Streaming Data Sources; Technical Report, No. 32, Department of Mathematics and Computer Science, Univerität of Marburg, July 2003 Han, Jiawei; Data mining concepts and techniques; Academic Press, 2001 Witten I.H.; Frank, E.; Data Mining – Praktische Werkzeuge und Techniken für das maschinelle Lernen; 388 Seiten, Carl Hanser Verlag, 2001 [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] Links • XXL und PIPES (http://www.xxl-library.de) • Weka 3 (http://www.cs.waikato.ac.nz/ml/weka/) • JAVA API Spezifikationen (http://java.sun.com/j2se/1.4.2/docs/api/) Alexander Hoffmann Studienarbeit