Data Science, Machine Learning und KI
Kontakt

Von der Zeichenbank zum Machine Learning Forschungsprojekt

Als eine der führenden Beratungen im Bereich Data Science, KI & Machine Learning treffen wir bei STATWORX regelmäßig Menschen, die uns mit ihren revolutionierenden Ideen nachhaltig beeindrucken. Eines haben viele dieser Menschen mit ihren Produktideen gemeinsam: Sie wollen einen persönlichen pain point in ihrer Arbeitweise verringern. Einer dieser spannenden Menschen mit einer außergewöhnlichen Idee ist Marco Limm.


Bild 1: Marco Limm, Gründer des Startups creaition

Marco Limm hat das Start-up creaition gegründet, das mit seinem Produkt den äußerst komplexen und sehr iterativen Prozess der Designentwicklung optimieren möchte. Aber wie er auf diese Idee?

Während seines Studiums im Bereich Transportdesign in den USA kam ihm erstmals die Idee, den Designprozess mit Hilfe von Machine Learning zu optimieren. Dazu motiviert hat ihn, dass viele seiner Arbeiten, um es in seinen Worten zu sagen, „für die Tonne“ produziert wurden und er dadurch angespornt wurde, einen effizienteren Weg zu finden.

Die Idee, ein eigenes Produkt zu entwickeln, dass als digitale Muse für Designer*innen fungiert, umtrieb Marco bereits seit dem 3. Semester sehr stark. Mit der Motivation, auch anderen Designer*innen damit die Arbeit zu erleichtern, und angespornt von der Neugier, ob seine Idee tatsächlich umsetzbar ist, entwickelte er aus der Idee eine Forschungsarbeit, der er sich sowohl für seine Bachelor- als auch seine Masterarbeit widmete.

Die Entwicklung des creaition Prototypen

Erste Versuche mit 3D Modellen, Bilddaten & knappen Ressourcen

Marco sieht den wichtigsten Einfluss von Designer*innen am Anfang und Ende des klassischen Designprozesses – darauf müssten sich Designer*innen seiner Meinung nach viel stärker konzentrieren können. Der mittlere Part des Designprozesses umfasst z.B. „stundenlanges Auto-Fronten zeichnen“, so Marco. „Die Morphologie kann die Maschine übernehmen, dafür braucht man keinen menschlichen Designer.“

Abbildung eines Designprozesses
Bild 2: Abbildung der klassischen Struktur des Designprozesses und des interaktiven Aufbaus.

Basierend auf der Grundidee der Optimierung durch Machine Learning startete Marco zusammen mit Kevin German, im Rahmen der gemeinsamen Bachelorarbeit an der Uni, die Entwicklung des Algorithmus. Ziel war es, eine künstliche Intelligenz (KI) zu trainieren, die selbstständig Design-Vorschläge basierend auf historischen Daten kreiert.

Zuerst hat das Duo versucht, mit 3D Modellen zu arbeiten, die Marco selbst erstellt hatte. Bei diesem Versuch stießen die beiden schnell an ihre Grenzen, da ihnen in der Uni nicht die ausreichende Rechenleistung und Infrastruktur zur Verfügung stand. Ein weiteres Problem waren zudem mangelnde Daten.

In einem zweiten Schritt versuchten sie sich an Bildern, die sie aus verschiedenen Quellen bezogen (Archive, Online etc.). Das hat zwar schon besser funktioniert, aber die Ergebnisse, die der Algorithmus aus diesen Daten generierte, waren mehr Kunst als Industriedesign. Einer seiner Professoren hätte diese Ergebnisse gerne als Kunstprojekt veröffentlicht, erzählt uns Marco. „Es kamen zwar schöne Kompositionen dabei raus, die man sicherlich in ein Museum stellen könnte, aber leider war das nicht das eigentlich Ziel.“


Bild 3: In einem „Picture Book“ zeigt Marco Limm die Ergebnisse der verschiedenen Phasen der Entwicklung des Machine Learning Algorithmus‘.

3-Layer Ansatz für den Machine Learning Algorithmus

Aus diesen ersten beiden gescheiterten Versuchen konnte die Erkenntnis gezogen werden, dass sie eine weniger komplexe, aber auch nicht zu abstrakte Datengrundlage brauchten. Es ging noch einmal zurück in die Recherche-Phase, Bücher wälzen, verschiedene Ansätze prüfen, neue Eindrücke sammeln. Das hatte zur Folge, dass sie im dritten Anlauf mit einem ganz neuen Ansatz starteten. Bei diesem neuen Ansatz unterteilten sie das Design in 3 Layer: Silhouette, Flächen, Grafiken. Die drei Layer, aus denen sich ein Design zusammensetzt, haben sie genutzt, um die Komplexität der Daten zu verringern.


