Topic modeling con LDA
Individui i topic latenti nei corpus di documenti usando il pacchetto topicmodels
Topic modeling con LDA è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.
Che cos'è la modellazione degli argomenti?
La modellazione degli argomenti è una tecnica di apprendimento automatico non supervisionato che individua la struttura tematica latente di un corpus. La Latent Dirichlet Allocation (LDA) presume che ogni documento sia una combinazione di K argomenti e che ogni argomento sia una distribuzione di probabilità sulle parole.
# 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 da tm
LDA richiede una Document-Term Matrix (DTM): le righe sono documenti, le colonne sono parole e le celle contengono i conteggi delle parole. Il pacchetto tm produce questo formato con DocumentTermMatrix(), mentre tidytext lo produce con cast_dtm().
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 da tidytext
cast_dtm(document, term, value) converte direttamente un tibble ordinato di conteggi delle parole in una DocumentTermMatrix compatibile con il pacchetto topicmodels. In questo modo la pipeline mantiene lo stile 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): addestrare il modello
LDA(dtm, k = K, control = list(seed = 42)) adatta un modello LDA con K argomenti usando il campionamento Gibbs o VEM. Imposti sempre un seed per garantire la riproducibilità: LDA è stocastico e, senza un seed fisso, i risultati variano tra un'esecuzione e l'altra.
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'): probabilità degli argomenti per parola
tidy(lda_model, matrix = 'beta') estrae le probabilità degli argomenti per parola (la matrice beta). Ogni riga indica la probabilità che una specifica parola sia stata generata da uno specifico argomento. Le parole con probabilità elevata definiscono il tema di ciascun argomento.
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)Visualizzare le parole degli argomenti
Rappresenti le N parole principali di ogni argomento con un grafico a barre suddiviso in facet. Ordini le parole all'interno di ogni argomento in base al valore beta usando reorder_within() e scale_x_reordered() di tidytext, così da ottenere un ordinamento indipendente corretto per ogni facet.
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'): probabilità degli argomenti per documento
tidy(lda_model, matrix = 'gamma') estrae le probabilità degli argomenti per documento (la matrice gamma). Ogni riga indica la proporzione del documento stimata come appartenente a uno specifico argomento. I documenti con un valore gamma elevato per l'argomento 2 trattano principalmente l'argomento 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))Scegliere K: numero di argomenti
LDA richiede di specificare K in anticipo. Gli approcci comuni sono: (1) perplessità: più è bassa, meglio è, ma diminuisce monotonicamente all'aumentare di K; (2) punteggio di coerenza (pacchetto ldatuning); (3) conoscenza del dominio; (4) provare K = 5, 10, 20 e ispezionare manualmente gli elenchi di parole.
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')Assegnare un'etichetta agli argomenti
LDA produce argomenti anonimi (1, 2, 3…). L'analista deve assegnare un'etichetta a ogni argomento esaminandone le parole principali. Crei una tabella di ricerca che associ i numeri degli argomenti a nomi descrittivi e la unisca ai risultati.
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 su un corpus personalizzato
Ecco una pipeline LDA completa, dall'inizio alla fine, su un corpus personalizzato: tokenizzazione, costruzione della DTM, addestramento di LDA, estrazione della matrice beta e visualizzazione delle parole principali per argomento.
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()Limiti di LDA
LDA presuppone un modello bag-of-words (l'ordine delle parole non conta), che gli argomenti siano statici nel corpus e che K venga scelto in anticipo. Per argomenti dinamici o gerarchici, consideri STM (Structural Topic Model) o CTM (Correlated Topic Model), disponibili nel pacchetto 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 rapida
In LDA, che cosa rappresenta la matrice beta?
Riepilogo: modellazione degli argomenti con LDA
Punti chiave:
- LDA individua K argomenti latenti come distribuzioni di parole a partire da una matrice documento-termine
- Costruisca la DTM con
cast_dtm(document, word, n)(tidytext) oDocumentTermMatrix()(tm) LDA(dtm, k = K, control = list(seed = 42))adatta il modellotidy(lda, 'beta')= probabilità degli argomenti per parola (ciò che definisce ogni argomento)tidy(lda, 'gamma')= proporzioni degli argomenti per documento (il tema di ciascun documento)- Usi i punteggi di perplessità o coerenza per orientare la scelta di K
- Esamini sempre manualmente le parole principali per assegnare un'etichetta agli argomenti
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()Impara R con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 43
- Lezioni
- 159
Domande Frequenti
La lezione «Topic modeling con LDA» è gratuita?
Sì — il testo completo di «Topic modeling con LDA» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.
Cosa imparerò in «Topic modeling con LDA»?
Individui i topic latenti nei corpus di documenti usando il pacchetto topicmodels Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare R Academy?
Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Topic modeling con LDA»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione R Academy?
Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Tokenizzazione e rimozione delle stop word
- TF-IDF e analisi della frequenza dei termini
- Analisi del sentiment in R
- Topic modeling con LDA