Ein kompakter Einstieg in Recommender-Systeme

Eine gute Empfehlung
Keine Kommentare

Die Grundlage von Empfehlungssystemen, wie sie für Amazon und Co. gelten, ist keine Zauberei. Auf verständliche Weise vermittelt der folgende Beitrag die notwendigen Zusammenhänge, um sich bei Interesse tief gehender mit der Thematik vertraut zu machen.

Die Motivation ein Recommender System, sprich ein Empfehlungssystem, anzubieten, hat verschiedene Ausprägungen. Der Maßstab über die Güte eines solchen Service ist, wie gut die ausgesprochenen Empfehlungen den Bedürfnissen des Kunden tatsächlich auch entsprechen. Recommender sind Werkzeuge, die bei einer Entscheidungsfindung unterstützen. Sie sind allerdings nicht gleichzusetzen mit sogenannten Expertensystemen, die sich den Methoden der künstlichen Intelligenz (KI) bedienen. Im Wesentlichen kann man sagen, dass ein Expertensystem auf der Grundlage einer definierten Wissensbasis und einem zugehörigen Regelsatz die höchste Wahrscheinlichkeit einer Diagnose ermittelt und diese anhand von Fakten begründet. Ein klassisches Beispiel dafür ist das Diagnostizieren einer Krankheit anhand bestimmter Symptome. Es ist für das Expertensystem nicht maßgeblich, wie oft diese Krankheit bereits erfolgreich diagnostiziert wurde. Bei einem Recommender ist genau diese Häufigkeit – wie oft ein Merkmal zutrifft – das Entscheidungskriterium. Bei der Vielzahl der angebotenen Services im Internet ergibt sich denklich eine große Fülle von möglichen Anwendungen. Diese können beispielsweise Kinofilme, Musiktitel, Wahlpflichtkurse einer Schule, Artikel eines Onlineshops oder Ähnliches sein.

Das, was die Empfehlung beinhaltet, wird als Item (Gegenstand) bezeichnet. Ein Item kann mehrere Eigenschaften (Merkmale) besitzen. Merkmale werden auch oft als Attribute bezeichnet. Vielmals ist es vorteilhaft, den Merkmalen eine Rangordnung (Präferenz) zu zuweisen. Der mathematische Ausdruck dazu lautet Wichtung und beschreibt, ob ein Merkmal mit einem hohen oder geringen Gewicht bei der Berücksichtigung einfließt.

Spiel der Zahlen

Auch wenn es im ersten Moment lästig erscheinen mag, gehört ein wenig Rechenkunst dazu. Aber keine Sorge, die hier besprochenen Dinge wurden auf ein absolutes Minimum reduziert, und mehr als die Grundrechenarten werden für den kleinen Ausflug in die Statistik nicht benötigt. Weil man aber bekanntlich nur einer Statistik Glauben schenken soll, die man selbst gefälscht hat, ist ein wenig Wissen darüber, wie und warum Dinge auf eine bestimmte Art und Weise gezählt werden, recht nützlich.

Grundsätzlich unterscheidet man dabei zwei Ausprägungen: Aufzählen und Abzählen. Beim Aufzählen von Dingen kommt eine Liste zustande, deren Inhalt die vorkommenden Items enthält. Bei mehrfachem Vorkommen eines Items wird dies jedoch nur einmal aufgezählt. Es gibt keinen Rückschluss über die Häufigkeit des Vorkommens eines Items. Beim Abzählen hingegen wird diese Frage beantwortet. Als Resultat erhält man die exakte Anzahl des Vorkommens eines ausgewählten Items. In den meisten Fällen ist eine Empfehlung eine Mischform beider Strategien. Die Ergebnisliste der Items ist nach der höchsten Wahrscheinlichkeit absteigend sortiert. Das Ziel ist es, Items zu ermitteln, deren Merkmale größtmöglich mit den Vorlieben beziehungsweise den Bedürfnissen des Kunden übereinstimmen.

Die einfachste Möglichkeit, über eine Menge von Zahlen einen Erwartungswert, auch Mittelwert genannt, zu bestimmen, ist die Berechnung des arithmetischen Mittels. Eine gebräuchlichere Bezeichnung lautet Durchschnitt und ergibt sich aus dem Aufsummieren aller ermittelten Werte. Die Summe wird anschließend durch die Anzahl der berücksichtigten Werte dividiert:

