Maschinelles Lernen mit Python Thomas Proisl 2015-09-16 Professur für Korpuslinguistik Überblick Ziele dieses Tutorials • Mini-Einführung in maschinelles Lernen • Problemstellungen • Lernverfahren • Vorgehensweisen • Machine learning demystified • Funktionsweise eines einfachen Klassifikationsverfahrens • Merkmalsextraktion • Bag-of-words model • DARIAH NLP-Pipeline • Maschinelles Lernen mit scikit-learn • Klassifikation • Clustering • Folien und Quellcode und Beispieldaten online verfügbar: http://www.linguistik.fau.de/~tsproisl/share/Maschinelles_ Lernen_mit_Python.zip 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 3 Maschinelles Lernen – was ist das? Maschinelles Lernen (ML) Maschinelle Lernverfahren können überall eingesetzt werden, wo „Wissen“ aus Daten gewonnen werden kann: • Spielen (Backgammon, Dame) • Erkennen gesprochener Sprache (Diktiersoftware, Komponenten in sprachgesteuerter Software) • Astronomische Strukturen klassifizieren • Kreditkartenbetrug erkennen • Zielgruppenspezifische Werbung anzeigen • Trends an den Finanzmärkten vorhersagen • Krankheiten diagnostizieren • Auto fahren (Google Self-Driving Car) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 5 ML für textuelle Daten • Maschinelle Lernverfahren operieren auf Merkmalen von Texten1 um Aussagen über die Eigenschaften von unbekannten Texten machen zu können. • Dafür werden Texte in der Regel als Vektoren quantifizierbarer Merkmale betrachtet (→ Merkmalsextraktion). Grobe Übersicht über typische Problemstellungen: • Überwachtes Lernen (supervised learning) • Klassifikation • Regression • Unüberwachtes Lernen (unsupervised learning) • Clustering • Dimensionsreduktion 1 Text: Alle textuellen Daten, vom ganzen Roman bis hin zu einzelnen Absätzen oder Sätzen 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 6 Überwachtes Lernen Wir haben annotierte Trainingsdaten und wollen weitere Daten automatisch annotieren. Klassifikation: Es handelt sich um kategorische Annotation, d.h. jeder Trainingstext ist einer Kategorie oder Klasse zugeordnet. Beispiele: Sprache, Autor, Genre Regression: Es handelt sich um numerische Annotation, d.h. jedem Trainingstext ist eine Zahl zugeordnet. Beispiele: Bewertungen, Noten, Polarität 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 7 Unüberwachtes Lernen Wir haben unannotierte Daten und wollen Strukturen darin finden. Clustering: Entdecken von Gruppen ähnlicher Texte, bspw. Texte des gleichen Autors, inhaltlich ähnliche Texte Dimensionsreduktion: Hochdimensionale Repräsentation der Texte in einen niederdimensionalen Raum projizieren, bspw. für Visualisierung, topic modelling 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 8 Vorgehensweise bei überwachtem Lernen 1. Daten sammeln und annotieren 2. Daten in ein Trainingsset und ein Testset aufteilen 3. Quantifizierbare Merkmale aus Daten extrahieren 4. Abhängig von Art der Annotation, Anzahl der Merkmale und Menge der Trainingsdaten ein Lernverfahren auswählen 5. Lernverfahren auf Trainingsdaten trainieren (lernen); Ergebnis: Modell 6. Modell auf Testset anwenden und prognostizierte Annotation mit tatsächlicher Annotation vergleichen (evaluieren) 7. Modell auf unbekannte Daten anwenden Anstelle von Trainings- und Testset kann auch Kreuzvalidierung verwendet werden. 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 9 Vorgehensweise bei Clustering 1. Daten sammeln 2. Quantifizierbare Merkmale aus Daten extrahieren 3. Abhängig von Eigenschaften des gewünschten Clusterings, Anzahl der Merkmale und Menge der Trainingsdaten ein Clusteringverfahren auswählen 4. Daten clustern; Ergebnis: Clustering und Modell 5. Optional: Modell auf unbekannte Daten anwenden Evaluation: Clustern von annotierten Daten 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 10 Welche Art von Lernverfahren eignet sich für welches der folgende Szenarien? • Wir haben eine Menge von Filmrezensionen, die eine Gesamtbewertung des Films mit einer Schulnote zwischen 1 und 6 enthalten. Wir möchten eine Sammlung alter Filmrezensionen automatisch mit einer solchen Gesamtbewertung versehen. • Wir möchten automatisch erkennen, ob es sich bei einer E-Mail um Spam handelt. • Bei einer Mitarbeiterumfrage wird in einem Freitextfeld nach dem Kantinenessen gefragt. Wir möchten automatisch die Zufriedenheit der Mitarbeiter erkennen. • Wir möchten den wahren Autor eines unter Pseudonym geschriebenen Romans herausfinden. 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 11 Scikit-learn cheat-sheet 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 12 Naive Bayes: Ein sehr einfacher Klassifikator Bedingte Wahrscheinlichkeiten und der Satz von Bayes (1) Spam • Wir haben 75 Emails • 30 von 75 Mails sind Spam als markiert • 50 von 75 Mails enthalten das Wort „Viagra“ • 20 Mails, die das Wort „Viagra“ enthalten, sind als Spam markiert Viagra • Frage: Wie hoch ist die Wahrscheinlichkeit, dass eine neue Mail, die das Wort „Viagra“ enthält, eine Spammail ist? P (A|B ) = 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python P (A ∩ B ) P (B |A)P (A) = P (B ) P (B ) 14 Bedingte Wahrscheinlichkeiten und der Satz von Bayes (2) • Antwort: P (Viagra|Spam) · P (Spam) P (Viagra) 20 30 · 30 75 = 50 75 20 = 50 = 0.4 • Wir schätzen die Wahrscheinlichkeiten aus den Daten (relative Häufigkeiten). • Simples Beispiel, für das wir den Satz von Bayes eigentlich noch nicht gebraucht hätten. P (Spam|Viagra) = 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 15 Bedingte Wahrscheinlichkeiten und der Satz von Bayes (3) • Je mehr Wörter wir betrachten (= Merkmale), desto komplexere bedingte Wahrscheinlichkeiten müssen wir abschätzen: P (Spam|Viagra) = P (Spam|Viagra, Sex) = P (Spam|Viagra, Sex, Penis) = P (Viagra|Spam)P (Spam) P (Viagra) P (Sex|Spam, Viagra)P (Viagra|Spam)P (Spam) P (Sex|Viagra)P (Viagra) P (Penis|Spam, Viagra, Sex)P (Sex|Spam, Viagra)P (Viagra|Spam)P (Spam) P (Penis|Viagra, Sex)P (Sex|Viagra)P (Viagra) • Jedes zusätzliche Wort steigert die Komplexität der Berechnung. 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 16 Naive-Bayes-Annahme • Vereinfachende Annahme (Naive-Bayes-Annahme): Vorkommen von Wörtern sind vollkommen unabhängig voneinander. • Berechnung wird einfacher: P (Viagra|Spam)P (Sex|Spam)P (Penis|Spam) P (Spam|Viagra, Sex, Penis) = P (Viagra)P (Sex)P (Penis) • Zum Abschätzen der Wahrscheinlichkeiten müssen wir nur Worthäufigkeiten in Klassen bestimmen. • Annahme ist zwar offensichtlich falsch, darauf aufbauende Klassifikation funktioniert aber überraschend gut. 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 17 Naive-Bayes-Klassifikator • Grundlegende Idee: Wir ordnen einen Text der wahrscheinlichsten Kategorie zu: P (Spam|Viagra, Sex, Penis) = P (Viagra|Spam)P (Sex|Spam)P (Penis|Spam) P (Viagra)P (Sex)P (Penis) P (Ham|Viagra, Sex, Penis) = P (Viagra|Ham)P (Sex|Ham)P (Penis|Ham) P (Viagra)P (Sex)P (Penis) • Nenner ist für alle Kategorien gleich und kann weggelassen werden. • Naive-Bayes-Klassifikator verwendet die Wörter eines Textes. • Für jede mögliche Kategorie: Multiplikation der relativen Häufigkeiten dieser Wörter in den Trainingsdaten • Zuordnung der Kategorie mit dem höchsten Wert • „Lernen“ ist die Abschätzung der bedingten Wahrscheinlichkeiten aus den Trainingsdaten 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 18 Merkmalsextraktion Das Bag-of-words-Modell (1) • Maschinelle Lernverfahren operieren in der Regel auf Vektoren von numerischen Merkmalen. • Wir müssen unsere Texte also durch quantifizierbare Merkmale repräsentieren. • Einfachste Methode ist das Bag-of-words-Modell: • Annahme: Ein Text ist eine ungeordnete Menge von Wörtern, d.h. genaue Position oder Reihenfolge der Wörter kann vernachlässigt werden. • Ausschlaggebend ist nur die Häufigkeit der Wörter. • Text wird auf seine Frequenzliste reduziert. Beispiel 1 Der Satz „Rose is a rose is a rose is a rose“ wird, unter Vernachlässigung der Groß-/Kleinschreibung, so dargestellt: {"a": 3, "is": 3, "rose": 4} 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 20 Das Bag-of-words-Modell (2) • Die Sätze „Der Hund beißt den Mann“ und „Der Mann beißt den Hund“ sind für das Bag-of-words-Modell identisch. • Einfache Erweiterung, die ein klein wenig Syntax in das Modell bringt: Verwendung von N-Grammen. Beispiel 3 Durch Hinzunahme von Bigrammen können die beiden Sätze unterschieden werden: {"beißt": 1, "der hund": {"beißt": 1, "der mann": 2015-09-16 "den": 1, "der": 1, "hund beißt": "den": 1, "der": 1, "mann beißt": | Thomas Proisl | Professur für Korpuslinguistik | 1, 1, 1, 1, "hund": 1, "mann": 1, "beißt den": 1, "den mann": 1} "hund": 1, "mann": 1, "beißt den": 1, "den hund": 1} Maschinelles Lernen mit Python 21 Wie kann der Output der DARIAH NLP-Pipeline integriert werden? Annotationsebenen: • Segmentierung: • Absätze • Sätze • Tokens • Linguistische Annotation: • • • • • • Lemmata Part-of-Speech-Tags und vereinfachte POS-Tags Morphologie: Kasus, Numerus, Genus, Person, . . . Dependenzstruktur Named Entities Konstituentenstruktur 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 22 Ein paar Ideen • Lemmata anstatt oder zusätzlich zu Tokens • Filtern nach POS-Tag (bspw. nur Inhaltswörter) • Häufigkeiten von POS-Tags • Häufigkeiten von Named Entities • Häufigkeiten von bestimmten morphologischen Informationen, bspw. für Verben Person und Numerus, Tempus • Kombination von Lemma und vereinfachtem POS-Tag: „der_ART“, „hund_NN“, „beißen_V“, „der_ART“, „mann_NN“ • Kombination von bestimmten Lemmata mit bestimmten morphologischen Informationen, bspw. Numerus für alle Substantive: „mann_sg“ • Über Dependenzrelation verbundene Tokens an Stelle von Bigrammen: „hund der“, „beißt hund“, „beißt mann“, „mann den“ • Optional mit Label: „NK(hund, der)“, „SB(beißt, hund)“, „OA(beißt, mann)“, „OA(mann, den)“ 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 23 Weitere einfach zu extrahierende Merkmale • Häufigkeiten von bestimmten Interpunktionszeichen (!?) • Häufigkeit von wörtlicher Rede • Durchschnittliche Satz- und Absatzlänge • Type-Token-Verhältnis • Verhältnis von Interpunktionszeichen zu Wörtern 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 24 Maschinelles Lernen mit scikit-learn Installation • Installationsanweisungen unter http://scikit-learn.org/stable/install.html, bspw.: pip install -U numpy scipy scikit-learn 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 26 Datenorganisation • Für unsere Beispiele: Alle Texte einer Klasse in einem Unterverzeichnis; Verzeichnisname = Klassenname; Dateiname egal Daten/ |-- Klasse_1 | |-- 01.txt | |-- 02.txt | ‘-- 03.txt |-- Klasse_2 | |-- 04.txt | |-- 05.txt | ‘-- 06.txt |-- Klasse_3 | |-- 07.txt | |-- 08.txt 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 27 Unser Spielzeugdatenset • Je acht Romane von sechs verschiedenen Autoren • Plaintext (8x6) • Ausgabe der DARIAH NLP-Pipeline (8x6_output) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 28 Laden der Daten • Datenset laden, dabei Kodierung richtig angeben: from sklearn.datasets import load_files corpus = load_files("data/8x6", encoding="utf-8") • corpus ist ein „Bunch“, eine Menge von Datenfeldern: • • • • filenames: Liste der Dateinamen (reproduzierbar gemischt) data: Liste von Strings mit den Dateiinhalten target_names: Liste der Namen aller Klassen target: Liste der den Dateien zugeordneten Klassen • Liste der Felder: print(corpus.keys()) • Kann als Dictionary oder als Objekt angesprochen werden: print(corpus["target_names"]) print(corpus.target) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 29 Aufteilung in Trainings- und Testset • Reproduzierbare Aufteilung in ein Trainings- und Testset • n_iter: Anzahl der verschiedenen Aufteilungen; wir wollen nur eine • test_size: Welcher Anteil der Daten soll zum Testen verwendet werden (50%) • random_state: Wenn nicht None ist die Aufteilung reproduzierbar from sklearn.cross_validation import StratifiedShuffleSplit sss = StratifiedShuffleSplit(corpus.target, n_iter=1, test_size=0.5, random_state=0) • sss ist ein Iterator, uns interessiert nur die erste mögliche Aufteilung: train_index, test_index = list(sss)[0] • data und target aufteilen (corpus.target ist ein numpy Array): data_train = [corpus.data[_] for _ in train_index] data_test = [corpus.data[_] for _ in test_index] target_train = corpus.target[train_index] target_test = corpus.target[test_index] 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 30 Merkmalsextraktion • Tokenisierung und Bag-of-words-Modell from sklearn.feature_extraction.text import CountVectorizer count_vect = CountVectorizer() data_train_counts = count_vect.fit_transform(data_train) • Relative statt absolute Häufigkeiten (term-frequencies) • norm="l1": Termfrequenzen summieren sich zu 1 • norm="l2": Dokumentvektor hat die euklidische Länge 1 (Standardwert) from sklearn.feature_extraction.text import TfidfTransformer tfidf_transformer = TfidfTransformer(norm="l2", use_idf=False) data_train_tfidf = tfidf_transformer.fit_transform(data_train_counts) • Testdaten transformieren (transform() statt fit_transform()!) data_test_counts = count_vect.transform(data_test) data_test_tfidf = tfidf_transformer.transform(data_test_counts) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 31 Tf-Idf • Abkürzung für term frequency-inverse document frequency • tf : Häufigkeit eines Wortes in einem Text • df : In wie vielen Texten kommt ein Wort vor • idf = Anzahldf Texte • Intuition: Ein Wort ist wichtig für einen Text, wenn es in diesem Text oft vorkommt (hohe tf ), und unwichtig, wenn es selten vorkommt (niedrige tf . Ein Wort ist wichtig (spezifisch), wenn es in wenigen Texten vorkommt (hohe idf ), und unwichtig wenn es in vielen verschiedenen oder allen Texten vorkommt (niedrige idf ). • Multiplikation von tf und idf 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 32 Klassifikator trainieren und evaluieren • Naive-Bayes-Klassifikator trainieren: from sklearn.naive_bayes import MultinomialNB clf = MultinomialNB() clf.fit(data_train_tfidf, target_train) • Testdaten klassifizieren: predicted = clf.predict(data_test_tfidf) • Ergebnis evaluieren: from sklearn import metrics print(metrics.accuracy_score(target_test, predicted)) print(metrics.classification_report(target_test, predicted, target_names=corpus.target_names)) print(metrics.confusion_matrix(target_test, predicted)) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 33 Schnittstellen sind immer gleich • fit(): Modell wird angepasst • transform(): Modell wird auf Daten angewandt • fit_transform(): Kombination von fit() und transform() • predict(): Anstelle von transform() bei Lernern 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 34 Pipelines Pipelines • Mit Pipelines können mehrere Verarbeitungsschritte einfach kombiniert werden. • Pipeline konfigurieren: text_clf = Pipeline([(’vect’, CountVectorizer()), (’tfidf’, TfidfTransformer(norm="l2", use_idf=False)), (’clf’, MultinomialNB()), ]) • Pipeline trainieren: text_clf.fit(data_train, target_train) • Testdaten klassifizieren: predicted = text_clf.predict(data_test) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 36 Komponenten hinzufügen und austauschen • Einzelne Komponenten können dank einheitlicher Schnittstellen leicht hinzugefügt oder ausgetauscht werden. • Naive Bayes kommt nicht gut mit extrem vielen Merkmalen zurecht, Beschränkung auf 200 beste Merkmale: text_clf = Pipeline([(’vect’, CountVectorizer()), (’tfidf’, TfidfTransformer(norm="l2", use_idf=False)), (’kbest’, SelectKBest(chi2, k=200)), (’clf’, MultinomialNB()), ]) • SVMs kommen gut mit sehr vielen Merkmalen zurecht: Verwenden von Uni- und Bigrammen, lineare Support Vector Machine: from sklearn.svm import LinearSVC text_clf = Pipeline([(’vect’, CountVectorizer(ngram_range=(1, 2))), (’tfidf’, TfidfTransformer(norm="l2", use_idf=False)), (’clf’, LinearSVC()), ]) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 37 Verwendung der DARIAH NLP-Pipeline • Das Ausgabeformat muss geparst werden: class DARIAHAnnotationExtractor(BaseEstimator, TransformerMixin): """Convert tab-separated values with header line to dict of columns""" def fit(self, x, y=None): return self def transform(self, texts): features = collections.defaultdict(list) for text in texts: # parse tsv format (list of rows) table = [[c for c in r.split("\t")] for r in text.splitlines()] # extract header line header = table[0] # convert to list of columns columns = list(zip(*table[1:])) # store in dict for name, column in zip(header, columns): features[name].append(column) return features 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 38 Kombination von Merkmalen • Verwendung von beliebigen Tupeln von Merkmalen (auch 1-Tupel): class FeatureCombiner(BaseEstimator, TransformerMixin): """Convert to dictionary of feature tuples""" def __init__(self, keys=[]): self.keys = keys def fit(self, x, y=None): return self def transform(self, data_dict): # extract desired columns (features) columns = [data_dict[k] for k in self.keys] # combine features into tuples return [collections.Counter(zip(*text)) for text in zip(*columns)] 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 39 Beispielpipelines • Bag-of-words-Modell mit Tokens: text_clf = Pipeline([(’extractor’, DARIAHAnnotationExtractor()), (’combiner’, FeatureCombiner(["Token"])), (’vect’, DictVectorizer()), (’tfidf’, TfidfTransformer()), (’clf’, LinearSVC()), ]) • Hier mit (Lemma, CPOS)-Tupeln (Kombination von Lemma und CPOS in ein einziges Merkmal): text_clf = Pipeline([(’extractor’, DARIAHAnnotationExtractor()), (’combiner’, FeatureCombiner(["Lemma", "CPOS"])), (’vect’, DictVectorizer()), (’tfidf’, TfidfTransformer()), (’clf’, LinearSVC()), ]) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 40 FeatureUnion (1) • FeatureUnion kombiniert mehrere unabhängige Transformer in einen • Transformer werden unabhängig voneinander ausgeführt, Ausgabe wird konkateniert 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 41 FeatureUnion (2) text_clf = Pipeline([(’extractor’, DARIAHAnnotationExtractor()), (’union’, FeatureUnion( transformer_list=[ # Bag-of-words-Modell (’bow’, Pipeline([ (’combiner’, FeatureCombiner(["Lemma", "CPOS"])), (’vect’, DictVectorizer()), (’tfidf’, TfidfTransformer()), ])), # POS-Tags (’bopos’, Pipeline([ (’combiner’, FeatureCombiner(["POS"])), (’vect’, DictVectorizer()), (’tfidf’, TfidfTransformer(use_idf=False)), ])), ])), (’normalizer’, Normalizer()), (’clf’, LinearSVC()), ]) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 42 Verwendung von Dependenzrelationen (1) • Wir wollen Tripel bestehend aus Dependenzrelation, Governor und Dependent • Eigene Transformer-Klasse erstellen: class DependencyTupleCombiner(BaseEstimator, TransformerMixin): """Convert to dictionary of (relation, governor, dependent) tuples""" def __init__(self, lemma=True): self.lemma = lemma def fit(self, x, y=None): return self 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 43 Verwendung von Dependenzrelationen (2) • Fortsetzung: def transform(self, data_dict): features = [] # use tokens or lemmata lemma_or_token = "Lemma" if self.lemma else "Token" # extract necessary columns columns = [data_dict[k] for k in ["TokenId", lemma_or_token, "DependencyHead", "DependencyRelation"]] for text in zip(*columns): # convert to rows rows = list(zip(*text)) # do some arithmetic and extract token/lemma for DependencyHead dependency_tuples = [(r[3], rows[i + (int(r[2]) - int(r[0]))][1], r[1]) for i, r in enumerate(rows) if r[2] != "_"] features.append(collections.Counter(dependency_tuples)) return features 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 44 Clustering k-Means (1) • Daten müssen nur geladen werden, Aufteilung in Trainings- und Testset nicht zwingend nötig: corpus = load_files("data/8x6_output", encoding="utf-8") • Anstelle eines Klassifikators kann ein Clusterverfahren in die Pipeline eingebunden werden, bspw. k-Means. • k-Means teilt die Daten in k Gruppen auf, d.h. Anzahl der Cluster muss vorher bekannt sein (oder durch Probieren gefunden werden). 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 46 k-Means (2) text_clst = Pipeline([(’extractor’, DARIAHAnnotationExtractor()), (’union’, FeatureUnion( transformer_list=[ # Bag-of-words-Modell (’bow’, Pipeline([ (’combiner’, FeatureCombiner(["Lemma", "CPOS"])), (’vect’, DictVectorizer()), (’tfidf’, TfidfTransformer()), ])), # POS-Tags (’bopos’, Pipeline([ (’combiner’, FeatureCombiner(["POS"])), (’vect’, DictVectorizer()), (’tfidf’, TfidfTransformer(use_idf=False)), ])), ])), (’normalizer’, Normalizer()), (’clst’, KMeans(n_clusters=6)) ]) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 47 Hierarchisches Clustering • Anfangs ist jeder Text in einem eigenen Cluster. • Schrittweise werden die ähnlichsten Cluster verschmolzen. • Verschiedene Ähnlichkeitsmaße möglich. • Implementierung in scikit-learn verlangt vorgegebene Anzahl Cluster (scipy.cluster.hierarchy kann auch explorativ verwendet werden). • AgglomerativeClustering() 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 48 Delta-Maße • Auswahl der n häufigsten Wörter, Skalierung ($z$-Werte), optional Normalisierung, Abstandsmaß • Burrows’s Delta: Keine Normalisierung, Manhattan-Distanz • Burrows’s Delta mit Vektornormalisierung: L1-Normalisierung, Manhattan-Distanz • Cosine Delta: Keine Normalisierung, Cosinus-Distanz AgglomerativeClustering(n_clusters=6, affinity="cosine", linkage="complete") 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 49 Visualisierung mit matplotlib (1) 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 50 Visualisierung mit matplotlib (2) • Zweidimensionale Repräsentation der Daten durch Multidimensional Scaling (MDS); MDS versucht euklidische Abstände beizubehalten: from sklearn import manifold twodim = manifold.MDS().fit_transform(data) • Daten plotten; Farben markieren Cluster, Beschriftungen tatsächliche Klassen: import matplotlib.pyplot as plt fig, ax = plt.subplots() ax.scatter(twodim[:, 0], twodim[:, 1], c=clusters) for i, target in enumerate(corpus.target): ax.annotate(corpus.target_names[target].split(",")[0], (twodim[:, 0][i], twodim[:, 1][i]), fontsize="small") plt.savefig("clustering.png") 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 51 Weitere Features von scikit-learn Features • Merkmalsextraktion: CountVectorizer kann weitreichend konfiguriert werden • Merkmalsauswahl: Varianz, rekursive Merkmalseliminierung, Merkmalsauswahl mit Hilfe linearer Modelle (bspw. lineare SVM) • Dimensionsreduktion: Hauptkomponentenanalyse (PCA), Manifold Learning • Weitere überwachte Lernverfahren: Generalisierte lineare Modelle, Diskriminanzanalyse, SVMs mit verschiedenen Kerneln, Nearest Neighbors, Entscheidungsbäume, . . . • Ensemble-Methoden um mehrere überwachte Modelle zu kombinieren, bspw. Random Forests • Kreuzvalidierung • Parameter Tuning: Systematisches Durchprobieren von Parameterkombinationen mit GridSearchCV 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 53 Andere interessante Module • gensim für Topic Modelling: Latent Semantic Indexing, Latent Dirichlet Allocation, Hierarchical Dirichlet Processes, Deep Learning (word2vec, paragraph2vec) • matplotlib für die Visualisierung • PyStruct für strukturiertes Lernen • seqlearn für Sequenzklassifikation 2015-09-16 | Thomas Proisl | Professur für Korpuslinguistik | Maschinelles Lernen mit Python 54