Bild 4:  Auf dieser Zeichnung von Marco Limm sind man eine Auswahl der zahlreichen Entwürfe, die bei dem klassischen Designprozess vonnöten sind.

Mit dem 3-Layer Ansatz konnte Marco einen geeigneten Datensatz anlegen und mit diesen Daten den Algorithmus trainieren. Dabei heraus kamen 40.000 Designs, aus denen sie nun wählen konnten.

Aus diesem Ergebnis erwuchs die nächste Herausforderung: 40.000 Design zu evaluieren stellte keine wirkliche Arbeitserleichterung dar. Die Lösung? Ein genetischer Algorithmus, der aufgrund der Reaktionen der Designer*innen auf verschiedene Design-Vorschläge den individuellen Geschmack erkennt und darauf basierend neue Vorschläge generiert. Genannt haben sie das „Bottle-Tinder“ – denn auch hier swiped man weiter, je nachdem, ob einem das Design gefällt, oder nicht.

Beim „Bottle-Tinder“-Prinzip werden den Designer*innen immer wieder neue Designvorschläge präsentiert, die sie dann bewerten müssen. Nach etwa 15 Minuten kann der Algorithmus den Geschmack der Person extrahieren und anschließend beliebig anwenden.


Bild 5: In diesem Rendering ist das erste von der KI generierte Flaschendesign abgebildet.

Creaition unterwegs auf nationalen und internationalen Messen

Mit diesem Prototypen im Gepäck machte das Projekt creaition auf verschiedenen Messen auf sich aufmerksam und erhielt dort durchweg positives Feedback bekommen. Ihre Kolleg*innen aus der Designbranche sehen in ihrem Produkt ein hohes Potenzial – wer hat schon Lust auf stundenlanges Auto-Fronten zeichnen?

Creaition war u.a. bei folgenden Messen vertreten:

Next steps: Pilotprojekt

Wir von STATWORX unterstützen creaition aktuell bei Suche nach einem geeigneten Partner für ein Pilotprojekt. Ziel des Proof of Concepts ist die Entwicklung neuer Design-Entwürfe basierend auf extrahierter Design-DNA des Auftraggebers.

Konkret bedeutet das, dass der Machine Learning Algorithmus auf Grundlage Ihrer 2D-Daten neu trainiert wird und daraus eine Design-DNA herausfiltert, mit der dann wiederum beliebig viele neue Design-Vorschläge generiert werden können. In der Regel haben Unternehmen, die für diese Art von KI-Optimierung in Frage kommen, bereits eine Fülle an Daten (v.a. 2D-Daten ihrer Produkte), aus denen sie bisher keinen großen Nutzen ziehen. Nutzen Sie also das Potenzial Ihrer Daten und helfen Sie Ihrer Design-Abteilung dabei, repetitive und monotone Arbeitsschritte zu verringern, damit sie sich auf die wesentlichen, kreativen und schöpferischen Arbeiten konzentrieren können.

Sie möchten noch mehr über creaition erfahren? Hier können Sie sich das vollständige Conference-Paper herunterladen, das Marco Limm und seine Co-Autoren (Kevin German, Matthias Wölfel und Silke Helmerdig) für die ArtsIT zu diesem Thema verfasst haben.

Wenn Sie Interesse an einer Zusammenarbeit in diesem Pilotprojekt haben, dann kontaktieren Sie uns gerne über unser Kontaktformular oder schreiben Sie eine Mail an hello@creaition.io.

In the last Docker tutorial Olli presented how to build a Docker image of R-Base scripts with rocker and how to run them in a container. Based on that, I’m going to discuss how to automate the process by using a bash/shell script. Since we usually use containers to deploy our apps at STATWORX, I created a small test app with R-shiny to be saved in a test container. It is, of course, possible to store any other application with this automated script as well if you like. I also created a repository at our blog github, where you can find all files and the test app.

Feel free to test and use any of its content. If you are interested in writing a setup script file yourself, note that it is possible to use alternative programming languages such as python as well.

The idea behind it

$ docker-machine ls
NAME          ACTIVE   DRIVER       STATE     URL   SWARM   DOCKER    ERRORS
Dataiku       -        virtualbox   Stopped                 Unknown   
default       -        virtualbox   Stopped                 Unknown   
ShowCase      -        virtualbox   Stopped                 Unknown   
SQLworkshop   -        virtualbox   Stopped                 Unknown   
TestMachine   -        virtualbox   Stopped                 Unknown   

$ docker-machine start TestMachine
Starting "TestMachine"...
(TestMachine) Check network to re-create if needed...
(TestMachine) Waiting for an IP...
Machine "TestMachine" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

