© S&SMedia/Bianca Röder
Schließt Tribuo den Feature-Gap zwischen Python und Java?

Auf pythonischen Spuren


Nicht zuletzt ob der breiten Verfügbarkeit von Bibliotheken hat sich Python im Laufe der letzten Jahre als Quasistandard im Bereich Machine Learning etabliert. Logisch, dass man bei Oracle diesem Trend nicht wirklich gern zusah – schließlich und endlich muss Java ja große Verbreitung haben, möchte man am Produkt ernsthaft Geld verdienen. Vor einiger Zeit stellte Oracle deshalb die hauseigene Bibliothek Tribuo unter eine quelloffene Lizenz.

Im Prinzip handelt es sich bei Tribuo um ein ML-System, das den Feature-Gap zwischen Python und Java im Bereich der künstlichen Intelligenz zumindest bis zu einem gewissen Grad schließen helfen soll.

Das unter die (sehr liberale) Apache-Lizenz gestellte Produkt kann laut der Ankündigung auf eine mehrjährige Anwendungsgeschichte innerhalb Oracles zurückblicken. Man erkennt das unter anderem daran, dass die Bibliothek sehr umfangreiche Funktionen anbietet – neben der Erzeugung „eigener“ Modelle gibt es auch Interfaces für verschiedene andere Bibliotheken, darunter auch TensorFlow.

Autor und Redaktion ist klar, dass man Machine Learning nicht in einem Artikel eines Fachmagazins unterbringen kann. Schon ob der Wichtigkeit dieser Vorstellung wollen wir Ihnen allerdings ein wenig zeigen, wie man mit Tribuo herumspielen kann.

Modulare Bibliotheksstruktur

Machine-Learning-Anwendungen zählen normalerweise nicht zu den Aufgabenstellungen, die man auf ressourcenbeschränkten Systemen ausführt – IoT-Edge-Systeme, die ML Payloads ausführen, haben meist einen Hardwarebeschleuniger, wie beispielsweise den SiPeed MAiX. Trotzdem wird die Tribuo-Bibliothek von Oracle modularisiert angeboten, weshalb man als Entwickler in der Theorie nur jene Teile des Projekts in seine Solutions einbinden kann, die man auch wirklich benötigt. Unter [1] findet sich eine Übersicht, welche Funktionen in den einzelnen Paketen bereitgestellt werden.

Wir wollen uns in diesem Einführungsartikel allerdings nicht weiter mit Modularisierung auseinandersetzen, sondern stattdessen ein wenig drauflos programmieren. Eine Tribuo-basierte Anwendung der künstlichen Intelligenz weist im Allgemeinen immer die in Abbildung 1 gezeigte Struktur auf.

hanna_tribuo_1.tif_fmt1.jpgAbb. 1: Tribuo versucht, eine Full-Stack-Lösung zur künstlichen Intelligenz zu sein (Bildquelle: Oracle)

Die Abbildung informiert uns darüber, dass Tribuo die Informationen von A bis Z selbst zu verarbeiten sucht. Ganz links steht dabei ein DataSource-Objekt, das die per künstlicher Intelligenz zu verarbeitenden Informationen einsammelt und in das Tribuo-eigene Speicherformat namens Example konvertiert. Diese Example-Objekte werden dann in Form einer Dataset-Instanz vorgehalten, die – im Allgemeinen wie gewohnt – in Richtung eines Modells weiterwandern, das zu guter Letzt Vorhersagen liefert. Eine als Evaluator bezeichnete Klasse kann dann anhand dieser meist recht allgemein bzw. wahrscheinlichkeitsbezogen gehaltenen Informationen konkrete Entscheidungen treffen.

Ein in diesem Zusammenhang interessanter Aspekt des Frameworks ist, dass viele Tribuo-Klassen ein mehr oder weniger generisches System zum Setzen von Konfigurationseinstellungen mitbringen. Im Prinzip wird dabei eine Annotation vor die Attribute gestellt, deren Verhalten angepasst werden kann:

public class LinearSGDTrainer implements Trainer<Label>, WeightedExamples { @Config(description="The classification objective function to use.") private LabelObjective objective = new LogMulticlass();

Das unter [2] im Detail beschriebene Oracle Labs Configuration and Utilities Toolkit (OLCUT) kann diese Informationen dann aus XML-Dateien einlesen – im Fall unseres soeben angelegten Propertys könnte die Parametrierung beispielsweise nach folgendem Schema erfolgen:

<config> <component name="logistic" type="org.tribuo.classification.sgd.linear.LinearSGDTrainer"> <property name="objective" value="log"/>

Sinn dieser auf den ersten Blick akademisch klingenden Vorgehensweise ist, dass das Verhalten von ML-Systemen stark von den in den diversen Elementen enthaltenen Parametern abhängig ist. Durch die Implementierung von OLCUT kann der Entwickler dem User die Möglichkeit geben, diese Einstellungen zu dumpen, oder ein System mit geringem Aufwand in einen definierten Zustand zurückzuversetzen.

Einbindung von Tribuo

Nach diesen einführenden Überlegungen ist es nun an der Zeit, erste Experimente mit Tribuo durchzuführen. Auch wenn der Quellcode der Bibliothek in GitHub zum Selbstkompilieren bereitsteht, empfiehlt sich für erste Gehversuche die Verwendung eines fertigen Pakets.

Oracle unterstützt dabei sowohl Maven als auch Gradle und bietet im Gradle-Sonderfall sogar (teilweise) Unterstützung für Kotlin. Wir wollen in den folgenden Schritten allerdings mit klassischen Werkzeugen arbeiten, weshalb wir uns eine Eclipse-Instanz greifen und diese durch Anklicken von New | New Maven project zum Erzeugen eines neuen, auf Maven basierten Projektskeletts animieren.

Im ersten Schritt des Generators fragt die IDE, ob sie als Archetyp bezeichnete Vorlagen laden wollen. Bitte selektieren Sie die Checkbox Create a simple project (skip archetype selection), um die IDE zum Anlegen eines primitiven Projektskeletts zu animieren. Im nächsten Schritt öffnen wir die Datei pom.xml, um eine Einfügung der Bibliothek nach dem Schema in Listing 1 zu befehligen.

Listing 1