Der Erwartungswert liegt für diesen Fall innerhalb des Zahlenbereichs des kleinsten und des größten auftretenden Werts. Diese Grenzen bezeichnet man Spannweite. Durch verschiedene Einflüsse kann es allerdings vorkommen, dass ein Wert nicht zu den restlich ermittelten Werten passt. Am einfachsten ist es, solche Ausreißer nicht zu berücksichtigen. Da die Verarbeitung allerdings voll automatisiert erfolgt, muss ein solcher Ausreißer programmatisch in der Berechnung aussortiert werden. Das kann man beispielsweise dadurch erreichen, indem die Abstände zwischen benachbarten Items ermittelt werden. Das Festlegen eines Schwellwerts, der dafür Sorge trägt, Ausreißer zu eliminieren, ist eine mögliche Option. Typischerweise befinden sich Ausreißer an den Grenzen der Messreihen, weswegen diese Strategie einfach, aber wirkungsvoll ist.

Eine weitere Art, den Mittelwert zu bestimmen, ist die Verwendung des gewichteten Mittels. Dieses Verfahren berücksichtigt die Häufigkeit des Auftretens eines Elements. Das Item (x) wird mit der Häufigkeit (ni), mit der es in der Datenbasis auftritt, multipliziert, und diese Ergebnisse sind anschließend aufzusummieren und durch die gesamte Anzahl aller vorkommenden Items zu dividieren. Daraus ergibt sich die nachfolgende Formel:

Als Modus bezeichnet man genau das Item, das am Häufigsten in der betrachteten Datenbasis vorkommt. Basiert die Datenbasis hingegen auf Zuwachs, wie es beispielsweise bei Zinsen der Fall ist, eignet sich die Anwendung des arithmetischen Mittels nicht mehr. Für diese Problemstellungen greift man meist zum geometrischen Mittel, das durch folgende Formel definiert ist:

Diese kleine Einführung soll uns nun genügen, und es sei zusätzlich auf die sehr umfangreich verfügbare Literatur über Statistik und Stochastik verwiesen. Eine letzte Anmerkung für mathematisch interessierte Leser: Die frei verfügbare Programmiersprache R ist ein sehr hilfreiches Werkzeug für statistische Berechnungen.

Beschäftigen wir uns nun etwas detaillierter mit dem gesellschaftlichen Aspekt von Empfehlungen und deren Einordnung in programmatische Modelle.

Guter Rat ist teuer

Weil – wie bei so vielen Dingen – auch das Gefühl eine wichtige Rolle spielt, ist es nicht verkehrt, sich bei technischen Systemen an der Wirklichkeit zu orientieren. Dabei lassen sich die Erwartungen auf ein gesundes Maß bringen. Wer beispielsweise im Bekanntenkreis um eine Empfehlung gebeten wird, hat grundsätzlich die Optionen intrinsisch oder extrinsisch zur Auswahl.

Ein intrinsischer Ratschlag ist selbstbezogen und empfiehlt nach den Maßstäben des Ratgebenden. Typische Muster dafür sind: „Du solltest unbedingt den Film XYZ anschauen, der hat mich so beeindruckt. Genau nach meinem Geschmack.“ Solche Aussagen sind für technische Systeme wenig förderlich, weswegen die extrinsische Sicht, also die fremdbezogene Sicht, bevorzugt wird. Bei dieser Möglichkeit werden so viele Informationen wie möglich über die Vorlieben des Ratsuchenden eingeholt, um eine stark personalisierte Aussage treffen zu können. Dabei gilt: Je detaillierter diese Bedürfnisse ermittelt werden können, umso präziser kann ein Vorschlag unterbreitet werden. Dies ist auch der Maßstab für die Akzeptanz solcher Services. Stellt der Klient vermehrt fest, dass die Vorschläge nicht auf seine Bedürfnisse abgestimmt sind, wird er diese zukünftig ignorieren, anstatt ihnen motiviert zu folgen. Dies ist auch ein Grund, weshalb große Unternehmen einen erheblichen Aufwand betreiben, um möglichst viel über ihre Kunden in Erfahrung zu bringen. Das Erheben der verschiedenen Daten über ausgeklügelte Tracking-Verfahren ist eine der schwierigsten Herausforderungen in dieser Disziplin. Um möglichst wenig Schwankungen (Rauschen) zu erhalten, werden bevorzugt automatisiert gewonnene Erkenntnisse verwertet.