$ eval $(docker-machine env --no-proxy TestMachine)

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             
cfa02575ca2c        testimage           "/sbin/my_init"     2 weeks ago         
STATUS                            PORTS                    NAMES
Exited (255) About a minute ago   0.0.0.0:2000->3838/tcp   testcontainer

$ docker start testcontainer
testcontainer

$ docker ps
...

Building and rebuilding Docker images over and over again every time you make some changes to your application can get a little tedious at times, especially if you type in the same old commands all the time. Olli discussed the advantage of creating an intermediary image for the most time-consuming processes, like installing R packages to speed things up during content creation. That’s an excellent practice, and you should try and do this for every project viable. But how about speeding up the containerisation itself? A small helper tool is needed that, once it’s written, does all the work for you.

The tools to use

To create Docker images and containers, you need to install Docker on your computer. If you want to test or use all the material provided in this blog post and on our blog github, you should also install VirtualBox, R and RStudio, if you do not already have them. If you use Windows (10) as your Operating System, you also need to install the Windows Subsystem for Linux. Alternatively, you can create your own script files with PowerShell or something similar.

The tool itself is a bash/shell script that builds and runs docker containers for you. All you have to do to use it, is to copy the docker_setup executable into your project directory and execute it. The only thing the tool requires from you afterwards is some naming input.

If the execution for some reason fails or produces errors, try to run the tool via the terminal.

source ./docker_setup

To replicate or start a new bash/shell script yourself, open your preferred text editor, create a new text file, place the preamble #!/bin/bash at the very top of it and save it. Next, open your terminal, navigate to the directory where you just saved your script and change its mode by typing chmod +x your_script_name. To test if it works correctly, you can e.g. add the line echo 'it works!' below your preamble.

#!/bin/bash
echo 'it works!'

If you want to check out all available mode options, visit the wiki and for a complete guide visit the Linux Shell Scripting Tutorial.

The code that runs it

If you open the docker_setup executable with your preferred text editor, the code might feel a little overwhelming or confusing at first, but it is pretty straight forward.

#!/bin/bash

# This is a setup bash for docker containers!
# activate via: chmod 0755 setup_bash or chmod +x setup_bash
# navigate to wd docker_contents
# excute in terminal via source ./setup_bash

echo ""
echo "Welcome, You are executing a setup script bash for docker containers."
echo ""

echo "Do you want to use the Default from the global configurations?"
echo ""
source global_conf.sh
echo "machine name = $machine_name"
echo "container = $container_name"
echo "image = $image_name"
echo "app name = $app_name"
echo "password = $password_name"
echo ""

docker-machine ls
echo ""
read -p "What is the name of your docker-machine [default]? " machine_name
echo ""
if [[ "$(docker-machine status $machine_name 2> /dev/null)" == "" ]]; then
    echo "creating machine..." 
        && docker-machine create $machine_name
else
    echo "machine already exists, starting machine..." 
        && docker-machine start $machine_name
fi
echo ""
echo "activating machine..."
eval $(docker-machine env --no-proxy $machine_name)
echo ""

docker ps -a
echo ""
read -p "What is the name of your docker container? " container_name
echo ""

docker image ls
echo ""
read -p "What is the name of your docker image? (lower case only!!) " image_name
echo ""

The main code structure rests on nested if statements. Contrary to a manual docker setup via the terminal, the script needs to account for many different possibilities and even leave some error margin. The first if statement for example – depicted in the picture above – checks if a requested docker-machine already exists. If the machine does not exist, it will be created. If it does exist, it is simply started for usage.

The utilised code elements or commands are even more straightforward. The echo command returns some sort of information or a blank for better readability. The read command allows for user input to be read and stored as a variable, which in return enters all further code instances necessary. Most other code elements are docker commands and are essentially the same as the ones entered manually via the terminal. If you are interested in learning more about docker commands check the documentation and Olli’s awesome blog post.

The git repository

The focal point of the Git Repository at our blog github is the automated docker setup, but also contains some other conveniences and hopefully will grow into an entire collection of useful scripts and bashes. I am aware that there are potentially better, faster and more convenient solutions for everything included in the repository, but if we view it as an exercise and a form of creative exchange, I think we can get some use out of it.

The docker_error_logs executable allows for quick troubleshooting and storage of log files if your program or app fails to work within your docker container.

The git_repair executable is not fully tested yet and should be used with care. The idea is to quickly check if your local project or repository is connected to a corresponding Git Hub repository, given an URL address, and if not to eventually ‚repair‘ the connection. It can further manage git pulls, commits and pushes for you, but again please use carefully.

Next projects to come

As mentioned, I plan on further expanding the collection and usefulness of our blog github soon. In the next step I will add more convenience to the docker setup by adding a separate file that provides the option to write and store default values for repeated executions. So stay tuned and visit our STATWORX Blog again soon. Until then, happy coding.

Stephan Emmer

Stephan Emmer

In the last post of this series, we dealt with axis systems. In this post, we are also dealing with axes but this time we are taking a look at the position scales of dates, time, and datetimes. Since we at STATWORX are often forecasting – and thus plotting – time series, this is an important issue for us. The choice of axis ticks and labels can make the message conveyed by a plot clearer. Oftentimes, some points in time are – e.g. due to their business implications – more important than others and should be easily identified. Unequivocal, yet parsimonious labeling is key to the readability of any plot. Luckily, ggplot2 enables us to do so for dates and times with almost any effort at all.

We are using ggplot’s economics data set. Our base Plot looks like this:

base_plot <- ggplot(data = economics) +
  geom_line(aes(x = date, y = unemploy), 
            color = "#09557f",
            alpha = 0.6,
            size = 0.6) +
  labs(x = "Date", 
       y = "US Unemployed in Thousands",
       title = "Base Plot") +
  theme_minimal()

Scale Types

As of now, ggplot2 supports three date and time classes: POSIXct, Date and hms. Depending on the class at hand, axis ticks and labels can be controlled by using scale_*_date, scale_*_datetime or scale_*_time, respectively. Depending on whether one wants to modify the x or the y axis scale_x_* or scale_y_* are to be employed. For sake of simplicity, in the examples only scale_x_date is employed, but all discussed arguments work just the same for all mentioned scales.

Minor Modifications

Let’s start easy. With the argument limits the range of the displayed dates or time can be set. Two values of the correct date or time class have to be supplied.

 base_plot +
   scale_x_date(limits = as.Date(c("1980-01-01","2000-01-01"))) +
   ggtitle("limits = as.Date(c("1980-01-01","2000-01-01"))")

The expand argument ensures that there is some distance between the displayed data and the axes. The multiplicative constant is multiplied with the range of the displayed data, the additive is multiplied with one unit of the depicted data. The sum of the two resulting distances is added to the axis limits as padding. The resulting empty space is added at the left and right end of the x-axis or the top and bottom of the y-axis.

 base_plot +  
 scale_x_date(expand = c(0, 5000)) +   #5000/365 = 13.69863 years
   ggtitle("expand = c(0, 5000)")

position argument defines where the labels are displayed: Either “left” or “right” from the y-axis or on the “top” or on the “bottom” of the x-axis.

base_plot +  
   scale_x_date(position = "top") +
   ggtitle("position = "top"")

Axis Ticks and Grid Lines

More essential than the cosmetic modifications discussed so far are the axis ticks. There are several ways to define the axis ticks of dates and times. There are the labelled major breaks and further the minor breaks, which are not labeled but marked by grid lines. These can be customized with the arguments breaks and minor_breaks, respectively. The breaks as the well as minor_breaks can be defined by a numeric vector of exact positions or a function with the axis limits as inputs and breaks as outputs. Alternatively, the arguments can be set to NULL to display (minor) breaks at all. These options are especially handy if irregular intervals between breaks are desired.

 base_plot +  
  scale_x_date(breaks = as.Date(c("1970-01-01", "2000-01-01")),
               minor_breaks = as.Date(c("1975-01-01", "1980-01-01",
                                        "2005-01-01", "2010-01-01"))) +
   ggtitle("(minor_)breaks = fixed Dates")
base_plot +  
   scale_x_date(breaks = function(x) seq.Date(from = min(x), 
   											  to = max(x), 
   											  by = "12 years"),
                minor_breaks = function(x) seq.Date(from = min(x), 
                									to = max(x), 
                									by = "2 years")) +
   ggtitle("(minor_)breaks = custom function")
base_plot +  
	scale_x_date(breaks = NULL,
              minor_breaks = NULL) +
  ggtitle("(minor_)breaks = NULL")

Another and very convenient way to define regular breaks are the date_breaks and the date_minor_breaks argument. As input both arguments take a character vector combining a string specifying the time unit (either “sec“, „min“, „hour“, „day“, „week“, „month“ or „year“) and an integer specifying number of said units specifying the break intervals.

base_plot +
  scale_x_date(date_breaks = "10 years",
               date_minor_breaks = "2 years") +
  ggtitle("date_(minor_)breaks = "x years"")

If both are given, date(_minor)_breaks overrules (minor_)breaks.

Axis Labels

Similar to the axis ticks, the format of the displayed labels can either be defined via the labels or the date_labels argument. The labels argument can either be set to NULL if no labels should be displayed, with the breaks as inputs and the labels as outputs. Alternatively, a character vector with labels for all the breaks can be supplied to the argument. This can be very useful, since like this virtually any character vector can be used to label the breaks. The number of labels must be the same as the number of breaks. If the breaks are defined by a function, date_breaks or by default the labels must be defined by a function as well.

base_plot +
  scale_x_date(date_breaks = "15 years",
               labels = function(x) paste((x-365), "(+365 days)")) +
  ggtitle("labels = custom function") 
base_plot +
  scale_x_date(breaks = as.Date(c("1970-01-01", "2000-01-01")),
               labels = c("~ '70", "~ '00")) +
  ggtitle("labels = character vector")   

Furthermore and very conveniently, the format of the labels can be controlled via the argument date_labels set to a string of formatting codes, defining order, format and elements to be displayed:

Code Meaning
%S second (00-59)
%M minute (00-59)
%l hour, in 12-hour clock (1-12)
%I hour, in 12-hour clock (01-12)
%H hour, in 24-hour clock (01-24)
%a day of the week, abbreviated (Mon-Sun)
%A day of the week, full (Monday-Sunday)
%e day of the month (1-31)
%d day of the month (01-31)
%m month, numeric (01-12)
%b month, abbreviated (Jan-Dec)
%B month, full (January-December)
%y year, without century (00-99)
%Y year, with century (0000-9999)

Source: Wickham 2009 p. 99

base_plot +
  scale_x_date(date_labels = "%Y (%b)") +
  ggtitle("date_labels = "%Y (%b)"") 

The choice of axis ticks and labels might seem trivial. However, one should not underestimate the amount of confusion that can be caused by too many, too less or poorly positioned axis ticks and labels. Further, economical yet clear labeling of axis ticks can increase the readability and visual appeal of any time series plot immensely. Since it is so easy to tweak the date and time axes in ggplot2 there is simply no excuse not to do so.

References

  • Wickham, H. (2009). ggplot2: elegant graphics for data analysis. Springer.

 

Lea Waniek

Lea Waniek

Autokorrelation ist ein zentrales Element der Zeitreihenanalyse. Um den Nutzen greifen zu können, sollten wir zunächst einmal klären, was Autokorrelation überhaupt ist.

Autokorrelation

Korrelation beschreibt Einflüsse bzw. Abhängigkeiten von Zufallszahlen. Eine Autokorrelation hingegen beschreibt den Einfluss einer Zufallszahl auf vergangene Zeitpunkte. Das bedeutet, man vermutet bei solch einer Untersuchung, dass bei einer Zufallszahl zeitliche Abhängigkeiten bzw. Einflüsse vorzufinden sind.

Autokorrelation ist eine zentrale statistische Kennzahl der Zeitreihenanalyse, da bei Zeitreihenmodellen Vorhersagen meist nur auf Basis vergangener Zeitpunkte getroffen werden. Dementsprechend hängt die Güte der Vorhersage maßgeblich von der Autokorrelation ab.

Stellen wir uns einfach einmal vor, wir sind Hersteller von Faxgeräten. Eine zentrale Frage in unserem Unternehmen ist der Absatz im folgenden Monat, da wir somit die Produktion besser steuern und unsere Kosten minimieren können. Der einfachste und wohl logischste Weg den Absatz des Folgemonats zu schätzen, wäre den Absatz desselben Monats im Vorjahr anzunehmen. Dieser Ansatz ist nichts Weiteres als die Vermutung von Autokorrelation, da wir annehmen, dass der Absatz des Folgemonats in etwa so hoch sein wird wie der Absatz des äquivalenten Monats im Vorjahr.

Oft sind die Zusammenhänge aber komplexer, da die Autokorrelation nicht nur von einem vergangenen Zeitpunkt ausgeht, sondern von vielen vergangenen Zeitpunkten. Zudem kann sich die Autokorrelation über die Zeit maßgeblich ändern.

Identifikation

Es gibt viele Methoden relevante vergangene Zeitpunkte mithilfe von Autokorrelation bei einer Zeitreihe zu identifizieren. Die wohl bekannteste Methode ist die Bestimmung durch visuelles Beurteilen der (partiellen) Autokorrelationsfunktion. Hierbei wird die autokorrelative Struktur der Zeitreihe zu jedem vergangenen Zeitpunkt untersucht und jene Zeitpunkte als „signifikante“ Einflüsse deklariert, bei denen die Korrelation zum aktuellen Zeitpunkt über einer gewissen Schwelle (bspw. 0,05) liegt.

Diese Methode ist effektiv, aber mühsam, da man oft sehr viele Zeitreihen vorhersagen will. Des Weiteren muss man beurteilen, ab wann ein Einfluss „signifikant“ ist. Im R erweiternden Paket \texttt{forecast} gibt es eine Funktion (\texttt{auto.arima()}), welche die autokorrelative Struktur automatisch schätzt. Problem hierbei, sowie auch beim visuellen Beurteilen, ist allerdings, dass man nicht über die Form des Zusammenhangs urteilen kann. Bei beiden Methoden wissen wir nicht ob der Zusammenhang zwischen vergangenen Zeitpunkten und dem jetzigen linear oder nichtlinear ist.

Mithilfe von Gradient Boosting und Penalized Splines kann man die funktionale Form sowie die autokorrelative Struktur schätzen.(1)

Penalized Splines (P-Splines) transformieren unsere Einflussgrößen in ein stückweise zusammengesetztes Polynom mit beliebigem Grad. Das bedeutet diese Transformation ermöglicht es uns nichtlineare Zusammenhänge vergangener Zeitpunkte zu schätzen. Da wir nun lineare und nichtlineare Zusammenhänge schätzen können, fehlt nur noch ein Kriterium relevante Zeitpunkte herauszufiltern. Die Herangehensweise hier ist relativ simpel, da der Machine Learning Algorithmus Gradient Boosting automatisch nicht relevante Einflüsse ausschließt. Das bedeutet, dass wir dem Algorithmus lediglich alle relevanten vergangenen Zeitpunkte transformierter und nicht transformierter Version zur Verfügung stellen müssen.

Simulation

Simulieren wir uns mal zwei Zeitreihen und schauen ob das klappt:

(1)    \begin{equation*}\begin{split}Y_{t} &= \big(0.1-2.3\cos{(70Y_{t-6})}\exp{(-20Y_{t-6}^{2})}\big)Y_{t-6} \\ &+ \big(0.55 - 0.25\sin{(80Y_{t-10})}\exp{(-50Y_{t-10}^{2})}\big)Y_{t-10} + \epsilon_{t} \end{split}\end{equation*} \\

(2)    \begin{equation*}Y_{t} = 0.8\sin{(\frac{\pi}{8}Y_{t-4})} - 0.73\sin{(\frac{\pi}{8}Y_{t-5})} + 0.82\sin{(\frac{\pi}{4}Y_{t-6})} + 0.51\sin{(\frac{\pi}{4}Y_{t-7})} + \epsilon_{t} \end{equation*} \\

In der ersten Formel sehen wir, dass vier vergangene Zeitpunkte unsere Zielgröße beeinflussen. Zudem vermerken wir, dass dieser Einfluss nichtlinear ist. In der zweiten Simulation vermerken wir zwei nichtlineare Einflussgrößen, nämlich  Y_{t-6} und  Y_{t-10} . Nun versuchen wir mithilfe von Gradient Boosting diese Einflussgrößen zu identifizieren. Dies geschieht in dem wir den Einfluss von vergangenen Zeitpunkten in linearer und nichtlinearer Form auf die Zielgröße  Y_{t} schätzen. Mathematisch können wir unser Problem folgendermaßen formulieren:

(3)    \begin{equation*}Y_{t} = \beta_0 + \beta_1 Y_{t-1} + \beta_2 Y_{t-2} + \ldots + \beta_{12} Y_{t-12} + \beta_{13} f(Y_{t-1}) + \beta_{14} f(Y_{t-2}) + \ldots + \beta_{24} f(Y_{t-12}) + \epsilon_{t} \end{equation*} \\

wobei die Koeffizienten  \beta_{12}, \ldots, \beta_{24} alle nichtlinearen Funktionen markieren.

Da der Algorithmus beim Schätzen der Effekte nur für ihn relevante Einflüsse schätzt, können wir uns irrelevante und relevante Effekte in Form von einer Einflussbedeutung ansehen. In Abbildung 1 sehen wir die Relevanz der Einflüsse. Alle relevanten Zeitpunkte werden in beiden Funktionen selektiert. Wohingegen weder fälschlicherweise lineare Zusammenhänge noch andere vergangene Zeitpunkte jeglicher Form selektiert werden.

Abbildung 1: Nichtlinearer und linearer Variableneinfluss vergangener Zeitpunkte

Generalisierbarkeit

Mithilfe dieser Methode können relevante Zeitpunkte in linearer sowie nichtlinearer Form identifiziert werden und zur Vorhersage genutzt werden, ohne das Modell unnötig zu überspezifizieren. Zusätzlich kann man diesen Ansatz problemlos automatisieren und kann somit auf eine visuelle Beurteilung von Autokorrelationsfunktionen verzichten. Umsetzen kann man diese Methode bspw. mit dem R Paket  \texttt{mboost} .(2)