 <name>tribuotest1</name> <dependencies> <dependency> <groupId>org.tribuo</groupId> <artifactId>tribuo-all</artifactId> <version>4.0.1</version> <type>pom</type> </dependency> </dependencies> </project>

Zur Überprüfung der erfolgreichen Einbindung befehligen wir danach eine Rekompilation der Solution – bei bestehender Internetverbindung wird Sie die IDE darüber informieren, dass die benötigten Komponenten aus dem Internet auf Ihre Workstation wandern.

Ob der Nähe zum klassischen ML-Ökosystem dürfte es niemanden verwundern, dass die Tribuo-Beispiele im Großen und Ganzen in Form von Jupiter Notebooks vorliegen – eine insbesondere im Forschungsbereich weitverbreitete Darbietungsform, die für den seriellen Einsatz in der Produktion zumindest nach Meinung des Autors nicht wirklich geeignet ist.

Wir wollen in den folgenden Schritten deshalb auf klassische Java-Programme setzen. Als erstes Problem wollen wir uns dabei der Klassifikation zuwenden. Darunter versteht man in der Welt der ML, dass die angelieferten Informationen in eine Gruppe von als Klasse bezeichneten Kategorien oder Histogramm-Bins eingeordnet werden. Im Bereich des Machine Learnings hat sich eine Gruppe von als Data Set bezeichneten Beispielen (Sample Data Set) etabliert. Dabei handelt es sich um vorgefertigte Datenbanken, die konstant sind und zur Evaluation verschiedener Modellhierarchien und Trainingsstufen herangezogen werden können. In den folgenden Schritten wollen wir auf das unter [3] bereitstehende Iris-Data-Set setzen. Hinter dem Begriff Iris verbirgt sich witzigerweise nicht ein Teil des Auges, sondern eine Pflanzenart.

Freundlicherweise steht das Data Set in einer für Tribuo direkt verwendbaren Form zur Verfügung. Der unter Linux arbeitende Autor öffnet aus diesem Grund im ersten Schritt ein Terminalfenster, in dem er danach ein neues Arbeitsverzeichnis anlegt und die Informationen zu guter Letzt per wget vom Server herunterlädt:

t@T18:~$ mkdir tribuospace t@T18:~$ cd tribuospace/ t@T18:~/tribuospace$ wget https://archive.ics.uci.edu/ml/machine-learning-databases/iris/bezdekIris.data

Als nächsten Akt fügen wir unserem Eclipse-Projektskelett im ersten Schritt eine Klasse hinzu, die eine Main-Methode aufnimmt. Platzieren Sie in Ihr den Code aus Listing 2.

Listing 2

import org.tribuo.classification.Label; import java.nio.file.Paths; public class ClassifyWorker { public static void main(String[] args) { var irisHeaders = new String[]{"sepalLength", "sepalWidth", "petalLength", "petalWidth", "species"}; DataSource<Label> irisData = new CSVLoader<>(new LabelFactory()).loadDataSource(Paths.get("bezdekIris.data"), irisHeaders[4], irisHeaders);

Die auf den ersten Blick einfach erscheinende Routine hat es in mehrerlei Hinsicht faustdick hinter den Ohren. Erstens bekommen wir es hier mit einer Klasse namens Label zu tun – je nach Konfiguration ihrer Eclipse-Arbeitsumgebung wird die IDE vielleicht sogar Dutzende von Label-Kandidatenklassen anbieten. Wichtig ist, dass Sie sich unbedingt für den hier gezeigten Import org.tribuo.classification.Label entscheiden – ein Label ist in Tribuo eine Katalogisierungskategorie.

Die mit var beginnende Syntax ermöglicht der IDE dann das Erreichen einer aktuellen Java-Version – wer Tribuo (effektiv) verwenden möchte, muss zumindest JDK 8, besser aber JDK 10 einsetzen. Die in dieser Version eingeführte var-Syntax findet sich nämlich in so gut wie jedem Codebeispiel.

Aus der Logik folgt, dass Sie – je nach Systemkonfiguration – an dieser Stelle mehr oder weniger umfangreiche Anpassungen durchführen müssen. Der unter Ubuntu 18.04 arbeitende Autor musste beispielsweise erst ein kompatibles JDK bereitstellen:

tamhan@TAMHAN18:~/tribuospace$ sudo apt-get install openjdk-11-jdk

Beachten Sie, dass Eclipse den neuen Installationspfad mitunter nicht selbsttätig erreichen kann – im vom Autor verwendeten Paket lautete das korrekte Verzeichnis /usr/lib/jvm/java-11-openjdk-amd64/bin/java.

Nach der erfolgreichen Anpassung der Java-Ausführungskonfiguration sind wir jedenfalls in der Lage, unsere Applikation zu kompilieren – eventuell müssen Sie noch das NIO-Paket zur Maven-Konfiguration hinzufügen, weil die Tribuo-Bibliothek im Interesse besserer Performance quer durch den Gemüsegarten auf diese neuar...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang