Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Tour de Force: Textanalysis

Tour de Force: Textanalysis

Talk about CRISP Datamining Process with R, ELK, Spark and LingPipe

Stefan Siprell

November 23, 2015
Tweet

More Decks by Stefan Siprell

Other Decks in Programming

Transcript

  1. 2 Motivation zum Vortrag Machine Learning ist auch nur Source

    Code Abbauen von Berührungsängsten Die Tools hierfür sind schon alle da
  2. 3 Abweichungen •  Erste Ansätze bestanden aus einfachen Textanalysis mit

    Naive Bays Implementierungen in R •  Ansätze waren OK, aber nicht befriedigend – nicht genügend Daten! •  Heute reden wir über R, Spark, LingPipe und ELK!
  3. 4 Cross Industry Standard Process for Data Mining Was möchten

    wir erreichen? Explorative Analyse der Daten, Datenqualität sichern Daten strukturieren und bereinigen Auswahl und Parametrisierung der Algorithmen Überprüfen des Modells Integration mit anderen Systemen
  4. 6 Wie kann eine Maschine das verstehen? Von welchem Verein

    handelt der Tweet? Sind die Emotionen positiv / negativ? Was sagt das über den Autor aus?
  5. 7 Wir möchten anhand des Fließtextes eine Zuordnung zu einem

    Verein realisieren, Möglichkeiten sind: •  Vereinsnamen inklusive inoffiziellen Titeln •  Spielernamen •  Dialekt •  Relevante Ereignisse Zusätzlich möchten wir die Emotionalität einer Nachricht erkennen Hier zu gibt es zwei Klassen an Algorithmen •  Document Classification •  Sentiment Detection Zwei Mechanismen für Verständnis
  6. 9 Hier gibt es grundsätzlich zwei sehr gute Tools " R

    – ist für einen geschulten Nutzer ein sehr mächtiges und schlankes Tool " ELK – Kibana erlaubt es auch für ungeschulten Nutzer einen Überblick zu erhalten Tools
  7. 10 Erstes Tool - R R ist eine Sprache /

    Laufzeit für Statische Rechnungen und Grafiken Ist einfach ideal um schnell einen Überblick über Daten zu erhalten
  8. 11 gradyear,gender,age,friends,basketball,football,soccer,softball,volleyball,swimming, cheerleading,baseball,tennis,sports,cute,sex,sexy,hot,kissed,dance,band,marching ,music,rock,god,church,jesus,bible,hair,dress,blonde,mall,shopping,clothes,holli ster,abercrombie,die,death,drunk,drugs 2006,M, 18.982,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 2006,F, 18.801,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,2,2,1,0,0,0,6,4,0,1,0,0,0,0,0,0,0,0 2006,M,

    18.335,69,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, 0 2006,F, 18.875,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 2006,NA, 18.995,10,0,0,0,0,0,0,0,0,0,0,0,1,0,0,5,1,1,0,3,0,1,0,0,0,1,0,0,0,2,0,0,0,0,0,1, 1 R - Unser Dataset Aus einem Sozialen Netzwerk wurden die 500 häufigsten Begriffe von High-School Schülerprofilen den oben genannten Kategorien zugewiesen und die Häufigkeit der Begriffe pro User gezählt.
  9. 12 Laden von Daten teens <- read.csv("~/Downloads/snsdata.csv") Ausgaben > table

    (teens$gender) F M 22054 5222 > summary(teens$age) Min. 1st Qu. Median Mean 3rd Qu. Max. NA's 3.086 16.310 17.290 17.990 18.260 106.900 5086 R – QuickOverview Ein bisschen Jung?!? Ein bisschen Alt?!? Wo sind die Jungs?
  10. 13 Bereinigen von Daten > aggregate(data = teens, age ~

    gradyear, mean, na.rm = TRUE) gradyear age 1 2006 18.65586 2 2007 17.70617 3 2008 16.76770 4 2009 15.81957 > ave_age <- ave(teens$age, teens$gradyear, FUN = function(x) mean(x, na.rm = TRUE)) > teens$age <- ifelse(is.na(teens$age), ave_age, teens$age) > summary(teens$age) Min. 1st Qu. Median Mean 3rd Qu. Max. 13.03 16.28 17.24 17.24 18.21 20.00 R – QuickOverview II Abschluss Jahr und Alter korrelieren Durchschnittsalter mit korrekten Vektorenlänge Ersetzen der fehlenden Altersangaben
  11. 14 Clustering der Daten > interests <- teens[5:40] > interests_z

    <- as.data.frame(lapply(interests, scale)) > teen_clusters <- kmeans(interests_z, 5) Wieso 5 Cluster? R – QuickOverview III
  12. 15 Bereinigen von Daten basketball football soccer softball volleyball swimming

    1 0.3427687 0.36148309 0.12406954 0.16495749 0.11129383 0.27097377 2 0.5347402 0.49217281 0.29328529 0.37835496 0.38660379 0.29699406 3 -0.1197076 0.03407084 -0.07534803 -0.01857530 -0.08231183 0.04443602 4 0.1600123 0.23641736 0.10385512 0.07232021 0.18897158 0.23970234 5 -0.1659121 -0.16399209 -0.08820562 -0.11448214 -0.11651468 -0.10635639 hollister abercrombie die death drunk drugs 1 0.16213333 0.26454350 1.71491556 0.93757803 1.901120381 2.72769246 2 -0.05574868 -0.07262787 0.03919937 0.12049381 -0.009236523 -0.06055113 3 -0.16931294 -0.14756789 -0.02295448 0.02216690 -0.086897407 -0.08524621 4 4.15218436 3.96493810 0.04347597 0.09857501 0.035614771 0.03443294 5 -0.15510547 -0.14858519 -0.09435262 -0.08324495 -0.087243227 -0.11294654 R – QuickOverview II
  13. 16 Welche 5 Cluster? R – QuickOverview III Criminal Sports,

    Sex, Sexy, Hot, Kissed, Danced, Music, Band, Die, Death, Drugs, Drunk Athlete Basketball, Football, Soccer, Softball, Volleyball, Baseball, Sports, God, Church, Jesus, Bible Princess Swimming, Cheerleading, Cute, Sexy, Hot, Dance, Dress, Hair, Mall, Hollister, Abercrombie, Shopping, Clothes Brains Band, Marching, Music, Rock Basket Case
  14. 18 Spark ist das Schweizer Taschenmesser für Big Data Spark

    kann für u.a. Folgendes genutzt werden: •  ETL – Man kann aus sehr vielen Formaten Daten einlesen und in RDBMS und NoSQL Systeme einfügen. Durch Parallelisierung auch sehr effektiv. •  SQL – Auf beliebige Datenquellen mit SQL arbeiten um Abfragen, Joins und Co abzubilden. •  R – Erlaubt den Zugriff auf Spark RDD Sätze aus R heraus •  Streaming – Man kann auch auf Streams von Daten zugreifen •  Machine Learning – Direkt in Spark kann auch mit Maschine Learning arbeiten Spark
  15. 19 Wir haben etwa 1 Mio Tweets gesammelt und möchten

    die Flat Files in Elasticsearch laden In Elasticsearch möchten wir die Daten explorativ analysieren, verarbeiten und abspeichern. Der Spark Job benötigt hierfür 47 Zeilen! Spark als Dataloader
  16. 21 try (JavaSparkContext sc = new JavaSparkContext(sparkConfig)) { ListObjectsRequest request

    = new ListObjectsRequest(); request.setBucketName(s3config.getBucketName()); request.setPrefix(s3config.getPrefix()); request.setMaxKeys(s3config.getMaxKeys()); ObjectListing objs = s3.listObjects(request); JavaRDD<String> rdd = sc.parallelize(objs.getObjectSummaries().stream().map(entry -> entry.getKey()).collect(Collectors.toList())) .flatMap(key -> FileContentLoader.loadContents(s3, s3config.getBucketName(), key)); JavaEsSpark.saveJsonToEs(rdd, "tweets/tweet"); } Lade aus 1000 Gzip Archive mit je 1000 Tweets aus S3 in Elasticsearch
  17. 24 Arten von Machine Learning – Unsupervised Learning Unsupervised Learning

    •  Erkennen von Mustern im allgemeinen Rauschen •  Es gibt keine vorgegebene Kriterien für die zu findenden Muster •  Wird in der Regel für Segmentierung von Daten und anschließender Kompression verwendet •  Beispiel Algorithmen sind: k- means, Hierarchical, etc.
  18. 25 Arten von Machine Learning – Supervised Learning Supervised Learning

    •  Trainieren anhand Features und vorbestimmten Kategorien •  Kriterien sind im Voraus definiert •  Automatisches klassifizieren von Daten nach bekannten Regeln •  Beispiel Algorithmen sind: Decision Trees, Naive Bayes, Neuronal Networks
  19. 26 Arten von Machine Learning – Reinforcement Learning Reinforcement Learning

    •  Online Training •  Erfolg oder Misserfolg muss identifizierbar sein •  Das System kann nicht erkennen warum etwas funktioniert, es weiß nur, ob es gut oder schlecht ausging. •  Meiste Konzepte basieren auf Markov Decision Process
  20. 27 Unsere Textclassifier basieren auf naive Bayes und / oder

    Support Vectoren, welche einen Trainingslauf benötigen. Daher müssen wir zunächst einen Trainingssatz bilden. Nichts leichter als das. Hierzu mappen wir die häufigsten Hashtags (Kibana) auf Vereine mit Spark und speichern die Ergebnisse wieder in Elasticsearch. Supervised Learning
  21. 28 private static String[][] clubs = new String[][] {{"FC Bayern",

    "Schweinsteiger", "BastianSchweinsteiger", "FCBayern", "BayernMünchen", "Vidal", "Bayern", "schweinsteiger", "fcbayern"}, {"BVB", "bvb", "Aubameyang", "badragaz15", "Kagawa", "Hummels", "Tuchel", "Reus", "Immobile", "Dortmund", "EchteLiebe", "BVBAsienTour15", "Mkhitaryan", "Gündogan", "Weigl", "Meyer"}, {"VfB", "vfb", "Stuttgart", "VfBimZillertal", "Rüdiger"}, {"Schalke", "schalke", "S04", "s04"}}; private static Map<String, String> aliasMapping = createMappings(); private static FilterTags filterTags = new FilterTags(); private static MapTweets mapTweets = new MapTweets(); Training Set bilden: Spark I
  22. 29 public static void main(String... args) { SparkConf sparkConfig =

    new SparkConf(); sparkConfig.setMaster("local[3]").setAppName(“Training Set Extracion"); sparkConfig.set("es.nodes", "localhost:9200"); try (JavaSparkContext sparkContext = new JavaSparkContext(sparkConfig)) { JavaRDD<Map<String, Object>> esRDD = JavaEsSpark.esRDD(sparkContext, "tweets/tweet", "? q=_exists_:entities.hashtags").values().filter(filterTags) .map(mapTweets); JavaEsSpark.saveToEs(esRDD, "trainings/training"); } } Training Set bilden: Spark Beispiel II
  23. 31 Training Lauf: LingPipe von aliasi Gutes Kommerzielles Framework (mit

    AGPL Lizenzen) für Computational Linguistics. Beispiele für den Einsatz sind: •  Topic Classification (mehr später) •  Text Korrektur •  Extraktion von relevanten Texten oder Informationen •  Sentiment Analysis (schaffen wir nicht mehr) •  Sprachenerkennung •  Zuordnung von mehrdeutigen Begriffen
  24. 32 Training Lauf: Spark public static void main(String... args) throws

    ClassNotFoundException, IOException { SparkConf sparkConfig = new SparkConf(); sparkConfig.setMaster("local[1]").setAppName(“Training Run"); sparkConfig.set("es.nodes", "localhost:9200"); try (JavaSparkContext sparkContext = new JavaSparkContext(sparkConfig)) { JavaEsSpark.esRDD(sparkContext, "trainings/training").values().foreach(classificationTrainer); } AbstractExternalizable.compileTo(classifier, new File("classifier.bin")); } private static class TrainClassification implements VoidFunction<Map<String, Object>> { @Override public void call(Map<String, Object> input) throws Exception { String club = input.get("club").toString().toLowerCase(); String text = input.get("text").toString().toLowerCase(); Classification classification = new Classification(club); Classified<CharSequence> classified = new Classified<CharSequence>(text, classification); classifier.handle(classified); } }
  25. 33 Klassifizierungslauf : Spark public static void main(String[] args) throws

    ClassNotFoundException, IOException { SparkConf sparkConfig = new SparkConf(); sparkConfig.setMaster("local[3]").setAppName(“Classification Run"); sparkConfig.set("es.nodes", "localhost:9200"); try (JavaSparkContext sparkContext = new JavaSparkContext(sparkConfig)) { JavaRDD<Map<String, Object>> esRDD = JavaEsSpark.esRDD(sparkContext, "tweets/tweet", "? q=_exists_:entities.hashtags").values().map(classifyTweets); JavaEsSpark.saveToEs(esRDD, "classifications/classification"); } } private static class ClassifyTweets implements Function<Map<String, Object>, Map<String, Object>> { @Override public Map<String, Object> call(Map<String, Object> entry) { Map<String, Object> resultMap = new HashMap<>(); resultMap.put("id", entry.get("id")); JointClassification jc = compiledClassifier.classify(entry.get("text").toString()); resultMap.put("text", entry.get("text")); resultMap.put("classification", jc.bestCategory()); resultMap.put("details", jc.toString()); return resultMap; } }
  26. 34 Klassifizierungslauf: Schöne Ergebnisse Schalke: RT @BILD_Schalke04: An den Gerüchten

    um #Huntelaar und #Farfan, die beide von #Galatasaray umworben werden soll, ist übrigens wohl nichts d… FCB: RT @PlaneteDuFoot: [#Officiel] Schweinsteiger rejoint Manchester United ! http://t.co/cX6KgCGJeb VfB: RT @Cannstatt05: "Wir lieben #Stuttgart, es gibt nur ein #Verein, wir lieben Stuttgart er muss aus #Cannstatt sein, wir lieben Stuttgart un…
  27. 35 Klassifizierungslauf: Aber auch viel Schrott •  Wir haben die

    meisten Tweets während der Bundesliga Pause gespeichert, einziges Thema: Schweinsteiger geht zu ManU •  Das hat die Ergebnisse verfälscht und viele Vereine unterpräsentiert •  Tweets hatten häufig irrelevante Inhalte wie Tickets bei Ebay oder Wasserrohrbrüchen in Vereinsheimen •  Es wurden viel zu wenige Tweets (etwa 1 Million) ausgewertet! •  Aber die Methodik ist richtig!
  28. 36 More Data The Unreasonable Effectiveness of Data •  Verwerft

    einfache Algorithmen, Akzeptiert Komplexität, Nutzt einfach mehr Daten •  http://static.googleusercontent.com/media/ research.google.com/de//pubs/archive/35179.pdf More Data, Simpler Algorithms •  Hardwarekosten sind kein Bottleneck mehr •  http://data-informed.com/why-more-data-and- simple-algorithms-beat-complex-analytics- models/
  29. 37 Daten versus Algorithmen: So sehen schlaue Algorithmen aus http://graphics.cs.cmu.edu/

    projects/scene-completion/ scene-completion.pdf Scene Completion Using Millions of Photographs
  30. 39 Ergebnis Auswertung •  Strukturiert: Anwenden der Klassifizierungen auf einen

    zweiten Data Set, um zum Beispiel eine Confusion Matrix zu berechnen •  Explorativ: Daten in Elasticsearch abspeichern, Dashboard mit Kibana bauen und explorativ auswerten (Schweinsteiger ist problematisch, oder Match Tweets in denen zwei Vereine erwähnt werden)
  31. 40 Weitere Clustering Verfahren •  Wir haben bisher nur HashTags

    genutzt, um das Training Set zu bilden •  Allerdings kann man auch temporale Cluster über Spiele bilden um noch mehr Tweets in den Training Set zu laden •  Man kann auch Followships und Retweets nutzen um weitere Korrelationen auszuwerten •  Natürlich können auch GeoIP Daten ausgewertet werden Mit Kibana kann man auch die verrücktesten Theorien schnell validieren!
  32. 42 public static void main(String... args) { // JavaStream SparkConf

    sparkConfig = new SparkConf(); sparkConfig.setMaster("local[1]").setAppName("ES Loader"); sparkConfig.set("es.nodes", "localhost:9200"); // Configre Twitter try (JavaSparkContext jsc = new JavaSparkContext(sparkConfig)) { JavaStreamingContext jstrc = new JavaStreamingContext(jsc, new Duration(1000)); TwitterUtils.createStream(jstrc).map(classifyTweets).foreachRDD(saveTweets); jstrc.start(); jstrc.awaitTermination(); } } private static class SaveTweets implements Function<JavaRDD<Map<String, Object>>, Void> { @Override public Void call(JavaRDD<Map<String, Object>> rdd) throws Exception { JavaEsSpark.saveToEs(rdd, "live/classifications"); return null; } } Stream Processing