Zum Paket selbst gibt es ein Tutorial in dem man leicht alle Funktionen, sowie die Spezifikation von linearen und nichtlinearen Einflussfaktoren kennen lernt.(3) Das Paket wurde mithilfe von  \texttt{Rcpp} (hier eine kleine Einführung) erstellt und ist somit sehr effizient und schnell.

Für alle Interessierten Leser zu dieser Thematik empfehle ich die wissenschaftliche Arbeit von Tutz und Shafik (2007), bei welcher die Thematik und Umsetzung im Detail vorgestellt wird.

Referenzen

  • Bühlmann, Peter, and Torsten Hothorn. „Boosting algorithms: Regularization, prediction and model fitting.“ Statistical Science(2007): 477-505.
  • Hothorn, Torsten, et al. „mboost: Model-based boosting.“ R package version (2012): 2-1.
  • Hofner, Benjamin, et al. „Model-based boosting in R: a hands-on tutorial using the R package mboost.“ Computational statistics29.1-2 (2014): 3-35.
  • Shafik, Nivien, and Gerhard Tutz. „Boosting nonlinear additive autoregressive time series.“ Computational Statistics & Data Analysis 53.7 (2009): 2453-2464.

André Bleier André Monaco

Autokorrelation ist ein zentrales Element der Zeitreihenanalyse. Um den Nutzen greifen zu können, sollten wir zunächst einmal klären, was Autokorrelation überhaupt ist.

Autokorrelation

Korrelation beschreibt Einflüsse bzw. Abhängigkeiten von Zufallszahlen. Eine Autokorrelation hingegen beschreibt den Einfluss einer Zufallszahl auf vergangene Zeitpunkte. Das bedeutet, man vermutet bei solch einer Untersuchung, dass bei einer Zufallszahl zeitliche Abhängigkeiten bzw. Einflüsse vorzufinden sind.

Autokorrelation ist eine zentrale statistische Kennzahl der Zeitreihenanalyse, da bei Zeitreihenmodellen Vorhersagen meist nur auf Basis vergangener Zeitpunkte getroffen werden. Dementsprechend hängt die Güte der Vorhersage maßgeblich von der Autokorrelation ab.

Stellen wir uns einfach einmal vor, wir sind Hersteller von Faxgeräten. Eine zentrale Frage in unserem Unternehmen ist der Absatz im folgenden Monat, da wir somit die Produktion besser steuern und unsere Kosten minimieren können. Der einfachste und wohl logischste Weg den Absatz des Folgemonats zu schätzen, wäre den Absatz desselben Monats im Vorjahr anzunehmen. Dieser Ansatz ist nichts Weiteres als die Vermutung von Autokorrelation, da wir annehmen, dass der Absatz des Folgemonats in etwa so hoch sein wird wie der Absatz des äquivalenten Monats im Vorjahr.

Oft sind die Zusammenhänge aber komplexer, da die Autokorrelation nicht nur von einem vergangenen Zeitpunkt ausgeht, sondern von vielen vergangenen Zeitpunkten. Zudem kann sich die Autokorrelation über die Zeit maßgeblich ändern.

Identifikation

Es gibt viele Methoden relevante vergangene Zeitpunkte mithilfe von Autokorrelation bei einer Zeitreihe zu identifizieren. Die wohl bekannteste Methode ist die Bestimmung durch visuelles Beurteilen der (partiellen) Autokorrelationsfunktion. Hierbei wird die autokorrelative Struktur der Zeitreihe zu jedem vergangenen Zeitpunkt untersucht und jene Zeitpunkte als „signifikante“ Einflüsse deklariert, bei denen die Korrelation zum aktuellen Zeitpunkt über einer gewissen Schwelle (bspw. 0,05) liegt.

Diese Methode ist effektiv, aber mühsam, da man oft sehr viele Zeitreihen vorhersagen will. Des Weiteren muss man beurteilen, ab wann ein Einfluss „signifikant“ ist. Im R erweiternden Paket \texttt{forecast} gibt es eine Funktion (\texttt{auto.arima()}), welche die autokorrelative Struktur automatisch schätzt. Problem hierbei, sowie auch beim visuellen Beurteilen, ist allerdings, dass man nicht über die Form des Zusammenhangs urteilen kann. Bei beiden Methoden wissen wir nicht ob der Zusammenhang zwischen vergangenen Zeitpunkten und dem jetzigen linear oder nichtlinear ist.

Mithilfe von Gradient Boosting und Penalized Splines kann man die funktionale Form sowie die autokorrelative Struktur schätzen.(1)