API Conference 2018

API Management – was braucht man um erfolgreich zu sein?

mit Andre Karalus und Carsten Sensler (ArtOfArc)

Web APIs mit Node.js entwickeln

mit Sebastian Springer (MaibornWolff GmbH)

Sehr interessant in diesem Zusammenhang ist der kommerzielle Videostreamingdienst Netflix, der seine Navigation auf Recommendation-Services ausgelegt hat. Die unterbreiteten Vorschläge werden durch Benutzerratings zusätzlich gestützt. Dadurch erhält der Nutzer eine Übersichtsseite mit Filmen und Serien, die auf seine Interessen abgestimmt sind. Je nach persönlicher Stimmung kann der Nutzer nun einen durch die Community hoch bewerteten Film auswählen oder einen noch recht unbekannten Titel anschauen und ihn durch eigene Ratings pushen.

Wichtig im Bezug auf Ratings ist Transparenz. So hat ein Titel mit hundert unterschiedlichen Bewertungen eine höhere Aussage als ein Titel mit höchstem Ranking, das aber durch nur fünf Bewertungen zustande gekommen ist. Daher sollte dieses wichtige Detail dem Nutzer nicht vorenthalten werden. Diese Überlegungen finden sich übrigens auch in einer leicht abgewandelten Form beim Ranking von Internetseiten durch Google. Um dem Nutzer einen einfachen Zugang zum gesamten Inhalt zu ermöglichen, kombiniert Netflix die Navigation mit einer Suchfunktion, die für diesen Fall eine optimale Usability der Webseite darstellt. Für Googles YouTube wiederum ist die Anzahl der vorhandenen Views ein wichtiger Parameter der unterbreiteten Vorschläge. So gewinnt man bei stärkerer Analyse den Eindruck, dass YouTube vornehmlich auf automatisierten Modellen operiert.

Wer suchet, der findet

Ein weiterer Punkt in der Theorie der Empfehlungen ist die Auswahl einer geeigneten Suchstrategie. Die optimale Lösung dieser Fragestellung beeinflusst merklich die Geschwindigkeit des Recommenders. Ein wichtiger Parameter ist das Terminierungsverhalten, sprich die Entscheidung darüber, ob die Suche möglicherweise frühzeitig beendet wird – auch wenn eventuell weitere Einträge vorhanden sind. Das Ermitteln sinnvoller Schwellenwerte für einen Abbruch lässt sich am besten anhand von Versuch und Irrtum bewerkstelligen, sofern sich kein geeignetes Abbruchskriterium voraussagen lässt. Je nach Empfehlungsdomäne gilt es zu entscheiden, ob man vorzugsweise auf eine Tiefensuche oder doch besser eine Breitensuche setzt. Abbildung 1 zeigt den Unterschied sehr anschaulich: Der zu untersuchende Baum hat die Tiefe 4. Ausgehend vom Wurzelknoten (root) A auf der Ebene 0 durchläuft eine Tiefensuche zuerst die Kanten (edge) I, IV und VII, um in das Blatt (leaf) I abzusteigen. Dabei werden die Knoten (node) B und E betrachtet. Eine Breitensuche hingegen traversiert vom Wurzelknoten zuerst die Kanten I, II und III und untersucht dabei die Knoten B, C und D, bevor sie in die nächste Ebene absteigt. Es lässt sich leicht erkennen, dass eine Breitensuche bei gut durchmischter Verteilung sehr schnell Ergebnisse liefert.

Um eine Domäne vollständig zu durchsuchen, bedient man sich dem Backtracking. Dieser Algorithmus basiert häufig auf der Tiefensuche und durchläuft den Pfad komplett von der Wurzel bis zum Blatt. Anschließend springt der Cursor zurück zur letzten Verzweigung, um dort in den nächsten Ast abzusteigen. Dieser Vorgang wiederholt sich so lange, bis der ganze Baum durchlaufen ist oder das Abbruchskriterium erreicht wurde.

Abb. 1: Ein Vergleich von Tiefen- und Breitensuche

