Ich frage mich, wie sich die Ergebnisse verschiedener Pakete, also Algorithmen, unterscheiden und ob Parameter so gesetzt werden könnten, dass ähnliche Themen entstehen. Ich habe mir insbesondere die Pakete text2vec
und topicmodels
angeschaut.Können text2vec und topicmodells ähnliche Themen mit geeigneten Parametereinstellungen für LDA generieren?
Ich verwendete unten Code, um 10 Themen zu vergleichen (siehe Code-Abschnitt für Begriffe), die mit diesen Paketen generiert wurden. Ich konnte es nicht schaffen, Gruppen von Themen mit ähnlicher Bedeutung zu generieren. Z.B. Thema 10 von text2vec
hat etwas mit "Polizei" zu tun, keines der von topicmodels
produzierten Themen bezieht sich auf "Polizei" oder ähnliche Begriffe. Des Weiteren konnte ich keinen Anhänger des Themas 5 von topicmodels
identifizieren, der etwas mit "Leben-Liebe-Familienkrieg" in den von text2vec
produzierten Themen zu tun hat.
Ich bin ein Anfänger mit LDA, daher kann mein Verständnis naiv für erfahrene Programmierer klingen. Intuitiv würde man jedoch annehmen, dass es möglich sein sollte, Themengruppen mit ähnlicher Bedeutung zu erstellen, um die Validität/Robustheit der Ergebnisse zu beweisen. Natürlich nicht unbedingt genau die gleiche Terminologie, sondern Terminologie, die ähnliche Themen behandelt.
Vielleicht ist das Problem einfach, dass meine menschliche Interpretation dieser Termini nicht gut genug ist, um Ähnlichkeiten zu erfassen, aber vielleicht gibt es einige Parameter, die die Ähnlichkeit für die menschliche Interpretation erhöhen könnten. Kann mir jemand sagen, wie man Parameter setzt, um dies zu erreichen, oder auf andere Weise Erklärungen geben oder Hinweise auf geeignete Ressourcen geben, um mein Verständnis der Angelegenheit zu verbessern?
Hier einige Fragen, die relevant sein könnten:
- Ich weiß, dass
text2vec
nicht Standard Sampling Gibbs nicht verwendet, aber WarpLDA, die bereits ein Unterschied in dem Algorithmus zutopcimodels
ist. Wenn mein Verständnis korrekt ist, werden die Priorsalpha
unddelta
, die intopicmodels
verwendet werden, alsdoc_topic_prior
bzw.topic_word_prior
intext2vec
festgelegt. - Darüber hinaus ermöglicht text2vec in der Nachbearbeitung die Anpassung von
lambda
für die Sortierung von Themen zu Themen basierend auf ihrer Häufigkeit. Ich habe noch nicht verstanden, wie die Begriffe intopicmodels
sortiert sind - vergleichbar mit der Einstellunglambda=1
?. (Ich habe verschiedene Lambdas zwischen 0 bis 1 ausprobiert, ohne ähnliche Themen zu bekommen) - Ein anderes Problem ist, dass es schwierig scheint, ein vollständig reproduzierbares Beispiel zu erzeugen, selbst wenn
seed
(see, e.g., this question) eingestellt wird. Das ist nicht direkt meine Frage, aber es könnte die Antwort schwieriger machen.
Entschuldigung für die lange Frage und danke im Voraus für jede Hilfe oder Anregungen.
Update2: Ich habe den Inhalt meines ersten Updates in eine Antwort verschoben, die auf einer vollständigeren Analyse basiert.
Update: Nach dem hilfreichen Kommentar von text2vec
Paket Schöpfer Dmitriy Selivanov, das kann ich lambda=1
erhöht die Ähnlichkeit der Themen betweeen, die durch die beiden Pakete erzeugt termlists Einstellung bestätigen.
Außerdem habe ich mir die Unterschiede zwischen den von beiden Paketen produzierten Terminlisten durch eine schnelle Überprüfung von length(setdiff())
und length(intersect())
über Themen hinweg angeschaut (siehe unten stehenden Code).Dieser grobe Check zeigt, dass text2vec
mehrere Begriffe pro Thema verwirft - wahrscheinlich durch eine Wahrscheinlichkeitsschwelle für die einzelnen Themen? topicmodels
enthält alle Begriffe für alle Themen. Dies erklärt einen Teil der Bedeutungsunterschiede, die (von einem Menschen) aus den Termlisten abgeleitet werden können.
Wie bereits oben erwähnt, scheint es schwierig, ein reproduzierbares Beispiel zu erstellen. Daher habe ich nicht alle Datenbeispiele im unten stehenden Code angepasst. Da die Laufzeit kurz ist, kann jeder sein eigenes System überprüfen.
library(text2vec)
library(topicmodels)
library(slam) #to convert dtm to simple triplet matrix for topicmodels
ntopics <- 10
alphaprior <- 0.1
deltaprior <- 0.001
niter <- 1000
convtol <- 0.001
set.seed(0) #for text2vec
seedpar <- 0 #for topicmodels
#Generate document term matrix with text2vec
tokens = movie_review$review[1:1000] %>%
tolower %>%
word_tokenizer
it = itoken(tokens, ids = movie_review$id[1:1000], progressbar = FALSE)
vocab = create_vocabulary(it) %>%
prune_vocabulary(term_count_min = 10, doc_proportion_max = 0.2)
vectorizer = vocab_vectorizer(vocab)
dtm = create_dtm(it, vectorizer, type = "dgTMatrix")
#LDA model with text2vec
lda_model = text2vec::LDA$new(n_topics = ntopics
,doc_topic_prior = alphaprior
,topic_word_prior = deltaprior
)
doc_topic_distr = lda_model$fit_transform(x = dtm
,n_iter = niter
,convergence_tol = convtol
,n_check_convergence = 25
,progressbar = FALSE
)
#LDA model with topicmodels
ldatopicmodels <- LDA(as.simple_triplet_matrix(dtm), k = ntopics, method = "Gibbs",
LDA_Gibbscontrol = list(burnin = 100
,delta = deltaprior
,alpha = alphaprior
,iter = niter
,keep = 50
,tol = convtol
,seed = seedpar
,initialize = "seeded"
)
)
#show top 15 words
lda_model$get_top_words(n = 10, topic_number = c(1:10), lambda = 0.3)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] "finally" "men" "know" "video" "10" "king" "five" "our" "child" "cop"
# [2,] "re" "always" "ve" "1" "doesn" "match" "atmosphere" "husband" "later" "themselves"
# [3,] "three" "lost" "got" "head" "zombie" "lee" "mr" "comedy" "parents" "mary"
# [4,] "m" "team" "say" "girls" "message" "song" "de" "seem" "sexual" "average"
# [5,] "gay" "here" "d" "camera" "start" "musical" "may" "man" "murder" "scenes"
# [6,] "kids" "within" "funny" "kill" "3" "four" "especially" "problem" "tale" "police"
# [7,] "sort" "score" "want" "stupid" "zombies" "dance" "quality" "friends" "television" "appears"
# [8,] "few" "thriller" "movies" "talking" "movies" "action" "public" "given" "okay" "trying"
# [9,] "bit" "surprise" "let" "hard" "ask" "fun" "events" "crime" "cover" "waiting"
# [10,] "hot" "own" "thinking" "horrible" "won" "tony" "u" "special" "stan" "lewis"
# [11,] "die" "political" "nice" "stay" "open" "twist" "kelly" "through" "uses" "imdb"
# [12,] "credits" "success" "never" "back" "davis" "killer" "novel" "world" "order" "candy"
# [13,] "two" "does" "bunch" "didn" "completely" "ending" "copy" "show" "strange" "name"
# [14,] "otherwise" "beauty" "hilarious" "room" "love" "dancing" "japanese" "new" "female" "low"
# [15,] "need" "brilliant" "lot" "minutes" "away" "convincing" "far" "mostly" "girl" "killing"
terms(ldatopicmodels, 10)
# Topic 1 Topic 2 Topic 3 Topic 4 Topic 5 Topic 6 Topic 7 Topic 8 Topic 9 Topic 10
# [1,] "show" "where" "horror" "did" "life" "such" "m" "films" "man" "seen"
# [2,] "years" "minutes" "pretty" "10" "young" "character" "something" "music" "new" "movies"
# [3,] "old" "gets" "best" "now" "through" "while" "re" "actors" "two" "plot"
# [4,] "every" "guy" "ending" "why" "love" "those" "going" "role" "though" "better"
# [5,] "series" "another" "bit" "saw" "woman" "does" "things" "performance" "big" "worst"
# [6,] "funny" "around" "quite" "didn" "us" "seems" "want" "between" "back" "interesting"
# [7,] "comedy" "nothing" "little" "say" "real" "book" "thing" "love" "action" "your"
# [8,] "again" "down" "actually" "thought" "our" "may" "know" "play" "shot" "money"
# [9,] "tv" "take" "house" "still" "war" "work" "ve" "line" "together" "hard"
# [10,] "watching" "these" "however" "end" "father" "far" "here" "actor" "against" "poor"
# [11,] "cast" "fun" "cast" "got" "find" "scenes" "doesn" "star" "title" "least"
# [12,] "long" "night" "entertaining" "2" "human" "both" "look" "never" "go" "say"
# [13,] "through" "scene" "must" "am" "shows" "yet" "isn" "played" "city" "director"
# [14,] "once" "back" "each" "done" "family" "audience" "anything" "hollywood" "came" "probably"
# [15,] "watched" "dead" "makes" "3" "mother" "almost" "enough" "always" "match" "video"
#UPDATE
#number of terms in each model is the same
length([email protected])
# [1] 2170
nrow(vocab)
# [1] 2170
#number of NA entries for termlist of first topic differs
sum(is.na(
lda_model$get_top_words(n = nrow(vocab), topic_number = c(1:10), lambda = 1)[,1]
)
)
#[1] 1778
sum(is.na(
terms(ldatopicmodels, length([email protected]))
)
)
#[1] 0
#function to check number of terms that differ between two sets of topic collections (excluding NAs)
lengthsetdiff <- function(x, y) {
apply(x, 2, function(i) {
apply(y, 2, function(j) {
length(setdiff(i[!is.na(i)],j[!is.na(j)]))
})
})
}
#apply the check
termstopicmodels <- terms(ldatopicmodels,length([email protected]))
termstext2vec <- lda_model$get_top_words(n = nrow(vocab), topic_number = c(1:10), lambda = 1)
lengthsetdiff(termstopicmodels,
termstopicmodels)
# Topic 1 Topic 2 Topic 3 Topic 4 Topic 5 Topic 6 Topic 7 Topic 8 Topic 9 Topic 10
# Topic 1 0 0 0 0 0 0 0 0 0 0
# Topic 2 0 0 0 0 0 0 0 0 0 0
# Topic 3 0 0 0 0 0 0 0 0 0 0
# Topic 4 0 0 0 0 0 0 0 0 0 0
# Topic 5 0 0 0 0 0 0 0 0 0 0
# Topic 6 0 0 0 0 0 0 0 0 0 0
# Topic 7 0 0 0 0 0 0 0 0 0 0
# Topic 8 0 0 0 0 0 0 0 0 0 0
# Topic 9 0 0 0 0 0 0 0 0 0 0
# Topic 10 0 0 0 0 0 0 0 0 0 0
lengthsetdiff(termstext2vec,
termstext2vec)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] 0 340 318 335 292 309 320 355 294 322
# [2,] 355 0 321 343 292 319 311 346 302 339
# [3,] 350 338 0 316 286 309 311 358 318 322
# [4,] 346 339 295 0 297 310 301 335 309 332
# [5,] 345 330 307 339 0 310 310 354 309 333
# [6,] 350 345 318 340 298 0 311 342 308 325
# [7,] 366 342 325 336 303 316 0 364 311 325
# [8,] 355 331 326 324 301 301 318 0 311 335
# [9,] 336 329 328 340 298 309 307 353 0 314
# [10,] 342 344 310 341 300 304 299 355 292 0
lengthsetdiff(termstopicmodels,
termstext2vec)
# Topic 1 Topic 2 Topic 3 Topic 4 Topic 5 Topic 6 Topic 7 Topic 8 Topic 9 Topic 10
# [1,] 1778 1778 1778 1778 1778 1778 1778 1778 1778 1778
# [2,] 1793 1793 1793 1793 1793 1793 1793 1793 1793 1793
# [3,] 1810 1810 1810 1810 1810 1810 1810 1810 1810 1810
# [4,] 1789 1789 1789 1789 1789 1789 1789 1789 1789 1789
# [5,] 1831 1831 1831 1831 1831 1831 1831 1831 1831 1831
# [6,] 1819 1819 1819 1819 1819 1819 1819 1819 1819 1819
# [7,] 1824 1824 1824 1824 1824 1824 1824 1824 1824 1824
# [8,] 1778 1778 1778 1778 1778 1778 1778 1778 1778 1778
# [9,] 1820 1820 1820 1820 1820 1820 1820 1820 1820 1820
# [10,] 1798 1798 1798 1798 1798 1798 1798 1798 1798 1798
lengthsetdiff(termstext2vec,
termstopicmodels)
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# Topic 1 0 0 0 0 0 0 0 0 0 0
# Topic 2 0 0 0 0 0 0 0 0 0 0
# Topic 3 0 0 0 0 0 0 0 0 0 0
# Topic 4 0 0 0 0 0 0 0 0 0 0
# Topic 5 0 0 0 0 0 0 0 0 0 0
# Topic 6 0 0 0 0 0 0 0 0 0 0
# Topic 7 0 0 0 0 0 0 0 0 0 0
# Topic 8 0 0 0 0 0 0 0 0 0 0
# Topic 9 0 0 0 0 0 0 0 0 0 0
# Topic 10 0 0 0 0 0 0 0 0 0 0
#also the intersection can be checked between the two sets
lengthintersect <- function(x, y) {
apply(x, 2, function(i) {
apply(y, 2, function(j) {
length(intersect(i[!is.na(i)], j[!is.na(j)]))
})
})
}
lengthintersect(termstopicmodels,
termstext2vec)
# Topic 1 Topic 2 Topic 3 Topic 4 Topic 5 Topic 6 Topic 7 Topic 8 Topic 9 Topic 10
# [1,] 392 392 392 392 392 392 392 392 392 392
# [2,] 377 377 377 377 377 377 377 377 377 377
# [3,] 360 360 360 360 360 360 360 360 360 360
# [4,] 381 381 381 381 381 381 381 381 381 381
# [5,] 339 339 339 339 339 339 339 339 339 339
# [6,] 351 351 351 351 351 351 351 351 351 351
# [7,] 346 346 346 346 346 346 346 346 346 346
# [8,] 392 392 392 392 392 392 392 392 392 392
# [9,] 350 350 350 350 350 350 350 350 350 350
# [10,] 372 372 372 372 372 372 372 372 372 372
Ich denke 'Lambda = 1 'entspricht, wie' topicmodels' sortiert Begriffe. –
Vielen Dank für Ihre schnelle und hilfreiche Antwort. Ich habe meine Frage aktualisiert und einige Ergebnisse zu den Unterschieden der Ergebnisse vorgestellt. –