Penalized Splines (P-Splines) transformieren unsere Einflussgrößen in ein stückweise zusammengesetztes Polynom mit beliebigem Grad. Das bedeutet diese Transformation ermöglicht es uns nichtlineare Zusammenhänge vergangener Zeitpunkte zu schätzen. Da wir nun lineare und nichtlineare Zusammenhänge schätzen können, fehlt nur noch ein Kriterium relevante Zeitpunkte herauszufiltern. Die Herangehensweise hier ist relativ simpel, da der Machine Learning Algorithmus Gradient Boosting automatisch nicht relevante Einflüsse ausschließt. Das bedeutet, dass wir dem Algorithmus lediglich alle relevanten vergangenen Zeitpunkte transformierter und nicht transformierter Version zur Verfügung stellen müssen.

Simulation

Simulieren wir uns mal zwei Zeitreihen und schauen ob das klappt:

(1)    \begin{equation*}\begin{split}Y_{t} &= \big(0.1-2.3\cos{(70Y_{t-6})}\exp{(-20Y_{t-6}^{2})}\big)Y_{t-6} \\ &+ \big(0.55 - 0.25\sin{(80Y_{t-10})}\exp{(-50Y_{t-10}^{2})}\big)Y_{t-10} + \epsilon_{t} \end{split}\end{equation*} \\

(2)    \begin{equation*}Y_{t} = 0.8\sin{(\frac{\pi}{8}Y_{t-4})} - 0.73\sin{(\frac{\pi}{8}Y_{t-5})} + 0.82\sin{(\frac{\pi}{4}Y_{t-6})} + 0.51\sin{(\frac{\pi}{4}Y_{t-7})} + \epsilon_{t} \end{equation*} \\

In der ersten Formel sehen wir, dass vier vergangene Zeitpunkte unsere Zielgröße beeinflussen. Zudem vermerken wir, dass dieser Einfluss nichtlinear ist. In der zweiten Simulation vermerken wir zwei nichtlineare Einflussgrößen, nämlich  Y_{t-6} und  Y_{t-10} . Nun versuchen wir mithilfe von Gradient Boosting diese Einflussgrößen zu identifizieren. Dies geschieht in dem wir den Einfluss von vergangenen Zeitpunkten in linearer und nichtlinearer Form auf die Zielgröße  Y_{t} schätzen. Mathematisch können wir unser Problem folgendermaßen formulieren:

(3)    \begin{equation*}Y_{t} = \beta_0 + \beta_1 Y_{t-1} + \beta_2 Y_{t-2} + \ldots + \beta_{12} Y_{t-12} + \beta_{13} f(Y_{t-1}) + \beta_{14} f(Y_{t-2}) + \ldots + \beta_{24} f(Y_{t-12}) + \epsilon_{t} \end{equation*} \\

wobei die Koeffizienten  \beta_{12}, \ldots, \beta_{24} alle nichtlinearen Funktionen markieren.

Da der Algorithmus beim Schätzen der Effekte nur für ihn relevante Einflüsse schätzt, können wir uns irrelevante und relevante Effekte in Form von einer Einflussbedeutung ansehen. In Abbildung 1 sehen wir die Relevanz der Einflüsse. Alle relevanten Zeitpunkte werden in beiden Funktionen selektiert. Wohingegen weder fälschlicherweise lineare Zusammenhänge noch andere vergangene Zeitpunkte jeglicher Form selektiert werden.

Abbildung 1: Nichtlinearer und linearer Variableneinfluss vergangener Zeitpunkte

Generalisierbarkeit

Mithilfe dieser Methode können relevante Zeitpunkte in linearer sowie nichtlinearer Form identifiziert werden und zur Vorhersage genutzt werden, ohne das Modell unnötig zu überspezifizieren. Zusätzlich kann man diesen Ansatz problemlos automatisieren und kann somit auf eine visuelle Beurteilung von Autokorrelationsfunktionen verzichten. Umsetzen kann man diese Methode bspw. mit dem R Paket  \texttt{mboost} .(2)

Zum Paket selbst gibt es ein Tutorial in dem man leicht alle Funktionen, sowie die Spezifikation von linearen und nichtlinearen Einflussfaktoren kennen lernt.(3) Das Paket wurde mithilfe von  \texttt{Rcpp} (hier eine kleine Einführung) erstellt und ist somit sehr effizient und schnell.

Für alle Interessierten Leser zu dieser Thematik empfehle ich die wissenschaftliche Arbeit von Tutz und Shafik (2007), bei welcher die Thematik und Umsetzung im Detail vorgestellt wird.

Referenzen

André Bleier André Monaco