blog

Wer klatscht für wen im Bundestag?

Seit dieser Wahlperiode können die Plenarsitzungen des Bundestages als strukturierte Daten im XML-Format heruntergeladen werden. Dieser Umstand hat mich neugierig gemacht und ich wollte schauen welche interessanten Informationen aus diesen Daten erschlossen werden können. Ich habe einige Bundestagsdebatten gesehen und faszinierend war für mich wer für wen klatscht. Ich fragte mich ob wohl die AfD überhaupt Beifall bekommt und wenn ja von wem. Gibt es Parteien die sich gegenseitig mehr Applaus geben?

In den Daten der Plenarsitzungen sind Kommentare aus dem Publikum erfasst, hierbei wird auch der Beifall mit aufgeschrieben. Es wird unterschieden zwischen der gesamten, einigen Abgeordneten oder eines einzelnen Abgeordneten einer Fraktion. Alle von mir genutzten Daten sind unter http://www.bundestag.de/service/opendata zu finden. Die berücksichtigten Daten sind alle Plenarsitzungen von beginn der Legislaturperiode bis zum 22.3.2018.

Vorbereitung

Um die Daten besser erforschen zu können wurden die Daten in eine Datenbank überführt. Das unten aufgeführte Entity-Relationship-Diagramm wurde von mir eigenst erstellt um die für mich interessanten Aspekte der Sitzungen ablegen zu können.

Datenbank Modell für Plenarsitzungen im Bundestag

Eine Rede hat einen Redner der Mitglied einer Fraktion ist. Die Rede gehört zu einem Tagesordnungspunkt von denen mehrere in einer Sitzung abgehandelt werden. Eine Rede wird in mehrere Absätze untergliedert zwischen denen Reaktionen in Form von Zurufen, Applaus oder Bemerkung des Bundestagspräsidenten oder einem seiner Vertreter auftreten können.
Da bereits eine MySql Datenbank auf meinem System vorhanden war wurde diese benutzt. Von MySql wird ein Python Interface angeboten das ärgerlicherweise seit langer Zeit (2015) nicht mehr überholt wurde. So ist die höchste nutzbare Python Version 3.45 und das Interface lässt sich auch nur hinzufügen wenn der Windows Installer genutzt wurde. Somit war eine einfache Nutzung zusammen mit Anaconda nicht möglich. Zum Glück gibt es andere Packages die ebenfalls in der Lage sind mit MySql zu kommunizieren hierbei möchte ich pymysql hervorheben da die API fast identisch ist und ich den gesamten Programmcode praktisch nicht überarbeiten musste nachdem ich auf dieses Package umgestiegen bin.
Die Daten konnte nun in die von mir erstellten Tabellen überführt werden.

Ergebnisse

Nun zum interessanten Teil dieses Beitrags.

Jede Fraktion klatscht für sich

Die Diagramme zeigen in Blau Applaus von der gesamten Fraktion und in Orange Applaus von einem bis einigen Abgeordneten. Zu sehen ist das jede Fraktion für sich am meisten klatscht, was auch nachvollziehbar ist. Zu erwarten war auch das die AfD von den anderen Fraktionen wenig bis gar keinen Applaus bekommt. Die Stellen an denen Applaus gegeben wurde lassen sich nicht zwangsläufig als Zustimmung interpretieren, so ist es auch möglich das Bemerkungen aus dem Publikum mit Applaus bedacht werden. Bei der weiteren Untersuchung der Daten ist eine weitere Diskriminierung des Beifalls möglicherweise machbar.
Die LINKE klatscht am liebsten für die GRÜNEN und die SPD, bekommt allerdings nicht so viel Beifall zurück. Somit sind beide Fraktionen am rechten und linken Ende des politischen Spektrums Außenseiter. Auch merkwürdig ist, dass die GRÜNEN wenn sie Beifall geben fast ausschließlich gemeinsam applaudieren.
Interessanterweise bekommen CDU/CSU am meisten Beifall von sich und anderen Fraktionen. Dies lässt sich nicht unmittelbar damit erklären das hier die meisten Sitze vergeben wurden. Jede andere Fraktion könnte ebenso viel für die eigenen Abgeordneten klatschen nur tun sie dies nicht. Die FDP scheint sich noch immer als Bruder im Geiste mit der CDU/CSU zu verstehen, von ihr bekommt die CDU/CSU am meisten Applaus.

Die meist applaudierten Reden

Die 6 Reden mit dem meisten Applaus wurden herausgefiltert und genauer betrachtet. Unter den sechs Reden sind zwei von Frauen und 4 von Männern. Bei 4 dieser Reden handelt es sich um Anträge der AfD. In jeder dieser Reden wird die AfD thematisiert, in den 4 Reden zu den Anträgen der AfD ist dies quasi notwendig da über diesen Antrag diskutiert wird. In den anderen beiden Reden über Antisemitismus und Rechtsextremismus, ohne Antrag der AfD, wird diese allerdings häufiger als Negativbeispiel erwähnt.
Jedes Thema mit der Ausnahme von vielleicht „Deutsch als Landessprache“ ist ein brisantes, bei dem eine emotionale Debatte vorstellbar ist. Die Rede von Herrn Saathoff, zum Thema „Deutsch als Landessprache“ wurde auf Plattdeutsch gehalten dies mag zu dem vermehrten Beifall aber auch womöglich zum geringerem Verständnis beigetragen haben.
Wie auch schon in Summe für alle Reden applaudiert hier immer die gesamte Fraktion für den eigenen Redner, mit einer kleinen Ausnahme für Nadine Schön die von ihrer Fraktion nicht die ganzen 100% Beifall bekommen hat. Herausragen tun außerdem die Reden von Özdemir und von Notz die beide sehr laut und aggressiv in Richtung AfD gerichtet wurden.

79 mal Beifall für Kerstin Griese(CDU/CSU) am 18.1.2018 Thema: Antisemitismus

71 mal Beifall für Cem Özdemir(GRÜNE) am 22.2.2018 Thema: Deniz Yücel

61 mal Beifall für Konstantin von Notz(GRÜNE) am 23.2.2018 Thema: Rechtsextremismus

64 mal Beifall für Nadine Schön(CDU/CSU) am 18.1.2018 Thema: Gleichberechtigung Frauen

57 mal Beifall für Alexander Throm(CDU/CSU) am 22.2.2018 Thema: Denis Yücel

58 mal Beifall für Johann Saathoff(SPD) am 2.3.2018 Thema: Deutsch als Landessprache

Fazit

Die Daten der Bundestagssitzungen sind durch das strukturierte Datenformat nun sehr gut statistisch auszuwerten. Der Einsatz einer relationalen Datenbank war für diesen Anwendungsfall zweckmäßig und funktionierte Reibungslos. Die Verbindung mit Python war einfach und Resultate auf Anfragen aus der Datenbank konnten bequem und schnell weiterverarbeitet werden.
Die Ergebnisse sind nachvollziehbar, es hat wenige Überraschungen gegeben. Das LINKE und AfD beide von den anderen Fraktionen weniger mit Beifall bedacht werden haben sich wahrscheinlich viele gedacht. Das Rezept für gute Reden scheint zum einen das Thema zu sein und zum anderen ist es auch hilfreich gegen die AfD zu wettern.
Es steht vielleicht aus das auch ältere Daten in das neue Format überführt werden, in diesem Fall würden wesentlich mehr Daten zur Verfügung stehen und eine chronologische Analyse wäre denkbar. Die Daten die bisher zur Verfügung stehen sind durchaus auch noch auf anderem Wege zu erschließen. Beispielsweise kann ich mir vorstellen das Abgeordnete mit einem Direktmandat weniger Beifall bekommen als Abgeordnete mit einem Listenplatz. Um dies zu belegen müsste man allerdings die Daten über die Platzvergabe noch einfließen lassen. Außerdem wäre es auch interessant zu schauen was gesagt wurde hier könnte man sentiment analysis machen und so auch Reden bewerten. Eine weitere spannende Idee wäre, per markov-chain einen Reden-Generator zu erstellen der dann für jede Fraktion mehr oder minder sinnvolle Reden produziert.
Die Aussichten sind also vielfältig und ich kann mir gut vorstellen mit den Daten weiter zu arbeiten, da der Kraftakt der Übertragung in eine Datenbank bereits geleistet ist. Die weitere Integration von neuen Daten kann also auf Knopfdruck geschehen und die Zeit kann intensiv mit der Analyse und Visualisierung der Daten verbracht werden.

Analyse des 3DMM Basel Face Model

Die Lerndaten für mein Master-Thema wurden mit Hilfe des 3DMM von Paysan et al. erstellt. Im Rahmen meines Hauptprojektes habe ich mir das Modell genauer angeschaut und möchte meine Erkenntnisse nun hier teilen.

Principal Component Analysis und Trennung in Farbe und Form

Das genutzt 3DMM hat 398 Parameter, wovon jeweils die Hälfte für die Form und die Textur genutzt werden. Diese Parameter wurden mittels Principal Component Analysis extrahiert. Die PCA ermöglicht die Darstellung eines multidimensionalen Sachverhaltes reduziert auf eine beliebige Anzahl von Dimensionen, wobei der Informationsgehalt trotz der Reduzierung der Dimensionalität möglichst hoch gehalten wird. Die 199 Parameter für die Form zeigen quasi Prototypen von Gesichtern die sich in den gescannten Modellen wiederfinden konnten. Hierbei sind die Parameter hierarchisch nach Intensität der Ausprägung sortiert, das bedeutet, dass der erste Parameter eine stärkere Ausprägung hat als alle folgenden Parameter. Ausprägung bedeutet in diesem Kontext eine Veränderung des generischen Modells mit allen Werten auf 0, im Hinblick auf die räumliche Verschiebung von Polygonen für die Form und farblicher Unterschied zum generischen Modell für die Textur. Der letzte Parameter hat im Vergleich zum ersten kaum noch Auswirkung auf das 3D-Modell. Zur Veranschaulichung dieses Sachverhaltes ist in der Abbildung 1 für Form (α) und Textur (β) jeweils der erste Werte von -5 bis +5 aufgetragen. Hier lässt sich erkennen, dass der erste Parameter für die Form im negativen Bereich sehr weiblich aussieht und im positiven Bereich sehr männlich. Für die Textur ist der erste Parameter im negativen Bereich sehr hell und für den positiven Bereich dunkel. Diese Beobachtung ist intuitiv nachvollziehbar, da Menschen sich einerseits gut anhand von Geschlechtsmerkmalen und andererseits anhand heller oder dunkler Hautfarbe unterscheiden lassen.

Permutationen der beiden ersten Parameter von Alpha und Beta von -5 std bis +5std
Abbildung 1: Permutationen der beiden ersten Parameter von Alpha und Beta von -5 std bis +5std

Eindeutigkeit

Die folgenden Parameter für die Form sind nicht alle wie der erste weiblich oder männlich sondern können auch für positive und negative Werte nur männlich oder nur weiblich aussehen. Häufig sind einzelne Ausprägungen wie fliehendes Kinn ⇒ großes Kinn oder dünn ⇒ dick zu erkennen. Wobei diese Eigenschaften nie in Reinform auftreten sondern immer mit anderen Merkmalen vermischt sind. Parameter können sich in Bezug auf ein Merkmal gegenseitig beeinflussen, was bedeutet, dass die Eindeutigkeit von 3D-Modell und Parametervektors nur in eine Richtung gewährleistet ist. Es existiert keine Umkehrfunktion um einen Parametervektor für ein gegebenes 3D-Modell zu ermitteln.
Eine Variation von Parametern, die sich weit unten in der Hierarchie befinden, hat zudem kaum Auswirkung auf das Aussehen des Modells jedoch auf einen gemessenen Fehler, wenn er als Basis die Distanz zwischen Label und Ausgabewerten berechnet. Dieser Umstand und die Uneindeutigkeit für Bilder, bzw. 3D-Modelle und Parametervektoren, erhöht die Schranke des minimal erreichbaren Fehlers beim Lernen. Mit einem höheren finalen Fehler muss es nicht zwangsweise so sein, dass das Modell schlechte Inferenzen zieht. Jedoch sollte dieser Sachverhalt in der Fehlerfunktion berücksichtigt werden.

Einschränkungen

Das 3DMM hat eine Reihe von Einschränkungen, es können zwar unerschöpflich viele Gesichter dargestellt werden, aber es können definitiv nicht alle Gesichter dargestellt werden. Alle Gesichter haben keine Features wie z.B. Brillen, Bärte, Schmuck oder Haare. Die 200 aufgenommenen Individuen spiegeln keine repräsentative Menge der Weltbevölkerung dar. Die Personen waren wahrscheinlich hauptsächlich Studenten der Universität Basel und repräsentieren also lediglich eine Gruppe von Personen die an dieser Hochschule verkehren. Die meisten Personen sind Mitte 20 und haben Normalgewicht, zudem kann angenommen werden, dass die meisten wahrscheinlich europäischer Herkunft sind. Somit sind wahrscheinlich nicht alle Ethnien und sehr junge und alte Personen ebenfalls nicht enthalten. Diese Beschränkung wird zur Folge haben, dass Inferenzen nicht notwendigerweise für alle Personengruppen passen, soweit sie nicht in der Menge dieser 200 Teilnehmer enthalten sind.

Distribution der Teilnehmer nach Alter und Gewicht von Paysan et al.

Generative Adversarial Networks

Eine neuere Art von Neuronalen Netzen sind die sog. Generative Adversarial Networks (GAN), sie wurdne erstmals 2014 von Goodfellow et al.[1] vorgestellt. Sie gehören zu den unsupervised Learning Methoden und werden bisher zumeist eingesetzt um künstlich neue Bilder von einer beliebigen Klassen zu erstellen. Ein GAN besteht aus zwei Teil-Netzwerken zum einen der Generator G und zum anderene der Diskriminator D. Der Generator erstellt mit einem zufällig generierten Vektor (auch Code genannt) einen Output der vom Diskriminator bewertet wird als authentisch oder generiert. Der Diskriminator hat Zugriff auf die Lerndaten und bewertet den generierten Output zusammen mit den vorhandenen Lerndaten und entscheidet wie echt das jeweilige Bild ist. Die beiden Netzte lernen gegenseitig voneinander und werden jeder für sich immer besser. Der Diskriminator kann besser falsche von richtigen Bildern unterscheiden und der Generator kann besser Bilder generieren die den Lerndaten entsprechen. Ein detaillierterer Einblick in die Technologie gibt es von Goodfellow selbst, in einer Video Präsentation[2].

Das untere Bild illustriert den Aufbau eines Generators, wie erwähnt wird zunächst ein Vektor mit zufälligen Werten initialisiert. Im Anschluss wird der Eingabevektor mittels Deconvolution Layer expandiert.

Beispiele

In der Arbeit von Reed et al.[3] wurden Lerndaten in Form von Bildern und korrespondierenden Bildunterschriften bereitgestellt. Die Bilder sind von Vögeln und die Bildunterschriften beschreiben das Aussehen der Vögel näher. Das Ergebnis ist verblüffend und zeigt welch großes Potential in dieser Technologie steckt.
In einer anderen Arbeit von Wu et al.[4] werden 3D Modelle erstellt von mehreren verschiedenen Klassen

Vögel generiert auf Basis einer Bildbeschriftung von Reed et al.[3]

Vektor-Arithmetrik

Ein GAN kann diverse Ausprägungen der Inputdaten erkennen. So kann ein Netz das auf Gesichter spezialisiert ist z.B. Mann und Frau unterscheiden und weitere Features wie eine Brille. Diese Ausprägungen spiegeln sich in individuellen Werten für den Eingabe-Vektor wieder. Es ist nun möglich Vektro Arithmetrik mit den individuellen Eingangs-Vektoren zu betreiben. In einem Beispiel von Goodfellow[4] wird hier „Mann mit Brille“ – „Mann“ + „Frau“ = „Frau mit Brille“ (siehe Abbildung).

Vektor-Artihmetrik mit GAN’s

Fazit

Ein GAN ist in der Lage zufällige Daten auf einen Input zu liefern. Für die Erstellung von Lerndaten für das Master-Projekt wäre ein GAN rein technisch nutzbar. Allerdings scheint die Methode mit 3DMM’s bessere Modelle zu generieren die realitätsnäher sind. Außerdem fällt die Regression auf Eingabeparameter für das 3DMM weg womit das Netz weniger effizient werden könnte.

Referenzen

[1] Generative Adversarial Nets von Goodfellow, Pouget-Abadie, Mirza, Xu, Warde-Farley, Ozair, Courville & Bengio
[2] Präsentation von Ian Goodfellow über GAN’s
3D morphable Model von Blanz und Vetter, 1999

Eine kleine Geschichte über 3DMM’s und Deep-Learning

Die Erstellung von 3D Modellen auf Basis von einzelnen Bildern ist ein in den letzten Jahren immer populärer werdendes Themengebiet, hilfreich hierbei sind sog. 3DMM’s (3D morphable models). Für die Gesichtserkennung ist es eine enorme Erleichterung ein 3D Modell des Gesichtes zu haben um dies in der Orientierung zu verändern und mit anderen Bildern besser vergleichen zu können. Oder anhand des Modells bessere Schätzungen für Position von Facial Feature Points[1] zu machen, was besonders bei verdeckten Gesichtsteilen oder stark gedrehter Haltung hilfreich ist.
Die Erstellung von Neuralen Netzen zur Lösung des Problems, der Rekonstruktion von 3D Modellen, wurde erst im letzten Jahr eine mögliche Option. Der Weg dorthin wird in diesem Beitrag beschrieben.

Das erste 3DMM

Im Jahr 1999 haben Blanz und Vetter[2] den Grundstein gelegt für die Generierung von lebensechten 3D Repräsentationen von Gesichtern. Diese Arbeit ist auch noch 17 Jahre nach der ersten Veröffentlichung eine der am häufigsten zitierten bei aktuellen Papern in diesem Themengebiet. In der Arbeit wurde ein 3DMM vorgestellt, das anhand von 200 Gesichtern erstellt wurde. Es handelt sich hierbei um 100 Frauen und 100 Männern von denen 3D Modelle erstellt und die Textur abgetragen wurde, die Scans wurden von CyberwareTM bereitgestellt. Die Firma vertrieb Geräte mit denen 3D-Scans von Personen erstellt werden konnten. Das Unternehmen existiert seit 2011 nicht, mehr Informationen gibt es unter cyberware.com . Eine Java-Implementierung des Modells von Blanz und Vetter kann hier heruntergeladen werden. Das Modell ermöglicht es mit mehreren Parametern eine vielzahl von unterschiedlichen realistischen Gesichtern zu erstellen. In dem Modell enthalten ist ein Algorithmus der für ein gegebenes Eingabebild, eines Gesichts, eine Rekonstruktion ausgibt. Diese Rekonstruktion wird über 105 Iterationen optimiert bis das Endergebnis dem Orginal verblüffend ähnlich sieht. Die Berechnung dieser Näherung dauerte damals knapp 50min.

Das 3D morphable model von Blanz und Vetter

Das Basel Face Model

Der erste Ansatz von Blanz und Vetter war gut aber hatte noch einige Nachteile, zum einen mussten die Bilder alle das Gesicht frontal zeigen und zum anderen waren nur gleichmäßig beleuchtete Gesichter gut rekonstruierbar. 10 Jahre nach dem ersten 3DMM hat dann Vetter[3] ein neues Modell erstellt das ohne diese Einschränkungen auf Bilder anwendbar war. Zur Erstellung dieses Modells wurden eigenst Aufnahmen getätigt und es wurden wie bereits im ersten 3DMM 200 Personen (100 weibl. 100 männl.) erfasst. Die Aufnahmen wurden mit dem Gerät ABW-3D getätigt, es entstehen zugleich 3 Bilder aus verschiedenen Posen. Die Auflösung des Gerätes übertrifft die anderer Vorrichtungen um das 3 (Cyberware) bis 8 (3Dmd) fache. Nach eigenen Aussagen sollte dieses Modell nun den Bedarf an Lerndaten für neuronale Netze decken. Das Modell wurde in Matlab entwickelt und steht
hier zur freien Verfügung.

Das verbesserte 3DMM von Vetter 2009

Erste CNN’s für 3D Gesichts Rekonstruktion

Lange passierte nichts auf dem Gebiet bis 2016 von Blanz und Piotraschke[4] eine Methode vorgestellt wurde die das 3DMM zusammen mit riesigen Datensätzen kombinierte um einen synthetischen Datensatz von Lerndaten zu generieren. Die Datensätze bestehen aus Bildern von Personen, wobei für jede Person mehrere Bilder zur Verfügung stehen. Diese Methode hat den Vorteil, dass durch unterschiedliche Fotos der gleichen Person eine gemittelte (bessere) Version der 3D Rekonstruktion möglich wurde.
Nur 3 Monate später veröffentlichte Richards et al.[5] ein CNN das auf einen ähnlich wie Blanz und Piotraschke erstellten Lerndatensatz 3D-Rekonstruktionen erstellte. Diese Technik in Kombination mit einem shape-from-shading Algorithmus war nun in der Lage effizient 3D Modelle zu erschaffen.

CNN von Richards et al. 2016

Im Dezember wurde von Tran et al.[7] eine weitere Arbeit vorgestellt die die Berechnungszeit nun noch um einiges verringerte. So können Parameter für ein 3DMM innerhalb von durchschnittlich 88ms errechnet werden. Das Modell ist nicht nur schnell sondern auch sehr genau, laut den Verfassern ist es das bisher beste Verfahren für Gesichtserkennung das ihnen bekannt ist.

Very Deep Neural Network, Tran, 2016

Ein neues 3DMM basierend auf dem MeIn3D Dataset

Auf der gleichen Konferenz auf der auch Blanz und Piotraschke ihr Paper, über Lerndaten Generierung, vorstellten wurde ein weiterer Beitrag veröffentlicht. In dem Beitrag von Booth et al.[6] wurde ein 3DMM vorgestellt das auf dem MeIn3D Datensatz basierte. Dieser Datensatz wurde bereits im Beitrag Lerndatensätze erwähnt. Der Datensatz beruht auf ca 10.000 Gesichtern die 2012 im Londoner Science Museum von Besuchern aufgenommen wurden. Das Modell ist ab Januar 2017 für medizinische Forschung freigegeben, ob eine breitere Veröffentlichung geplant ist, ist bisher nicht bekannt. Ein großer Vorteil dieses 3DMM ist das wesentlich mehr verschieden Gesichtsausprägungen vorliegen, so sind zum Beispiel alle Ethnien vertreten. In vielen Arbeiten ist der Mangel an Diversifikation häufig ein Grund für fehlerhafte generierte 3D-Modelle.

Fazit

Die Entwicklung von CNN’s für single image 3d face reconstructions hat seit 2016 bereits erste Früchte getragen. Wichtig für die Entwicklung von Deep Neural Networks sind einerseits die 3DMM’s und zum anderen die Algorithmen zum Fitting der Parameter. Die Hürden die bis zu diesem Zeitpunkt unüberwindbar schienen, Lerndaten Knappheit und zu viele Output Knoten, sind augenscheinlich durch 3DMM’s genommen worden. Die Erstellung von Lerndaten mittels 3DMM’s und Schätzung von Parametern als Output Knoten machen die Methode nun schließlich durchführbar.

Die Ergebnisse in den letzten Beiträgen sind erstaunlich und veranschaulichen welches große Potential Deep-Learning, im Bereich Genauigkeit und Schnelligkeit, bietet. Das Thema ist enorm gefragt und wird in den nächsten Monaten, auf Grund der enormen Erfolge, wohl noch mehr Aufwind erfahren. Man kann gespannt sein auf die nächsten Arbeiten in dem Bereich.

Referenzen

[1] Jun 2016, Large-pose Face Alignment via CNN-based Dense 3D Model Fitting, Jourabloo, Liu http://cvlab.cse.msu.edu/pdfs/Jourabloo_Liu_CVPR2016.pdf
[2] 1999, A Morphable Model For The Synthesis Of 3D Faces, Volker Blanz, Thomas Vetter, http://www.cs.cmu.edu/~efros/courses/AP06/Papers/Blanz-siggraph-99.pdf
[3] 2009, A 3D Face Model for Pose and Illumination Invariant Face Recognition, Vetter et al, http://gravis.dmi.unibas.ch/publications/2009/BFModel09.pdf
[4] Jun 2016, Automated 3D Face Reconstruction from Multiple Images Using quality Measures, Blanz, Piotraschke, http://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Piotraschke_Automated_3D_Face_CVPR_2016_paper.pdf
[5] Sep 2016, 3D Face Reconstruction by Learning from Synthetic Data, Richards et al., https://arxiv.org/pdf/1609.04387.pdf
[6] Jun 2016, A 3D Morphable Model learnt from 10,000 faces, Booth et al., http://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Booth_A_3D_Morphable_CVPR_2016_paper.pdf
[7] Dez 2016, Regressing Robust and Discriminative 3D Morphable Models with a very Deep Neural Network, Tran et al., https://arxiv.org/pdf/1612.04904.pdf, Code unter https://github.com/anhttran/3dmm_cnn

Streamlining der Lerndaten-Generierung

In diesem Beitrag möchte ich zeigen wie die Erstellung der Lerndaten für das Deep-Learning Modell effizient durchgeführt werden kann. Anhand der unteren Abbildung werde ich alle Schritte kurz erläutern. Pipeline für Lerndaten Generierung

Virtual-Box

Es wurde sich dafür entschieden zwei weitere Instanzen der Virtuellen Maschiene zu erstellen da der Prozessor, trotz Zuweisung aller Kerne, nicht vollständig ausgelastet wurde. Es handelt sich dabei um eine 2-fach geklonte Virtuelle Maschine die zuvor mit den notwendigen Packages für makehuman ausgestatte wurde. Die drei Instanzen greifen auf die selbe virtuelle Festplatte zu und haben alle Zugriff auf einen gemeinsamen Sharedfolder, in den im weiteren Verlauf die Modelle abgespeichert werden. Die Verbindung mit dem Sharedfolder wird mit folgendem Befehl etabliert.

sudo mount -t vboxsf <Name des Ordners> <Pfad zum Ordner in diesem System>

In jeder Instanz wird anschließend eine modifizierte Variante des makehuman Scripts gestartet. Das Script wurde so verändert, dass ein zufälliger 32 Zeichen langer String als Dateinamen festgelegt wird. Dies war notwendig um eine parallele Ausführung zu ermöglichen und eine einfachere Wiederaufnahme der Generierung zu gewährleisten.

Batch-Script

Nun werden kontinuierlich Modelle im Sharedfolder abgelegt die nach und nach in Lerndaten umgewandelt werden können. Hierzu wird ein einfaches Batch-Script benutzt.

:loop
blender --background --python <Pfad zum Script für die Lerndaten Generierung>
<Pfad zum Powershellscript>/renameoutput.ps1
goto loop

Mit diesem Script wird Blender gestartet und das Script aus dem vorherigen Beitrag wird ausgeführt. Nachdem Blender beendet wurde wird ein Powershellscript gestartet welches die Outputdaten verändert. Die Dateinamen werden von Blender mit ‚0001‘ ergänzt um zu zeigen das dies der erste Frame ist. Diese Namenskonvetion konnte nicht abgeändert werden, mit dem Script werden die Dateinamen um die unnötige Erweiterung gekürzt. Im Anschluss wird Blender erneut gestartet. Das Blender-Script wurde erweitert so, dass alle vorhanden Modelle im Ordner erkannt und in Blender verarbeitet werden können.

Blender

Es gab einige Änderungen im Blender-Script die notwendig waren um einen reibungslosen Ablauf zu gewährleisten. Zunächst musste, da wie erwähnt die Namen der Modelle geändert wurden, der Aufruf der einzelnen Modelle abgeändert werden. Hierzu wurde eine Liste aller Dateien mit der Endung .mhx2 erstellt und durchiteriert. Nachdem eine Datei geladen und zu Lerndaten verabeitet wurde, wird sie verschoben in den Ordner ‚./done‘.

Eine weitere Änderung war notwendig damit Blender nicht immer mehr Arbeitsspeicher einfordert. Da die Modelle anscheinend nicht durch Entfernen in der Szene vollständig gelöscht werden sondern weiter im Arbeitspeicher gehalten werden, wird die Szene nach 500 geladenen Modellen neu geladen. So wird der Arbeitsspeicher geleert und das System kann so lange wie es beliebt laufen.

base_path = 'D:/makehumanModels/'

models = glob.glob(base_path + '*.mhx2')

for x, fp in enumerate(models):

    if (x % 500) == 0:
        bpy.ops.wm.open_mainfile(filepath='D:/Dropbox/Studium/Master Informatik/Master Thema/Grundprojekt/material/empty.blend')
        generateDepthmapNodes()

    else:
        clearScene()

    importModel(fp)
    generateInput(fp)
    generateOutput(fp)
    os.chdir(base_path)
    print('move ' + os.path.basename(fp) + ' '+  base_path + 'done')
    os.system('move ' + os.path.basename(fp) + ' ' + base_path + 'done')

Zusammenfassung

Es wurde gezeigt wie mehrere Instanzen unter VirtualBox genutzt werden können um parallel Modelle zu generieren. Mit einem Batch-Script wird Blender wiederholt aufgerufen um die Modelle weiter zu Lerndaten umzuformen. So entsteht eine Pipeline die einen 4 Kern-Prozessor vollständig auslastet und kontinuierlich Lerndaten generiert.
Mit dieser Konstruktion wird ca. alle 3 Sekunden ein Modell generiert und ungefähr im gleichen Zeitraum zu Lerndaten weiterentwickelt. In einer Nacht (ca. 9 Std) wurden so 12.610 Modelle generiert und weiterverarbeitet. In Zukunft werden die Modelle noch differenzierter erstellt werden und diese Pipeline wird dazu beitragen authentische Modelle in entsprechender Menge zu erzeugen um bessere Ergebnisse für das Deep-Learning Modell zu ermöglichen.

Import von mhx2 Modellen in Blender und Erstellung von Lerndaten

Im vorherigen Beitrag habe ich erläutert wie zufällige Modelle im großen Stil mit Hilfe von MakeHuman erstellt werden können. In diesem Artikel möchte ich kurz zeigen wie Modelle in Blender importiert werden können und anschließend wie mit einem Script Lerndaten für ein Neuronales Netz erstellt werden können.

Import von mhx2 Modellen

Modellimport in Blender
Das importierte Modell aus MakeHuman
Zunächst muß das nötige Plugin für Blender hier herruntergeladen werden. Die Anleitung zur Aktivierung ist sehr anschaulich auf der Seite des Entwicklers des Plugins erklärt. Ein Modell kann nun über File -> Import -> MakeHuman (.mhx2) importiert werden. Das in MakeHuman erstellte Modell wird dann in der Mitte der Szene erscheinen. In Blender kann das Modell dann weiter wie gewünscht bearbeitet werden.

Erstellung von Lerndaten

Um nun Input- und Output-Werte für ein neuronales Netz zu generieren muss zunächst geklärt werden wie die Daten beschaffen sein sollen. Das Ziel ist es möglichst viel Information in möglichst wenig Ausgängen und Eingängen unterzubringen. Ein späterer Artikel wird sich detailliert mit dieser Problematik beschäftigern, der einfachheit halber wird für die ersten Modelle ein Tiefenbild generiert das 1:1 auf ein Eingangs-Bild passt. Beispiele sind in der unteren Galerie aufgeführt.

Die Input- und Output-Daten werden im Bmp-Format abgespeichert dieses ist zwar speicherintensiv aber dafür schneller lesbar. Die Bilder haben eine Auflösung von 64×64 Pixel das heisst für die Anzahl der Eingänge 64 x 64 x 3 = 12288 (Länge x Breite x rot/grün/blau), die Anzahl der Ausgänge wird bei 64 x 64 = 4096 liegen da nur Informationen über die Entfernung der Pixel vorhanden sind.

Scripting in Blender

Die korrespondierenden Bilder wurden mit Hilfe eines Scripts (hier herunterzuladen) erstellt welches für die nicht selbsterklärenden Teile im Detail erläutert wird.

def f(x):
    return (e**-((x-0.5)*1.6))/8+1/8

Zunächst wurde eine Funktion definiert die die Kopfgröße im Verhältnis zur Körpergröße approximiert. Diese Funktion wird benötigt um die richtige Position für die Kamera zu finden die das Bild schießen wird. Diese Exponentialfunktion hat sich nach mehrfachee Anpassungen als praktikable erwiesen.

Das Verhältnis der Größes des Kopfes zur gesamten Körpergröße
Position der Kamera

Die genauere Berechnung der Kameraposition is anhand der Illustration in rot genauer aufgeschlüsselt. Mit h = Größe des Modells, Zk = Höhe der Kamera, α = Kamerawinkel, a = Kopfgröße/2 und Yk der Abstand der Kamera. Der Kamerawinkel wurde berechnet über die Entfernung, bei der halben Höhe des Modells, die notwendig ist damit ein Modell vollständig von der Kamera aufgenommen werden kann. Bei einem 1,6m großem Modell musste die Kamera 3,2m entfernt sein. So ergibt sich α zu:

\alpha=atan\bigg(\frac{0.8}{3.2}\bigg)=14^{\circ}

Die weiteren Parameter wurden errechnet zu:

a=\frac{f(h)}{2}\cdot h
Z_k=h-\frac{f(h)}{2}\cdot h = h - a
Y_k=\frac{a}{tan(\alpha)}

def importModel(filename):
    bpy.ops.import_scene.makehuman_mhx2(filepath='D:/makehumanModels/' + filename + '.mhx2')

    body = bpy.data.objects[filename + ':Body']
    eyes = bpy.data.objects[filename + ':High-poly']

    body.scale = Vector((0.1,0.1,0.1)) # Körper richtig skallieren
    eyes.scale = Vector((0.1,0.1,0.1)) # Augen richtig skallieren

    h = body.dimensions[2] # Größe abtragen (Z-Koordinate)
    a = f(h) * h /2 # Kopfgröße/2

    alpha = 14 * pi / 180 # Kamerawinkel in rad

    z_cam = h - a  # Kamerahöhe
    y_cam = - a / tan(alpha)


    setCam(y_cam,z_cam)

    light = bpy.data.objects['Lamp']
    light.location = Vector((0,-1,1.5))
    light.rotation_euler = Euler((pi/2,0,0))

Mit der Methode importModel() wird das Modell in die Szene geladen. Es werden außerdem mit setCam() die Orientierung und Position der Kamera eingestellt damit ein gutes Bild vom Kopf des Modells geschossen werden kann.

def generateDepthmapNodes():
    
    if not bpy.context.scene.use_nodes:
        bpy.context.scene.use_nodes = True
        
    nodesField = bpy.context.scene.node_tree
    for currentNode in nodesField.nodes:
        nodesField.nodes.remove(currentNode)
        
    renderNode = nodesField.nodes.new(type = 'CompositorNodeRLayers')
    renderNode.location = (0, 0)
    compositeNode = nodesField.nodes.new(type = 'CompositorNodeComposite')
    compositeNode.location = (200, 0)
    nodesField.links.new(renderNode.outputs['Image'], compositeNode.inputs['Image'])
    normalizeNode = nodesField.nodes.new(type = 'CompositorNodeNormalize')
    normalizeNode.location = (200, -200)
    nodesField.links.new(renderNode.outputs['Z'], normalizeNode.inputs[0])
    outputNode = nodesField.nodes.new(type = 'CompositorNodeOutputFile')
    outputNode.name = 'FileOutput'
    outputNode.location = (400, -100)
    nodesField.links.new(normalizeNode.outputs[0], outputNode.inputs['Image'])
    outputNode.base_path = 'D:\\makehumanModels\\output\\'
    outputNode.file_slots[0].format.file_format = 'BMP'

Diese Methode wird einmalig aufgerufen und erstellt im Node-Editor die notwendigen Knoten und Verbindungen um aus den Bilddaten des Rendings das Tiefenbild zu erstellen. Die Z-Buffer Werte werden zusaätzlich noch normalisiert um eine höhere Auflösung zu bekommen.

Nodes-Pipeline für die Erstellung der Output-Daten

Die Methoden generateInput() und generateOutput() nehmen einige Einstellungen vor und erstellen dann das jeweilige Bild. Der gesamte Programmablauf ist dann wie folgt:

generateDepthmapNodes()  
 
for x in range(10):
    
    filename = 'Model_'+ str(x)
    clearScene()
    importModel(filename)
    generateInput(filename)
    generateOutput(filename)

Erstellung von Modellen mit Hilfe von MakeHuman

Die Bedienoberfläche von makehuman

Ich habe von meinem betreuenden Professor den Vorschlag bekommen zunächst eigene Modelle zu erstellen und mein Vorgehen für das Grundprojekt zu dokumentieren. Auf der Suche nach Programmen die mir hilfreich sein können bin ich über makehuman.org gestolpert. Dieses Programm wird seit 2001 entwickelt, ist Open-Source und in Python 2.7 geschrieben.
Da ich seit einiger Zeit selbst verstärkt mit Python arbeite war mein initiales Interesse sehr groß. Ich schaute mir das Programm an und stellte fest das kein direkter Zugriff auf die API durch die Programmierer angedacht ist. Allerdings gab es eine Commandline-Variante (makehuman-commandline) die ein Scripting-Interface bereitstellt. Mit der Option Scripte auszuführen ist eine beliebige Anzahl zufälliger Modelle problemlos zu erstellen.

Einrichtung der Umgebung

Da meine Versuche die Commandline-Variante unter Windows 10 zu installieren leider fehl schlugen entschied ich mich das Programm in einer Virtuellen-Maschiene unter Ubuntu 16.04 zu installieren. Die notwendigen Pakete die nicht unter pip installiert werden konnten sind unten aufgeführt.

apt-get install python-pip python-dev build-essential python-qt4-gl python-sip python-qt4
apt-get install libglu1-mesa-dev freeglut3-dev mesa-common-dev

Alle weiteren notwendigen Module können mit pip installiert werden.
Nachdem ich nun fertig war mit der Installation musste ich leider feststellen das nur wenige Features von MakeHuman in der Scriptingumgebung ausführbar waren. So war es zum Beispiel nicht möglich mit einem Befehl ein zufälliges Modell zu erstellen oder ein Modell zu exportieren.

Entscheidung über das Export-Format

Es gab 5 verschiedene Formate für den Export von Modellen. Das populärste ist mhx2, mit dem laut dem Forum von makehumancommunity.org ein guter Import zu Blender möglich sei. Es wurden alle Formate für das gleiche Modell zum Vergleich in Blender importiert.

Alle exportierten Formate im Überblick (v.L.n.R. .dae, .fxb, .obj, .mxh2, .slt)
Alle exportierten Formate im Überblick (v.L.n.R. .dae, .fxb, .obj, .slt, .mxh2)

Es ist zu erkennen das die Ergebnisse sehr unterschiedlich sind. Der Export per .stl ist unvollständig, ohne Textur und sehr grob. Die besten Ergebnisse werden mit dem mhx2-Format und dae-Format erlangt. Im Vergleich schneidet das mhx2-Format jedoch noch besser ab, wie in den Bildern unten zu erkennen ist. Da die erstellten Modelle zufällige Attribute haben kann ein männlicher Kopf auf einem weiblichen anmutenden Körper sein. Da lediglich der Kopfbereich interessant ist für das Projekt ist es nicht problematisch, dass die Gesichter nicht zu den Körpern passen. Die erste Generation von zufälligen Modellen hat bisher keine Haare oder andere Features wie Brille, Schnurbart o.Ä., ebenso sind die Texturen zunächst auch zufällig gewählt und so kann ein Modell welches den Parameter ‚cacasian‘ auf 1 hat und ‚asian‘ und ‚african‘ auf 0 eine Textur erhalten die zu einer dunkelhäutigen Person gehört. Wenn diese Modelle zur Erstellung von Lerndaten genutzt werden ist die Übertragbarkeit des entstehenden Modells auf echte Bilder natürlich weniger gegeben. Ebenfalls gilt dies für das Alter einer Person und die Textur, wenn später noch Haare und andere Features hinzugefügt werden muss hier auch darauf geachtet werden, dass diese stimmig sind.

Erweiterung des Programmcodes

Um mehr Freiheiten zu gewinnen wurde der Programmcode genauer angeschaut. Es existiert ein Plugin das zufällige Modelle generieren kann, der notwendigen Programmcode wurde in die Scripting-Umgebung hinzugefügt. So war es nun möglich belibig viele zufällige Modell in einer Schleife zu erstellen.
Der Export von Modellen gestaltete sich komplexer. Jegliche Export-Formate wurden über ein Gui-Element in das Programm integriert. So musste das Gui-Element verändert werden um Zugriff auf die Export-Funktionalität zu gewinnen. Eine neue Methode wurde definiert die aus der Scripting-Umgebung aufgerufen werden kann. Die abgeänderten Dateien (/makehuman/plugins/7_scripting.py, /makehuman/apps/gui/guiexport.py) können Sie sich gerne hier herrunterladen.

Das Script sieht dann wie folgt aus:

import random
from core import G
app = G.app
human = app.selectedHuman