Abb. 1: Ein Vergleich von Tiefen- und Breitensuche

Es besteht auch die Möglichkeit, für den Suchalgorithmus die Suchrichtung festzulegen. Eine vorwärtsgerichtete Suche oder auch datenbasierte Suche orientiert sich im Problemlösungsverfahren an Fakten, auf die Regeln angewendet werden, um weitere Fakten zu generieren, bis die Zielbestimmung erfüllt wurde. Die Alternative ist die rückwärtsgerichtete Suche oder auch zielorientierte Suche, die zuerst das Ziel vorgibt. Zu diesem Ziel sind die notwendigen Regeln zu ermitteln, die auf die Fakten anzuwenden sind, bis die Ausgangssituation erfüllt wurde. Zur Bewertung der geeigneten Suchrichtung sei kurz ein Beispiel aus der Ahnenforschung angeführt, das aus [1] entnommen ist. Zur Klärung der Frage ob „ich“ ein Nachkomme von Thomas Edison bin, wäre eine rückwärtsgerichtete Suche ausgehend von „ich“ der effizientere Ansatz. Für diesen Fall sind ausschließlich die von mir in direkter Abstammung befindlichen Vorfahren zu untersuchen. Eine vorwärtsgerichtete Suche ausgehend von Thomas Edison müsste alle Verzweigungen einbeziehen, was zu mehr Möglichkeiten führt.

Strategieauswahl

Für die Umsetzung eines Recommender-Systems existieren verschiedene Varianten, die auch als Mischform auftreten können. Grundsätzlich unterscheidet man zwischen personalisierten und kollaborativen Recommendern. Das kollaborative System ordnet das Nutzerprofil einer Gruppe zu und berücksichtigt die Vorlieben der Gemeinschaft. Im Vergleich zu personalisierten Recommender-Systemen sind diese ressourcenschonender. Innerhalb dieser Aufteilung klassifiziert man die verwendeten Algorithmen nach wissensbasiertem und inhaltsbasierendem Vorgehen. Die Eigenschaft eines contentbasierten Algorithmus fördert Ergebnisse zutage, die weitere Treffer mit den persönlichen Vorlieben produzieren. „Zeige mir mehr von den Dingen, die ich mag.“ Ein wissensbasiertes System hingegen produziert Treffer nach den ermittelten Bedürfnissen: „Zeige mir, was am besten auf meine Bedürfnisse passt.“

Da sich Empfehlungen wie ein Filter über einer Datenbasis verhalten, spricht man auch von Filtering. Der beliebteste Algorithmus für kollaborative Filter in großen E-Commerce-Systemen ist Wisdom of the Crowd, was so viel bedeutet wie: die Weisheit der Masse. Diese Methode lässt sich für viele Anwendungen leicht spezialisieren, und es gibt hinreichend Erfahrungen, die die Wirksamkeit belegen.

Die Grundidee basiert auf Userratings, die in einer Matrix organisiert sind. Daraus ergibt sich folgender Algorithmus: Finde für den Nutzer Zac (User a) ein Item, das nicht mit ihm in direkter Verbindung steht und das andere Nutzer (User b) mit ähnlichen Vorlieben wie Zac sehr hoch bewertet haben. Die nachfolgende Formel nennt sich Pearson-Korrelation und ermittelt für den User a aus der bestehenden Datenbasis weitere User b, die ähnliche Vorlieben wie User a haben. Die möglichen Werte dieser Berechnung liegen zwischen -1 (keine Übereinstimmung) bis +1 (hohe Übereinstimmung). Die Variablen a und b stehen für die User. P repräsentiert das Itemset, das durch a und b bewertet wurde. Die Bewertungen des Items (rating) wiederum werden durch r repräsentiert:

Die gewonnenen Ergebnisse werden wiederum für die Berechnung der Vorhersagen herangezogen:

Die Grenzen dieser Strategie liegen in umfangreichen Datenbeständen, die für jeden Nutzer entsprechend bewertet werden müssen. Daher gelangt der Memory-basierte Ansatz, der die Ratings on the fly auf der vorhandenen Datenbasis ermittelt, schnell an seine Grenzen. Um die Anzahl der Berechnungen zu reduzieren, greift man auf Modelle zu, die eine vorberechnete Anzahl von Ratings enthalten. In regelmäßigen Abständen wird das Model aktualisiert. Daher spricht man beim modellbasierten Ansatz auch von einer Offlinestrategie.

