Modelagem de tópicos com LDA
Descubra tópicos latentes em corpora de documentos usando o pacote topicmodels.
Modelagem de tópicos com LDA é uma aula grátis de R Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de R Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de R Academy inclui 4 aulas no total.
O que é modelagem de tópicos?
A modelagem de tópicos é uma técnica de aprendizado de máquina não supervisionado que descobre a estrutura temática latente de um corpus. A Alocação Latente de Dirichlet (LDA) pressupõe que cada documento é uma mistura de K tópicos e que cada tópico é uma distribuição de probabilidade sobre as palavras.
# LDA key assumptions:
# 1. Each document is a mixture of K topics
# 2. Each topic is a distribution over all vocabulary words
# 3. Words are generated by first picking a topic, then a word from that topic
# Example: K=2 topics in a corpus about tech and cooking
# Topic 1 (Tech): neural(0.15) python(0.12) algorithm(0.10) ...
# Topic 2 (Cooking): recipe(0.14) flour(0.11) bake(0.10) ...
# A document about 'AI-generated recipes' might be:
# 70% Topic 1 (Tech) + 30% Topic 2 (Cooking)
cat('LDA parameters:\n')
cat('K = number of topics (you choose)\n')
cat('alpha = document-topic sparsity prior\n')
cat('beta = topic-word sparsity prior\n')DocumentTermMatrix do tm
A LDA exige uma matriz documento-termo (DTM): as linhas são documentos, as colunas são palavras e as células contêm contagens de palavras. DocumentTermMatrix() do pacote tm ou cast_dtm() do tidytext produzem esse formato.
library(tm)
# Build a corpus from raw text
docs <- c(
'machine learning neural networks training algorithms',
'deep learning gradient backpropagation optimizer',
'python scikit numpy pandas machine learning',
'database sql tables indexes queries joins',
'relational schema normalization foreign primary',
'nosql mongodb document store redis queries'
)
corpus <- Corpus(VectorSource(docs))
corpus <- tm_map(corpus, removePunctuation)
corpus <- tm_map(corpus, removeWords, stopwords('english'))
corpus <- tm_map(corpus, stripWhitespace)
dtm <- DocumentTermMatrix(corpus)
cat('DTM shape:', nrow(dtm), 'docs x', ncol(dtm), 'terms\n')
cat('Sparsity: ', round(tm::sparsity(dtm) * 100, 1), '%\n')cast_dtm do tidytext
cast_dtm(document, term, value) converte diretamente um tibble organizado de contagens de palavras em uma DocumentTermMatrix compatível com o pacote topicmodels. Isso mantém seu pipeline no estilo do tidyverse.
library(tidytext)
library(dplyr)
# Tidy corpus
corpus <- tibble::tibble(
doc_id = c(rep(1, 3), rep(2, 3), rep(3, 3), rep(4, 3)),
text = c(
'neural networks deep learning training',
'gradient descent backpropagation optimizer',
'machine learning algorithms classification',
'database sql tables queries indexes',
'relational schema normalization joins',
'foreign primary key constraints transactions',
'recipe bake flour butter oven',
'cooking temperature simmer saute ingredients',
'kitchen knife herbs spices garnish'
)
)
dtm <- corpus |>
unnest_tokens(word, text) |>
anti_join(tidytext::stop_words, by = 'word') |>
count(doc_id, word) |>
cast_dtm(doc_id, word, n)
cat('DTM:', nrow(dtm), 'docs x', ncol(dtm), 'terms\n')LDA(dtm, k = 5): ajustando o modelo
LDA(dtm, k = K, control = list(seed = 42)) ajusta um modelo LDA com K tópicos usando amostragem de Gibbs ou VEM. Sempre defina um seed para garantir a reprodutibilidade — a LDA é estocástica e os resultados variam entre execuções sem uma semente fixa.
library(tidytext)
library(dplyr)
library(topicmodels)
# Build DTM
corpus <- tibble::tibble(
doc_id = c(rep(1,3), rep(2,3), rep(3,3), rep(4,3), rep(5,3), rep(6,3)),
text = c(
'neural networks deep gradient','backpropagation training optimizer','learning model layers',
'database sql queries indexes','relational tables joins foreign','schema normalization constraints',
'recipe flour bake butter','cooking temperature oven simmer','kitchen knife herbs spices'
)[rep(c(1,2,3,4,5,6), each=1)]
)
dtm <- corpus |>
unnest_tokens(word, text) |>
count(doc_id, word) |>
cast_dtm(doc_id, word, n)
# Fit LDA with k=3 topics
lda_model <- LDA(dtm, k = 3, control = list(seed = 42))
cat('LDA model fitted: k=3 topics\n')
cat('Class:', class(lda_model), '\n')tidy(lda, matrix = 'beta'): probabilidades de tópicos por palavra
tidy(lda_model, matrix = 'beta') extrai as probabilidades de tópicos por palavra (a matriz beta). Cada linha fornece a probabilidade de uma palavra específica ter sido gerada por um tópico específico. As palavras com alta probabilidade definem sobre o que é cada tópico.
library(topicmodels)
library(tidytext)
library(dplyr)
# Using the built-in AssociatedPress dataset
data('AssociatedPress', package = 'topicmodels')
lda <- LDA(AssociatedPress[1:50, ], k = 4, control = list(seed = 1234))
# Per-word topic probabilities (beta)
beta_tbl <- tidy(lda, matrix = 'beta')
cat('Beta matrix rows:', nrow(beta_tbl), '\n')
cat('Columns:', names(beta_tbl), '\n')
# Top words per topic
top_terms <- beta_tbl |>
group_by(topic) |>
slice_max(beta, n = 5) |>
ungroup()
cat('\nTop 5 words per topic:\n')
print(top_terms)Visualizando as palavras dos tópicos
Represente as N palavras mais frequentes de cada tópico em um gráfico de barras facetado. Ordene as palavras dentro de cada tópico pelo valor beta usando reorder_within() e scale_x_reordered() do tidytext para obter a ordenação independente correta em cada faceta.
library(topicmodels)
library(tidytext)
library(dplyr)
library(ggplot2)
data('AssociatedPress', package = 'topicmodels')
lda <- LDA(AssociatedPress[1:100, ], k = 4, control = list(seed = 42))
tidy(lda, matrix = 'beta') |>
group_by(topic) |>
slice_max(beta, n = 8) |>
ungroup() |>
mutate(term = reorder_within(term, beta, topic)) |>
ggplot(aes(term, beta, fill = factor(topic))) +
geom_col(show.legend = FALSE) +
facet_wrap(~topic, scales = 'free') +
scale_x_reordered() +
coord_flip() +
labs(x = NULL, y = 'Beta', title = 'Top Words per LDA Topic') +
theme_minimal(base_size = 10)tidy(lda, matrix = 'gamma'): probabilidades de tópicos por documento
tidy(lda_model, matrix = 'gamma') extrai as probabilidades de tópicos por documento (a matriz gamma). Cada linha fornece a proporção de um documento estimada como proveniente de um tópico específico. Documentos com gamma alto para o tópico 2 são sobre o tópico 2.
library(topicmodels)
library(tidytext)
library(dplyr)
data('AssociatedPress', package = 'topicmodels')
lda <- LDA(AssociatedPress[1:30, ], k = 3, control = list(seed = 99))
# Per-document topic proportions (gamma)
gamma_tbl <- tidy(lda, matrix = 'gamma')
cat('Gamma matrix rows:', nrow(gamma_tbl), '\n')
# Dominant topic per document
dominant_topic <- gamma_tbl |>
group_by(document) |>
slice_max(gamma, n = 1) |>
ungroup()
cat('\nDominant topic per document (first 8):\n')
print(head(dominant_topic, 8))Escolhendo K: número de tópicos
A LDA exige que você especifique K antecipadamente. Abordagens comuns: (1) perplexidade — quanto menor, melhor, mas ela diminui monotonicamente com K; (2) pontuação de coerência (pacote ldatuning); (3) conhecimento do domínio; (4) experimente K = 5, 10, 20 e examine manualmente as listas de palavras.
library(topicmodels)
library(tidytext)
data('AssociatedPress', package = 'topicmodels')
# Evaluate perplexity for K = 2, 3, 4, 5
k_values <- 2:5
perplexities <- vapply(k_values, function(k) {
model <- LDA(AssociatedPress[1:50, ], k = k,
control = list(seed = 42))
perplexity(model)
}, numeric(1))
results <- data.frame(k = k_values, perplexity = round(perplexities, 1))
cat('Perplexity by K:\n')
print(results)
cat('\nNote: lower perplexity = better fit to training data\n')Rotulagem de tópicos
A LDA produz tópicos anônimos (1, 2, 3…). O analista humano deve rotular cada tópico examinando suas palavras principais. Crie uma tabela de referência que associe os números dos tópicos a nomes descritivos e faça uma junção dessa tabela aos seus resultados.
library(topicmodels)
library(tidytext)
library(dplyr)
data('AssociatedPress', package = 'topicmodels')
lda <- LDA(AssociatedPress[1:100, ], k = 4, control = list(seed = 7))
# Top 5 words per topic for manual labelling
tidy(lda, matrix = 'beta') |>
group_by(topic) |>
slice_max(beta, n = 5) |>
summarise(top_words = paste(term, collapse = ', ')) |>
print()
# After inspecting top words, assign human-readable labels
topic_labels <- tibble::tibble(
topic = 1:4,
label = c('Politics', 'Economy', 'Sports', 'Science') # your interpretation
)
cat('\nTopic labels assigned (example):\n')
print(topic_labels)LDA em um corpus personalizado
Aqui está um pipeline completo de LDA, do início ao fim, aplicado a um corpus personalizado: tokenizar, construir a DTM, ajustar a LDA, extrair a matriz beta e exibir as palavras principais de cada tópico.
library(tidytext)
library(dplyr)
library(topicmodels)
# 9 documents across 3 latent topics
docs <- tibble::tibble(
id = 1:9,
text = c(
'machine learning neural deep training',
'algorithm gradient backpropagation network',
'python tensorflow keras model layers',
'database sql relational tables queries',
'joins indexes schema foreign primary',
'transactions normalization constraints',
'recipe ingredients bake flour butter',
'cooking temperature simmer oven saute',
'kitchen knife herbs spices garnish'
)
)
dtm <- docs |>
unnest_tokens(word, text) |>
count(id, word) |>
cast_dtm(id, word, n)
lda <- LDA(dtm, k = 3, control = list(seed = 123))
tidy(lda, 'beta') |>
group_by(topic) |>
slice_max(beta, n = 4) |>
summarise(words = paste(term, collapse = ', ')) |>
print()Limitações da LDA
A LDA pressupõe um modelo de saco de palavras (a ordem das palavras não importa), que os tópicos são estáticos em todo o corpus e que K deve ser escolhido antecipadamente. Para tópicos dinâmicos ou hierárquicos, considere STM (Structural Topic Model) ou CTM (Correlated Topic Model), disponíveis no pacote stm.
# LDA assumptions and limitations
limitations <- data.frame(
Assumption = c(
'Bag of words', 'Fixed K', 'Topic independence',
'Static topics', 'No metadata'
),
Alternative = c(
'word2vec / BERT',
'ldatuning for K selection',
'CTM (Correlated Topic Model)',
'DTM (Dynamic Topic Model)',
'STM (Structural Topic Model)'
)
)
print(limitations, row.names = FALSE)Verificação rápida
Na LDA, o que a matriz beta representa?
Recapitulação: modelagem de tópicos com LDA
Principais conclusões:
- A LDA descobre K tópicos latentes como distribuições de palavras a partir de uma matriz documento-termo
- Construa a DTM com
cast_dtm(document, word, n)(tidytext) ouDocumentTermMatrix()(tm) LDA(dtm, k = K, control = list(seed = 42))ajusta o modelotidy(lda, 'beta')= probabilidades de tópicos por palavra (o que define cada tópico)tidy(lda, 'gamma')= proporções de tópicos por documento (sobre o que é cada documento)- Use pontuações de perplexidade ou coerência para orientar a escolha de K
- Sempre examine manualmente as palavras principais para rotular os tópicos
library(topicmodels)
library(tidytext)
library(dplyr)
data('AssociatedPress', package = 'topicmodels')
lda <- LDA(AssociatedPress[1:20, ], k = 2, control = list(seed = 1))
tidy(lda, 'beta') |>
group_by(topic) |>
slice_max(beta, n = 3) |>
summarise(top_words = paste(term, collapse = ', ')) |>
print()Perguntas Frequentes
A aula “Modelagem de tópicos com LDA” é grátis?
Sim — o texto completo de “Modelagem de tópicos com LDA” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de R Academy, atualize para CoddyKit PRO. O curso de R Academy inclui 4 aulas no total.
O que vou aprender em “Modelagem de tópicos com LDA”?
Descubra tópicos latentes em corpora de documentos usando o pacote topicmodels. Você pratica R Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar R Academy?
Nenhuma experiência prévia é necessária. R Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Modelagem de tópicos com LDA”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de R Academy?
Sim. Cada aula de R Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Tokenização e remoção de palavras irrelevantes
- TF-IDF e análise de frequência de termos
- Análise de sentimentos em R
- Modelagem de tópicos com LDA