Alle Worte sind gleich?! Natürlich nicht: Manche Worte sind ungleicher in dem Sinne, dass sie stärker bedeutungstragend sind als andere und den semantischen Gehalt eines Textes ausmachen. Doch wie identifiziert man das inhaltlich interessante und relevante Vokabular eines Subkorpus?
Die bloße Häufigkeit von Worten ist bei dieser Frage ein schlechter Ratgeber. Allerweltsworte ("haben", "machen", "ist", "der", "die", "das" etc.) treten weit häufiger auf als jenes Vokabular, das tatsächlich den Inhalt eines Textes ausmacht.
Im 'Text Mining' ist es vor diesem Hintergrund gängig, Allerweltsvokabular auf Stopwort-Listen zu setzen und dieses von vornherein von der Analyse auszuschließen. Es gibt etwa eine Vielzahl von Beispielen von Wortwolken, welche die bloße Zählung der Häufigkeiten von Worten eines Textes darstellen, nachdem eine Stopwort-Liste als Filter verwendet wurde.
Die undifferenzierte Anwendung von Stopwort-Listen im Rasenmäher-Stil kann jedoch zu ungewollten Informationsverlusten führen. Ein Beispiel: Die Pronomen "wir" und die Anrede "Sie", die stets auf Stopwort-Listen stehen (z.B. tm::stopwords("de")
) haben im Rollenspiel zwischen Regierungs- und Oppositionsfraktionen eine wichtige Bedeutung. Je nach Anwendungsszenario kann es schlecht begründet sein, diese Worte mit dem Rasenmäher zu eliminieren.
In der Korpuslinguistik wurden inhaltlich besser begründete statistische Verfahren entwickelt, um das statistisch signifikante Vokabular eines (Sub-)Korpus zu ermitteln. Die Grundfrage ist dabei: Welche Worte treten in einem Untersuchtungskorpus ("corpus of interest" /coi) im Vergleich zu einem Referenzkorpus (ref) überzufällig oft auf?
Diese Grundüberlegung findet in verschiedenen Domänen Anwendung
Im Feld des Machine Learning wird auch von feature extraction gesprochen: Die features eines Textes machen diesen unterscheidbar von anderen.
Die Rede von den features eines Textes (oder eines Sub-Korpus) erscheint als die allgemeinste Weise, die hervorstechenden Merkmale zu bezeichnen, die in der Analyse besonders zu beachten sind. Daher ist die Methode des polmineR-Pakets, die zur Keyword-/Term-/Feature-Extraktion zur Verfügung steht, als features()
-Methode bezeichnet.
library(polmineR)
for (pkg in c("magrittr", "data.table", "RColorBrewer", "tm", "wordcloud")){ if (!pkg %in% rownames(installed.packages())) install.packages(pkg) library(package = pkg, character.only = TRUE) }
Statistische Verfahren der Feature-Extraktion (vgl. z.B. Manning / Schuetze 2003) beruhen auf dem Vergleich des Auftretens eines Worts (oder einer lexikalischen Einheit) in einem (Sub-)Korpus (coi) im Vergleich zu einem Referenzkorpus (ref). D. h. die Zählung der Häufigkeiten in Unterschungs- und Referenzkorpus steht am Anfang des Verfahrens.
Die zentrale Frage des an den Häufigkeiten ansetzenden Unterschiedstests ist, ob bestimmte Worte im Untersuchungskorpus überzufällig oft auftreten. Diese Logik eines statistischen Unterschiedstests findet auch bei der Berechnungen von Kookkurrenzen Anwendung. Während aber bei der Kookkurrenzanalyse Log-Likelihood-Tests gängig sind, die auch bei seltener auftretenden Worten noch robust bleiben, wird bei der Feature-Extraktion oft auch mit dem etwas einfacheren Chi-Quadrat-Test gearbeitet.
Die features()
-Methode beinhaltet keinen voreingestellten Filter nach der Auftretenshäufigkeit, damit NutzerInnen sich über Selektionsschritte im Klaren bleiben. Es wird in aller Regel immer erforderlich sein, selten auftretendes Vokabular mit der subset()
-Methode aus der Analyse auszuschließen.
Die Zahl der statistisch signifikanten Worte ist in hohem Maße abhängig von der Größe des Untersuchungskorpus. Wie bei Kookkurrenz-Analysen wird die Anwendung weiterer Filter- und Reduktionskriterien oftmals relevant sein.
Im ersten Beispiel wollen wir die herausstechenden Themen der parlamentarischen Debatte von 2015/2016 im Vergleich zu den Vorjahren ermitteln.
Als "corpus of interest" (coi) legen wir zunächst eine partition
für 2015/16 an, wobei wir Zwischenrufe aus der Analyse ausschließen.
coi <- partition("GERMAPARL", year = 2016, interjection = FALSE)
ref <- partition("GERMAPARL", year = 2002:2015, interjection = FALSE)
enrich()
-Methode.coi <- enrich(coi, p_attribute = "word") ref <- enrich(ref, p_attribute = "word")
partition()
und der Anreicherung mit enrich()
kann auch etwas kompakter als "Pipe" gestaltet werden:coi <- partition("GERMAPARL", year = 2016, interjection = FALSE) %>% enrich(p_attribute = "word")
p_attribute
direkt beim Aufruf von partition()
anzugeben und also gleich "in einem" Rutsch die Zählung durchzuführen.coi <- partition("GERMAPARL", year = 2016, interjection = FALSE, p_attribute = "word") ref <- partition("GERMAPARL", year = 2002:2015, interjection = FALSE, p_attribute = "word")
partition
-Objekte auch count
-Objekte sehen. Das sehen Sie wie folgt.is(coi)
features()
-Methode.f <- polmineR::features(coi, ref)
features
-Objekt können generische-Methoden wie as.data.frame()
, dim()
, nrow()
, ncol()
, colnames()
etc. angewandt werden. Über die nrow()
-Methode verschaffen wir uns einen Eindruck, wie viele Zeilen eigentlich die Tabelle hat.nrow(f)
f <- subset(f, count_coi >= 5) %>% subset(chisquare >= 10.83)
f
options("polmineR.pagelength" = 5L)
terms_to_drop <- c(tm::stopwords("de"), "--", "``", "[", "]", "2016", "2017", "2015", "Vielen", "Dank") subset(f, !word %in% terms_to_drop)
partition()
die count()
-Methode an und nehmen eine Zählung über zwei positionale Attribute ("word" und "pos") vor.coi <- partition("GERMAPARL", year = 2016, interjection = FALSE) %>% count(p_attribute = c("word", "pos")) ref <- partition("GERMAPARL", year = 2002:2015, interjection = FALSE) %>% count(p_attribute = c("word", "pos"))
f <- polmineR::features(coi, ref) %>% subset(count_coi >= 5) %>% subset(chisquare >= 10.83)
f <- subset(f, pos == "NN")
options("polmineR.pagelength" = 10L) f
Wir möchten nun noch auf ein besonderes Szenario hinweisen, das relevant ist, wenn das Untersuchungskorpus Teil des Referenzkorpus ist. Dann ist es erforderlich, das Argument included
auf TRUE
zu setzen, so dass von der Zählung der Worte im Referenzkorpus die Häufigkeiten im Untersuchungskorpus abgezogen werden.
Als Beispiel nehmen wir die Reden von Angela Merkel in 2008, dem Jahr der Finanzmarktkrise unter die Lupe. Wir vergleichen diese mit allen anderen Reden im Bundestag, um die Schwerpunktsetzungen der Bundeskanzlerin in Erfahrung zu bringen.
merkel <- partition("GERMAPARL", speaker = "Angela Merkel", year = 2008:2009, interjection = FALSE) %>% count(p_attribute = c("word", "pos")) bt <- partition("GERMAPARL", year = 2008:2009, interjection = FALSE) %>% count(p_attribute = c("word", "pos"))
features()
-Methode setzen wir das Argument included
auf TRUE
. am_features <- polmineR::features(merkel, bt, included = TRUE)
am_features_min <- am_features %>% subset(count_coi >= 5) %>% subset(chisquare >= 10.83) %>% subset(pos %in% c("NN", "ADJA", "VVFIN"))
wordcloud::wordcloud( words = am_features_min[["word"]][1:50], freq = am_features_min[["count_coi"]][1:59], colors = rep(RColorBrewer::brewer.pal(8, "Dark2"), times = 7), random.color = TRUE )
wordcloud::wordcloud( words = am_features_min[["word"]][1:50], freq = am_features_min[["count_coi"]][1:59], colors = rep(RColorBrewer::brewer.pal(8, "Dark2"), times = 7), random.color = TRUE )
am_features_min
options("polmineR.pagelength" = 5L)
Die Extraktion von features beruht auf dem Vergleich von Häufigkeiten. Dabei sind es natürlich nicht nur die Häufigkeiten einzelner Worte, die verglichen werden können, sondern auch die von Mehrwort-Einheiten.
Auch das Ergebnis einer Zählung von N-Grammen mit der ngrams()
-Methode führt zu einem Objekt mit Zählungen, und auch hier können wir features bestimmen.
merkel_ngrams <- partition("GERMAPARL", speaker = "Angela Merkel", year = 2008:2009, interjection = FALSE) %>% polmineR::ngrams(n = 2, p_attribute = "word")
bt_ngrams <- partition("GERMAPARL", year = 2008:2009, interjection = FALSE) %>% polmineR::ngrams(n = 2, p_attribute = "word")
significant_mwes <- polmineR::features(merkel_ngrams, bt_ngrams, included = TRUE) %>% subset(count_coi >= 5) %>% subset(chisquare >= 10.83) DT::datatable(significant_mwes@stat, options = list(dom = "ftip"))
options("polmineR.pagelength" = 10L)
significant_mwes <- polmineR::features(merkel_ngrams, bt_ngrams, included = TRUE) %>% subset(count_coi >= 5) %>% subset(chisquare >= 10.83) DT::datatable(significant_mwes@stat, options = list(dom = "ftip"))
merkel_ngrams <- partition("GERMAPARL", speaker = "Angela Merkel", lp = 17, interjection = FALSE) %>% polmineR::ngrams(n = 2, p_attribute = c("word", "pos")) bt_ngrams <- partition("GERMAPARL", lp = 17, interjection = FALSE) %>% polmineR::ngrams(n = 2, p_attribute = c("word", "pos"))
data.table
-Objekt um, das wir noch ein wenig formatieren.dt <- polmineR::features(merkel_ngrams, bt_ngrams, included = TRUE) %>% data.table::as.data.table() dt <- subset(dt, dt[["pos_1"]] == "ADJA") %>% subset(.[["pos_2"]] == "NN") dt[,"pos_1" := NULL][,"pos_2" := NULL][,"exp_coi" := round(exp_coi, 2)][, "chisquare" := round(chisquare, 2)]
DT::datatable(dt)
cdu_ngrams <- partition("GERMAPARL", party = "CDU", lp = 17, interjection = FALSE) %>% polmineR::ngrams(n = 3, p_attribute = c("word", "pos")) non_cdu_ngrams <- partition("GERMAPARL", party = c("SPD", "FDP", "LINKE", "GRUENE"), lp = 17, interjection = FALSE) %>% polmineR::ngrams(n = 3, p_attribute = c("word", "pos")) cdu_ngrams <- subset(cdu_ngrams, count >= 5) # vorgezogen f <- polmineR::features(cdu_ngrams, non_cdu_ngrams, included = FALSE) f <- subset(f, chisquare >= 10.83)
data.table
-Objekt um und machen uns ans Filtern. dt <- data.table::as.data.table(f) dt <- subset(dt, dt[["pos_1"]] == "NN") %>% subset(.[["pos_2"]] == "ART") %>% subset(.[["pos_3"]] == "NN")
dt[, "pos_1" := NULL][, "pos_2" := NULL][, "pos_3" := NULL] dt[, "exp_coi" := round(exp_coi, 2)][, "chisquare" := round(chisquare, 2)] DT::datatable(dt)
Verfahren der feature-Extraktion, die im polmineR-Paket mit der features()
-Methode implementiert sind, können für eine Reihe von Zwecken eingesetzt werden:
Als Verfahren zur Schlagwort-Berechnung kann effizient das semantisch tragende Vokabular extrahiert werden, so dass effizient zentrale Begriffe des Diskurses erkannt werden können.
Wenn man dem Vergleich ein thematisch definiertes Subkorpus zugrunde legt, lässt sich das semantische Feld des Themenbereichs bestimmen. Dies kann etwa der Ansatzpunkt für die Entwicklung von Diktionären sein.
Die Ermittlung statistisch signifikanten Vokabulars kann auch für Zwecke der Bestimmung von features genutzt werden, auf die Zählungen oder andere textstatistische Maße eingeschränkt werden, so dass Speicherplatz geschont und die Qualität von Ergebnissen verbessert wird.
Insgesamt sind die geschilderten Verfahren ein flexibles wie effizientes Instrument, um effizient in Sachen Vokabular Wichtiges von Unwichtigem zu unterscheiden.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.