Für den Fall, dass schlichtweg nicht genügend Ratings für die vorhandenen Items verfügbar sind, bedient man sich wissensbasierten Algorithmen. Bei dieser Betrachtungsweise ist der Zeitraum, der für die Ratings herangezogen wird, relevant. Zudem bevorzugen die Nutzer konkrete Eigenschaften wie „Die Farbe meines neuen Fahrzeugs sollte schwarz sein!“. Für diese Aufgabenstellung existiert eine Constraint-basierte Lösung und eine fallbasierte Lösung. Beide Strategien sind in ihrem Empfehlungsprozess sehr identisch. Exemplarisch soll für wissensbasierte Empfehlungssysteme der fallbasierte Ansatz (Case) vorgestellt werden. Dieses Szenario ermittelt die Abstandsidentität zwischen den vorhandenen Items zu den Nutzer-Requirements. Den Anforderungen wird eine Wichtung zugeordnet, um Aussagen genauer klassifizieren zu können. Übliche Kriterien sind: Ermittle den günstigsten Anbieter für Spiegelreflexkameras mit der höchsten Auflösung. Die Berechnung geschieht mit folgender Formel:

Die Übereinstimmung sim eines Items I zu den Requirements R ergibt sich aus der Division über die Summe aller Wichtungen w und der Summe der gewichteten Übereinstimmungen aller Itemattribute a zu deren Anforderungen r. Dieses auf den ersten Blick kompliziert wirkende Konstrukt ist lediglich eine mathematische Beschreibung verschiedener Vergleichsoperationen. So wird im erwähnten Beispiel der Kameraauflösung ein Modell zugeordnet, das die Itemattribute geeignet abbildet. Es lässt sich sehr gut mit einer individuell erstellten Suche vergleichen.

Collaborative Item-based Filter in PHP

Ein sehr leicht zu benutzender Recommender wurde von Sameer Borate in PHP geschrieben. Auf seinem Blog codediesel können die unter GNU lizenzierten Quellen heruntergeladen werden. Die Implementierung läuft sehr stabil und ist laut Aussage des Entwicklers auch für große Systeme gut geeignet. Besonders charmant ist, dass diese Implementierung mit einer einzigen Klasse auskommt, die knappe hundert Zeilen Code enthält.

Das hier vorgestellte Beispiel dient dazu, Nutzern geeignete Bücher zu empfehlen. Dazu existiert ein Array sämtlicher Nutzer, denen wiederum ein Array mit den von ihnen gerateten Büchern zugeordnet ist. Die Datei sample_list.php enthält alle notwendige Einträge für das hier vorgestellte Beispiel. Nachdem das Skript recommend.php eingebunden wurde, kann es auch direkt verwendet werden, wie folgende Codezeilen zeigen:

require_once("recommend.php");
require_once("sample_list.php");
$re = new Recommend();
print_r($re->getRecommendations($books, "jill"));

Das kurze Beispiel erzeugt für Jill ein Array mit einer Liste an Buchempfehlungen, wie sie in Abbildung 2 zu sehen ist. Unter Anwendung der vorher beschriebenen Algorithmen erhält Jill für das Buch „a thousand splendid suns“ ein Rating von 5. Als Argumente der Methode getRecomendations() wird zum einen die Datenstruktur $books sowie der entsprechende Nutzer, für den die Empfehlung ausgesprochen werden soll, erwartet.

Abb. 2: Ein Vergleich von Tiefen- und Breitensuche

Abb. 2: Ein Vergleich von Tiefen- und Breitensuche

Ein weiteres sehr nützliches Feature ist die Ausgabe eines inversen Ratings. Dazu wird die Methode transformPreferences() mit dem $booksArray als Parameter aufgerufen. Als Ausgabe erhält man eine Auflistung der einzelnen Bücher mit den zugehörigen Userratings. In einem weiteren Schritt kann die Pearson-Korrelation zwischen zwei Items bestimmt werden. Für das Buch „chaos“ ermittelt die Methode matchItems() den Titel „php in action“ als nächsten Nachbarn mit dem Wert 0,4. Eine zusätzliche Betrachtungsweise ist die Bestimmung der Übereinstimmung zweier Nutzer. Hierfür enthält die Klasse Recommend die Methode similarityDistance(), die für die Nutzer Tom und Peter eine Übereinstimmung von 28,57 Prozent feststellt.