skins = ['default.mhmat','middleage_caucasian_female/middleage_caucasian_female.mhmat','old_caucasian_female/old_caucasian_female.mhmat','young_asian_male/young_asian_male.mhmat','middleage_caucasian_male/middleage_caucasian_male.mhmat','old_caucasian_male/old_caucasian_male.mhmat','Harvey_DevilhornsfemaleV1.mhmat','young_caucasian_female/young_caucasian_female.mhmat','Harveyg3g3.mhmat','Nipple_Skin.mhmat','skin_male_african_middleage.mhmat','middleage_african_female/middleage_african_female.mhmat','old_african_female/old_african_female.mhmat','summerglow.mhmat','young_caucasian_male/young_caucasian_male.mhmat','middleage_african_male/middleage_african_male.mhmat','old_african_male/old_african_male.mhmat','old_african_male/old_african_male.mhmat','middleage_asian_female/middleage_asian_female.mhmat','old_asian_female/old_asian_female.mhmat','young-caucasion-female-ehs01.mhmat','young_african_male/young_african_male.mhmat','young_lightskinned_female_diffuse2_tanlines_1.mhmat','middleage_asian_male/middleage_asian_male.mhmat','old_asian_male/old_asian_male.mhmat','young_asian_female/young_asian_female.mhmat']

for x in range(10):
    MHScript.randomize(human,1,True,True,True,True)
    MHScript.setMaterial('data/skins/'+skins[random.randint(0,len(skins)-1)])
    MHScript.exportmhx2('../../makehumanModels/model_'+str(x)+'.mhx2')

Die beiden Methoden exportmhx2() und randomize() wurden von mir hinzugefügt.

A 3D Morphable Model learnt from 10,000 faces

Lern-Datensätze

Die Erstellung eines neuronalen Netzes für die Generierung von 3d-Modellen von Gesichtern ist ambitioniert. Es ist bereits initial schwierig anzufangen da wenig Datensätze frei zur Verfügung stehen. Nach längerer Recherche habe ich einige Datensätze ausfindig machen können.

Name Samples Polygone
cyberware.com 100♀ 100♂ 106
www.micc.unifi.it/masi/research/ffd 53 ~105
3D-TEC (Twins Expression Challenge) 214
FRGC v2 ~2000
ND-Collection 27
MeIn3D 9967

MeIn3d

Besonders interessant ist hierbei der MeIn3D Datensatz welcher nach meinen Erkenntnissen das größte 3D-Modell Datenset für Gesichter darstellt. Es wurde 2012 von Londoner Science Museum mit Hilfe von Besuchern aufgenommen. Die Daten wurden zwei Instituten bereitgestellt zum einen dem Great Ormond Street Hospital und University College Hospital und dem Eastman Dental Hospital. Ich habe bereits versucht an den Datensatz heranzukommen aber bin bisher erfolglos geblieben.

Generierung von Lerndaten

A 3D Morphable Model learnt from 10,000 faces Eine interessante Arbeit[1] die auf den Mein3D Datensatz aufbaut, hat ein Modell erstellt um parametrierbare 3d-Modelle von Gesichtern zu erstellen. Es steht zu überprüfen ob die Generierung von Lerndaten für meine Master-Arbeit eine mögliche Alternative darstellt zu der Akquirierung von echten Datensätzen. Wichtig hierbei ist einerseits zu sehen in wieweit generierte Lerndaten die Wirklichkeit abbilden können. Zum Anderen ist es wichtig zu wissen wie viele Datensätze benötigt werden um gute Ergebnisse zu erzielen.

[1] A 3D Morphable Model learnt from 10,000 facesAllan Ponniah, David Dunaway, James Booth, Anastasios Roussos, Stefanos Zafeiriou

Vorstellung und Motivation

Das bin ich

Hallo,
mein Name ist Jan Scholz. Ich bin Vater eines 3 jährigen Sohns und selbst 33 Jahre alt. Ich bin gebürtiger Hamburger und habe bis auf 2 Jahre meinen Wohnsitz auch hier gehabt.

Motivation

Das Bestreben Dinge zu verstehen und die inneren Mechanismen zu durchschauen begann schon in meiner frühen Kindheit. Ich schraubte zum Beispiel meinen Radiowecker auf um zu sehen wie er funktioniert. Zusammengebaut habe ich ihn danach leider nicht mehr bekommen, aber das war es trotzdem für mich wert gewesen.
Schon seit langer Zeit hatte ich eine Faszination für Statistiken. Zahlen in aussagekräftige Darstellungen umzuwandeln so, dass einem Aussenstehenden auf einen Blick ein komplexer Sachverhalt oder eine Entwicklung klar wird ist eine Kunst (hierzu meine Lieblingsstatistik, sie zeigt den napoleonischen Russlandfeldzug von 1812). Mich begeistert außerdem die Idee auf der Basis von Daten Inferenzen über zukünftige Ereignisse machen zu können. Ich strebe eine Karriere im Bereich Data-Science an und bin zuversichtlich in diesem immer wichtiger werden Feld Fuß zu fassen.

Studium

Ich habe an der HAW (Hochschule für Angewandte Wissenschaften) Hamburg Informations- und Elektrotechnik im Bachelor abgeschlossen. Während meines Studiums wurde mir klar das ich die Elektrotechnik nicht sonderlich gut leiden kann, hingegen aber auf meiner Arbeit sehr gerne programmierte. So spezialisierte ich mich in meinem Studium weiter im Bereich Informatik und fing 2015 das Master-Studium Informatik an.
Das Master-Studium ist in mehrere Projekte geglieder auf die die Master-Thesis dann aufbaut.

Warum dieser Blog?

Ich arbeite zur Zeit am sog. Grundprojekt und habe mir vorgenommen meine Fortschritte in diesem Blog festzuhalten. Zum einen ist es für mich so einfacher regelmäßige Dokumentation meiner Arbeit zu erstellen da ich den Blog aktuell halten möchte. Und zum Anderen sehe ich außerdem die Chance meine Arbeit für die Öffentlich sichtbar zu machen und so in Kontankt mit potentiellen Arbeitgebern und allgemein mit anderen Menschen die mein Interesse für Data-Science teilen.

Das Thema meiner Master-Arbeit wird die Entwicklung eines neuronalen Netzes sein um aus einem Bild von einem Gesicht eine dreidimensionale Darstellung dieses Gesichts zu machen.