2017-10-20 3 views
0

Ich habe eine große Anzahl von Dokumenten und ich möchte Thema Modellierung mit Text2Vec und LDA (Gibbs Sampling) tun.Text Vorverarbeitung und Topic-Modellierung mit text2vec Paket

Schritte ich brauche sind (in der Reihenfolge):

  1. Zahlen und Symbole aus dem Text entfernen

    library(stringr) 
    docs$text <- stringr::str_replace_all(docs$text,"[^[:alpha:]]", " ") 
    docs$text <- stringr::str_replace_all(docs$text,"\\s+", " ") 
    
  2. Entfernen Stoppwörter

    library(text2vec)   
    library(tm) 
    
    stopwords <- c(tm::stopwords("english"),custom_stopwords) 
    
    prep_fun <- tolower 
    tok_fun <- word_tokenizer 
    tok_fun <- word_tokenizer  
    tokens <- docs$text%>% 
         prep_fun %>% 
         tok_fun 
    it <- itoken(tokens, 
          ids = docs$id, 
          progressbar = FALSE) 
    
    v <- create_vocabulary(it, stopwords = stopwords) %>% 
        prune_vocabulary(term_count_min = 10) 
    
    vectorizer <- vocab_vectorizer(v) 
    
  3. Ersetzen Synonyme durch Begriffe

Ich habe eine Excel-Datei, in der erste Spalte ist das Hauptwort und Synonyme sind in der zweiten, dritten und ... Spalten aufgeführt. Ich möchte alle Synonyme durch Hauptwörter ersetzen (Spalte # 1). Jeder Begriff kann eine unterschiedliche Anzahl von Synonymen haben. Hier ist ein Beispiel für Code "tm" Paket mit (aber ich bin interessiert an den in text2vec Paket):

replaceSynonyms <- content_transformer(function(x, syn=NULL) 
     {Reduce(function(a,b) { 
     gsub(paste0("\\b(", paste(b$syns, collapse="|"),")\\b"), b$word,  a, perl = TRUE)}, syn, x) }) 

l <- lapply(as.data.frame(t(Synonyms), stringsAsFactors = FALSE), # 
      function(x) { 
      x <- unname(x) 
      list(word = x[1], syns = x[-1]) 
      }) 
names(l) <- paste0("list", Synonyms[, 1]) 
list2env(l, envir = .GlobalEnv) 

synonyms <- list()   
for (i in 1:length(names(l))) synonyms[i] = l[i] 

MyCorpus <- tm_map(MyCorpus, replaceSynonyms, synonyms) 
  1. Convert Begriff Matrix zu dokumentieren

    dtm <- create_dtm(it, vectorizer) 
    
  2. Nehmen LDA-Modell auf Dokument Begriff Matrix

    doc_topic_prior <- 0.1 # can be chosen based on data? 
    lda_model <- LDA$new(n_topics = 10, 
          doc_topic_prior = doc_topic_prior, topic_word_prior = 0.01) 
    doc_topic_distr <- lda_model$fit_transform(dtm, n_iter = 1000, convergence_tol <- 0.01, check_convergence_every_n = 10) 
    

MyCorpurs in Schritt 3 ist der Korpus, der unter Verwendung des "tm" -Pakets erhalten wurde. Schritt 2 und Schritt 3 arbeiten nicht zusammen, da die Ausgabe von Schritt 2 vocab ist, aber die Eingabe für Schritt 3 ist ein "tm" -Korpus.

Meine erste Frage, hier ist, wie kann ich alle Schritte mit Text2vec-Paket (und kompatible Pakete) tun, wie ich es sehr effizient fand; Danke an Dmitri Selivanow.

Zweitens: Wie stellen wir optimale Werte für Parameter in LDA in Schritt 5 ein? Ist es möglich, sie automatisch anhand von Daten zu setzen?

Dank Manuel Bickel für Korrekturen in meinem Beitrag.

Danke, Sam

Antwort

2

aktualisiert Antwort als Antwort auf Ihren Kommentar:

Erste Frage: Das Thema Synonym Ersatz wurde hier bereits beantwortet: Replace words in text2vec efficiently. Überprüfen Sie die Antwort von count insbesondere. Muster und Ersetzungen können Ngramme sein (Mehrwortphrasen). Bitte beachten Sie, dass die zweite Antwort von Dmitriy Selivanovword_tokenizer() verwendet und nicht den Fall von ngram Ersatz in der vorliegenden Form umfasst.

Gibt es einen Grund, warum Sie Synonyme vor dem Entfernen der Stoppwörter ersetzen müssen? Normalerweise sollte diese Reihenfolge keine Probleme verursachen. Oder haben Sie ein Beispiel, in dem der Wechsel der Reihenfolge zu signifikant unterschiedlichen Ergebnissen führt? Wenn Sie wirklich Synonyme nach dem Entfernen des Stoppworts ersetzen möchten, denke ich, dass Sie solche Änderungen auf das dtm anwenden müssen, wenn Sie text2vec verwenden.Wenn Sie dies tun, müssen Sie Ngrams in Ihrem dtm mit einer minimalen Ngram-Länge zulassen, die in Ihren Synonymen enthalten ist. Ich habe einen Workaround im unteren Code als eine Option zur Verfügung gestellt. Bitte beachten Sie, dass das Erlauben höherer ngrams in Ihrem dtm Rauschen erzeugt, das Ihre nachgelagerten Aufgaben beeinflussen kann oder auch nicht (Sie können wahrscheinlich den größten Teil des Rauschens im Vokabelschritt reduzieren). Daher scheint das Ersetzen von Ngrammen in früheren Versionen eine bessere Lösung zu sein.

Zweite Frage: Sie könnten das Paket überprüfen (und den Quellcode) des textmineR-Paket, das Ihnen die beste Reihe von Themen oder auch die Antwort auf diese Frage Topic models: cross validation with loglikelihood or perplexity auszuwählen hilft. Bezüglich der Handhabung von Prionen habe ich noch nicht herausgefunden, wie verschiedene Pakete, zB text2vec (WarpLDA Algorithmus), lda (Collaped Gibbs Sampling Algorithmus und andere), oder topicmodels ('Standard' Gibbs Sampling und Variationaler Erwartungs-Maximierungsalgorithmus) diese behandeln Werte im Detail. Als Ausgangspunkt können Sie sich die detaillierte Dokumentation von topicmodels ansehen, Kapitel "2.2. Schätzung" zeigt Ihnen, wie die Alpha- und Beta-Parameter geschätzt werden, die in "2.1 Modellspezifikation" definiert sind.

Zum Zweck des Lernens, bitte beachten Sie, dass Ihr Code Fehler an zwei Punkten erzeugt, die ich überarbeite: (1) Sie, da Sie die richtigen Namen für Stoppwörter in create_vocabulary(), Stoppwörtern statt stop_words, verwenden müssen definiert den Namen als solche (2) Sie brauchen nicht vocabulary =... in Ihrer lda Modelldefinition - vielleicht verwenden Sie eine ältere Version von text2vec?

library(text2vec) 
library(reshape2) 
library(stringi) 

#function proposed by @count 
mgsub <- function(pattern,replacement,x) { 
    if (length(pattern) != length(replacement)){ 
    stop("Pattern not equal to Replacment") 
    } 
    for (v in 1:length(pattern)) { 
    x <- gsub(pattern[v],replacement[v],x, perl = TRUE) 
    } 
    return(x) 
} 

docs <- c("the coffee is warm", 
      "the coffee is cold", 
      "the coffee is hot", 
      "the coffee is boiling like lava", 
      "the coffee is frozen", 
      "the coffee is perfect", 
      "the coffee is warm almost hot" 
) 

synonyms <- data.frame(mainword = c("warm", "cold") 
         ,syn1 = c("hot", "frozen") 
         ,syn2 = c("boiling like lava", "") 
         ,stringsAsFactors = FALSE) 

synonyms[synonyms == ""] <- NA 

synonyms <- reshape2::melt(synonyms 
          ,id.vars = "mainword" 
          ,value.name = "synonym" 
          ,na.rm = TRUE) 

synonyms <- synonyms[, c("mainword", "synonym")] 


prep_fun <- tolower 
tok_fun <- word_tokenizer 
tokens <- docs %>% 
    #here is where you might replace synonyms directly in the docs 
    #{ mgsub(synonyms[,"synonym"], synonyms[,"mainword"], .) } %>% 
    prep_fun %>% 
    tok_fun 
it <- itoken(tokens, 
      progressbar = FALSE) 

v <- create_vocabulary(it, 
         sep_ngram = "_", 
         ngram = c(ngram_min = 1L 
           #allow for ngrams in dtm 
           ,ngram_max = max(stri_count_fixed(unlist(synonyms), " ")) 
           ) 
) 

vectorizer <- vocab_vectorizer(v) 
dtm <- create_dtm(it, vectorizer) 

#ngrams in dtm 
colnames(dtm) 

#ensure that ngrams in synonym replacement table have the same format as ngrams in dtm 
synonyms <- apply(synonyms, 2, function(x) gsub(" ", "_", x)) 

colnames(dtm) <- mgsub(synonyms[,"synonym"], synonyms[,"mainword"], colnames(dtm)) 


#only zeros/ones in dtm since none of the docs specified in my example 
#contains duplicate terms 
dim(dtm) 
#7 24 
max(dtm) 
#1 

#workaround to aggregate colnames in dtm 
#I think there is no function `colsum` that allows grouping 
#therefore, a workaround based on rowsum 
#not elegant because you have to transpose two times, 
#convert to matrix and reconvert to sparse matrix 
dtm <- 
    Matrix::Matrix(
    t(
     rowsum(t(as.matrix(dtm)), group = colnames(dtm)) 
    ) 
    , sparse = T) 


#synonyms in columns replaced 
dim(dtm) 
#7 20 
max(dtm) 
#2 
+0

Vielen Dank für Ihre Antwort. Tatsächlich habe ich große Daten mit vielen Rechtschreibfehlern und Abkürzungen; auch verschiedene Abkürzungen für das gleiche Wort. Das Hauptwort ist nur ein Wort, aber Synonyme können Sätze wie "heißes Wasser" sein. Ich muss zuerst Stoppwörter entfernen (Schritt 2 in meiner Frage) und dann mehrere Synonyme durch das Hauptwort ersetzen. Wie kann ich diese zwei Schritte der Reihe nach durchführen, d. H. Zuerst Stopwörter entfernen und dann Synonyme ersetzen? Ich habe all meine Arbeit mit den Paketen "tm" und "topicmodels" gemacht, aber sie sind sehr langsam und ich möchte zu text2vec wechseln. –

+0

Ich erkannte, dass ein Teil Ihrer Frage bereits an anderer Stelle beantwortet wurde. Ich habe meine Antwort entsprechend aktualisiert und einen Link zu dieser Antwort eingefügt. –

+0

Danke Manuel für das Update. Das Entfernen einiger Stoppwörter vor dem Ngramm erleichtert es mir, mich auf wichtige Ngramme/Phrasen zu konzentrieren. Zum Beispiel werden "zur Arbeit zurückkehren", "am Arbeitsplatz zurückkehren", "Arbeit zurückgeben" alle durch Rückgabe ersetzt. Ich habe viele dieser Art von Phrasen. –

Verwandte Themen