Das Skript lässt sich dank seiner Kompaktheit gut anpassen und gegebenenfalls erweitern. Auch wenn auf den ersten Blick die Datenstruktur recht einfach aufgebaut ist, lässt sie sich für die allermeisten Szenarien verwenden.

Die dunkle Seite der Macht

Dass Empfehlungssysteme einen breiten Nutzen haben, ist unumstritten. Dass ihr Einsatz aber durchaus kontrovers zu diskutieren ist, zeigt die Dominanz des sozialen Netzwerks Facebook. In diesem speziellen Fall ist die Informationsbeschaffung von Facebook stark zu hinterfragen. Denn der Dienst erhebt umfangreiche Daten auch über Personen, die bewusst nicht an dieser Plattform teilnehmen und generiert über diese Menschen personenbezogene Profile. Es wird angenommen, dass Facebook auch diese Daten kommerziell verwertet – ohne Zustimmung der betroffenen Nutzer. Dieses brisante Beispiel zeigt, dass bei einer Verwendung von Recommender-Systemen Fragen des Datenschutzes und des Persönlichkeitsrechts in Betracht gezogen werden sollten.

Auch die Wahrscheinlichkeit von Cyberattacken auf diese Systeme ist nicht aus der Luft gegriffen. So kann für ein Unternehmen ein wirtschaftlicher Vorteil dadurch entstehen, dass deren Produkte bevorzugt in den Trefferlisten erscheinen. Dieses Beispiel lässt sich auch negieren bzw. umdrehen, nämlich dann, wenn durch das Verwehren von Produktanzeigen in den Trefferlisten Nachteile entstehen. Eine solche Marktverzerrung ist natürlich vom Betreiber des Recommenders nicht erwünscht, weswegen auch solche Systeme gegen Angriffe geschützt werden müssen. Diese beschriebenen Szenarien sind auch ohne Programmierkenntnisse umsetzbar. Durch die Erzeugung von Fakeaccounts lässt sich bereits einiges bewirken. Drastischer ist es, wenn ein Angreifer in der Lage ist, solche Accounts automatisiert und in sehr hoher Anzahl zu erzeugen. Solch ein Fall wiederum weist auf Lösungen hin, die man dieser Problematik entgegenstellen kann. Das kann beispielweise CAPTCHA sein, eine Technik, die in Kombination mit anderen verhindert, dass automatisiert erstellte Nutzeraccounts im System angelegt werden können.

Fazit

Das Thema der Empfehlungssysteme ist natürlich viel weitreichender, eine umfassende Beschreibung im Rahmen dieses Artikels deshalb unmöglich. Dennoch hofft der Autor, mit dieser Einführung das Interesse geweckt zu haben. Es existiert mittlerweile einiges an Literatur [2], die sehr weit in die Fachdomäne eindringt. Auch die Querschnittsthemen Statistik, künstliche Intelligenz und Marketing sind jederzeit einen Ausflug wert, um ein gesamtes und abgerundetes Bild zu erhalten. Wie zu sehen war, ist die Technik der Recommender-Systeme kein kompliziertes Konstrukt, das sich nur einigen wenigen Experten erschließt. Diese Einführung versetzt Sie hoffentlich in die Lage, erste eigene Erfahrungen mit einer beliebigen Programmiersprache auf diesem Gebiet zu sammeln.

Literaturliste

[1] George F. Luger: „Künstliche Intelligenz“, Addison Wesley, 4. Auflage, 2001, ISBN: 3-8273-7002-7

[2] Francesco Ricci (Herausgeber): „Recommender Systems Handbook“, Second Edition, Springer 2015, ISBN: 1489976361

PHP Magazin

Entwickler MagazinDieser Artikel ist im PHP Magazin erschienen. Das PHP Magazin deckt ein breites Spektrum an Themen ab, die für die erfolgreiche Webentwicklung unerlässlich sind.

Natürlich können Sie das PHP Magazin über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist das Entwickler Magazin ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -