Tensorflow - KI im Einsatz für das Pharma Marketing

von Andreas Scheidmeir

In einem aktuellen Projekt für einen unserer Pharma-Kunden muss ein DAM-System mit kategorisierten Bild-Assets gefüllt werden. Dabei handelt es sich um Packungs-Bilder der einzelnen Präparate, die aus verschiedenen Perspektiven aufgenommen wurden: die beiden anonymisierten Packungs-Bilder unten stellen den Fall links oder rechts dar.

 

Die Bilder sind bisher komplett von Hand klassifiziert. Man kann sich leicht vorstellen wie monoton dieser Vorgang bei tausenden von Bildern auf Dauer ist und dass sich dabei gerne Fehler einschleichen können. Dank aktueller Bilderkennung sollte sich das aber automatisieren lassen, um zumindest eine Qualitätssicherung durchführen zu können.

Mit Tensorflow ist das Training eines solchen Klassifikators ein Leichtes, sofern man in der Lage ist einen repräsentativen Trainingsdatensatz (siehe unten) bereitzustellen.

Voraussetzung hierzu ist, dass Python, Pip und Tensorflow auf dem Rechner installiert sind (https://www.tensorflow.org/install/pip). Eine gute Einführung ist Googles CodeLabs Tutorial, bei dem das Netz auf 5 verschiedene Blumenarten trainiert wird. Um genau zu sein wird kein neues Neuronales Netz trainiert sondern einer der auf Tensorflow Hub bereitgestellten Klassifikatoren neu trainiert, aber eins nach dem anderen.

 

Schritt 1: Kategorisierung

Die Trainingsdaten müssen je Kategorie in einen Unterordner aufgegliedert werden und im JPEG-Format vorliegen. Die Formateinschränkung gilt nur für das Training, bei der anschließenden Klassifikation neuer Daten können auch PNG/GIFs vorliegen. Pro Kategorie sollten mindestens 100 unterschiedliche Exemplare gewählt werden, je mehr desto besser. Bei der Packungs-Klassifikation wurden rund 400 Bilder pro Kategorie verwendet.

Das in Schritt 2 verwendete Trainigns-Script teilt die Daten automatisch in Trainings-, Validierungs- und Testdaten (zur Bestimmung der Erkennungsrate) auf, sodass wir uns hierzu keine Gedanken machen müssen.

Beispiel der Ordnerstruktur:
Trainingsdaten/
    |—Kategorie1/
    |—Kategorie2/
     …

Das Erstellen eines umfangreichen und repräsentativen Trainingssets ist aufwendig und dieser Schritt nimmt mit Abstand die meiste Zeit ein. Dennoch lohnt es sich, dann hiermit steht und fällt die Genauigkeit und Verwendbarkeit des Klassifikators.

 

Exkurs: Repräsentative Trainignsdaten

Die Bilder müssen möglichst genau den zu erwartenden Daten entsprechen, um ein akzeptables Ergebnis unter realen Bedingungen zu erwarten. Wenn zum Beispiel Bilder von Objekten im Außenbereich klassifiziert werden sollen ist es keine gute Idee die Trainingsbilder im Innenbereich vor einer weißen Wand zu erzeugen. 

Dies ist zugegeben ein recht offensichtliches Beispiel aber auch kleinere Variationen müssen beachtet werden. In unserem Fall können die Packungsbilder verschiedene Ausmaße annehmen (schmal und hoch vs. flach und breit) und einmal mit Schlagschatten oder ohne auftreten. Sind nun in der Kategorie „Links“ hauptsächlich hohe Packungen mit Schlagschatten, in „Rechts“ hingegen breite ohne Schatten so ist es wahrscheinlich, dass der Klassifikator nicht auf die gewünschten Merkmale trainiert wird. Solche Variationen sind gut, aber müssen in allen Kategorien in angemessener Anzahl vertreten sein.

Falls die Trainingsbilder vorsortiert bereitgestellt werden lohnt es sich in der Regel auch, die Kategorisierung noch einmal kritisch zu überprüfen. Falsche einsortierte Exemplare können das Ergebnis stark verschlechtern.

 

Schritt 2: (Re)Training

Sobald die Trainingsdaten vorliegen kann man die Arbeit dem Rechner überlassen. Hierzu nutzen wir das retrain.py-Script aus dem Tensorflow Repository: https://github.com/tensorflow/hub/raw/master/examples/image_retraining/retrain.py

python retrain.py \
    --image_dir pfad/zu/trainingsbildern \
    --tfhub_module https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/feature_vector/2

Mit dem tfhub_modul Flag kann spezifiziert werden, auf welchem Netz unser Klassifikator aufbauen soll. Eine Übersicht findet sich unter https://tfhub.dev/s?module-type=image-classification. Die Vorgaben unterscheiden sich in Komplexität und Größe und sollten je nach Anwendungsfall gewählt werden. Die MobileNet Klassifikatoren sind recht schlank und performant, liefern aber vor allem bei komplexeren Kategorien schlechtere Erkennungsraten. NAS-/PNASNet liegen am anderen Ende der Skala aber die Klassifikation mit diesen großen Netzen braucht entsprechend länger. 

Für einen konkreten Anwendungsfall sollten verschiedene Netze getestet und entsprechend ein Kompromiss zwischen Erkennungsraten und Geschwindigkeit gefunden werden. Bei der Packungs-Klassifikation kommt aktuell das Inception-V3 Netz zum Einsatz, da es bei 95% Erkennungsrate noch ausreichend Performanz bietet.

Je nach Rechnerleistung und Größe des Trainingsdatensatzes kann das Lernen 15-30 Minuten dauern. Nach Abschluss ist der generierte Graph unter /tmp/output_graph.pb und die dazugehörigen Labels in /tmp/output_labels.txt zu finden.

Schritt 3: Klassifikation

Der erzeugte Graph kann jetzt zur Klassifikation herangezogen werden. Dafür gibt es ein weiteres Tensorflow-Script unter https://github.com/tensorflow/tensorflow/raw/master/tensorflow/examples/label_image/label_image.py. Als Ausgabe erhält man eine Liste aller Kategorien samt Konfidenz der Zugehörigkeit als Gleitkommazahl zwischen 1 und 0.

python label_image.py \
--graph=./pfad/zu/output_graph.pb --labels=./pfad/zu/output_labels.txt \
--input_layer=Placeholder \
--output_layer=final_result \
--input_height=299 --input_width=299 \
--image=./pfad/zum/bild.png

Die Flags input_height und input_width variieren mit dem verwendeten Graphen und können der Tensorflow-Hub Seite entnommen werden.

Im Grund ist damit alles fertig. Um aber nicht jedes Bild einzeln zu kategorisieren wurde das Skript noch erweitert. 

Erweiterungen

Um die Qualitätssicherung zu vereinfachen wurde das label_image.py Skript um folgende Punkte erweitert:

  • Statt einem einzelnen Bild iteritert das Skript über alle in einem gegebenen Ordner
  • Diese Schleife ist parallelisiert
  • auch PSD-Dateien können klassifiziert werden
  • die Klasse wird an den Dateinahmen angehängt
  • und bei einer Konfidenz kleiner 0.85 werden Bilder in einen gesonderten Ordner geschoben

Die Parallelisierung ist mittels JobLib realisiert. Diese Python Bibliothek ermöglicht sehr einfach die Auslagerung auf mehrere Kerne.

num_cores = multiprocessing.cpu_count()
Parallel(n_jobs=num_cores)(delayed(imagecategorizer)(filename, file_path) for filename in os.listdir(file_path))

Bei Photoshop Dateien kommt Wand zum Einsatz. Die Bibliothek ermöglich diverse Operationen auf Bilddateien wie z.B. Konvertierung in andere Formate. Hiermit kann ein Stellvertreterbild als PNG oder JPEG erzeugt werden, welches dann für die eigentliche Klassifizierung zum Einsatz kommt und danach wieder verworfen wird.

if (filename.endswith(".psd")):
    with Image(filename=file_path+filename+"[0]") as original:
        with original.convert('jpeg') as converted:
            converted.transform(resize='1280x1280>')
            converted.save(filename=file_path + filename + "converted.jpg")
            pass
    leftright = classify(file_path + filename + "converted.jpg", "left_right")

Fazit

Sobald man seine Trainingsdaten zusammen hat, ist es dank Tensorflow erstaunlich einfach und schnell möglich, einen guten Bildklassifikator zu erzeugen. Die Erkennungsrate von 95% konnten wir ins unserem Fall beim Testen mit neuen Daten bestätigen, was schon erstaunlich nah an die Leistung eines Menschen heran kommt. Als automatisierte Qualitätssicherung für die Verschlagwortung von Bild-Assets ist das System demnach gut zu gebrauchen. Ob man sich komplett auf die künstliche Intelligenz verlassen will muss aber je nach Anwendungsfall entschieden werden.

Zurück