Extração de Tópicos com Fatoração de Matrizes Não-Negativas (NMF) e Alocação de Dirichlet Latente (LDA)

Beginner

This tutorial is from open-source community. Access the source code

Introdução

Neste laboratório, aplicaremos a Fatoração de Matrizes Não-Negativas (NMF) e a Alocação Dirichlet Latente (LDA) a um corpus de documentos para extrair modelos aditivos da estrutura temática do corpus. A saída será um gráfico de tópicos, cada um representado como um gráfico de barras utilizando as poucas palavras mais importantes com base nos pesos.

Dicas da Máquina Virtual

Após o arranque da máquina virtual, clique no canto superior esquerdo para mudar para a aba Notebook para aceder ao Jupyter Notebook para a prática.

Por vezes, pode ser necessário esperar alguns segundos para o Jupyter Notebook terminar o carregamento. A validação das operações não pode ser automatizada devido a limitações no Jupyter Notebook.

Se tiver problemas durante o aprendizado, não hesite em contactar o Labby. Forneça feedback após a sessão e resolveremos prontamente o problema para si.

Carregar o Conjunto de Dados

Vamos carregar o conjunto de dados 20 newsgroups e vetorizá-lo. Usamos algumas heurísticas para filtrar termos inúteis desde o início: os posts são desprovidos de cabeçalhos, rodapés e respostas citadas, e palavras comuns em inglês, palavras que aparecem em apenas um documento ou em pelo menos 95% dos documentos são removidas.

from sklearn.datasets import fetch_20newsgroups

n_samples = 2000
n_features = 1000

print("Carregando conjunto de dados...")
data, _ = fetch_20newsgroups(
    shuffle=True,
    random_state=1,
    remove=("headers", "footers", "quotes"),
    return_X_y=True,
)
data_samples = data[:n_samples]

Extrair Recursos

Extrairemos recursos do conjunto de dados usando recursos tf-idf para NMF e recursos de contagem de termos brutos para LDA.

from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer

## Use recursos tf-idf para NMF.
print("Extraindo recursos tf-idf para NMF...")
tfidf_vectorizer = TfidfVectorizer(
    max_df=0.95, min_df=2, max_features=n_features, stop_words="english"
)
tfidf = tfidf_vectorizer.fit_transform(data_samples)

## Use recursos de contagem de termos brutos para LDA.
print("Extraindo recursos tf para LDA...")
tf_vectorizer = CountVectorizer(
    max_df=0.95, min_df=2, max_features=n_features, stop_words="english"
)
tf = tf_vectorizer.fit_transform(data_samples)

Aplicar NMF

Aplicaremos NMF com duas funções objetivo diferentes: a norma de Frobenius e a divergência generalizada de Kullback-Leibler. Esta última é equivalente à Indexação Semântica de Palavras Latentes Probabilística.

from sklearn.decomposition import NMF

n_components = 10
n_top_words = 20
init = "nndsvda"

## Ajustar o modelo NMF
print(
    "Ajustando o modelo NMF (norma de Frobenius) com recursos tf-idf, "
    "n_samples=%d e n_features=%d..." % (n_samples, n_features)
)
nmf = NMF(
    n_components=n_components,
    random_state=1,
    init=init,
    beta_loss="frobenius",
    alpha_W=0.00005,
    alpha_H=0.00005,
    l1_ratio=1,
).fit(tfidf)

## Plotar as palavras principais para o modelo NMF
def plot_top_words(model, feature_names, n_top_words, title):
    fig, axes = plt.subplots(2, 5, figsize=(30, 15), sharex=True)
    axes = axes.flatten()
    for topic_idx, topic in enumerate(model.components_):
        top_features_ind = topic.argsort()[: -n_top_words - 1 : -1]
        top_features = [feature_names[i] for i in top_features_ind]
        weights = topic[top_features_ind]

        ax = axes[topic_idx]
        ax.barh(top_features, weights, height=0.7)
        ax.set_title(f"Tópico {topic_idx +1}", fontdict={"fontsize": 30})
        ax.invert_yaxis()
        ax.tick_params(axis="both", which="major", labelsize=20)
        for i in "top right left".split():
            ax.spines[i].set_visible(False)
        fig.suptitle(title, fontsize=40)

    plt.subplots_adjust(top=0.90, bottom=0.05, wspace=0.90, hspace=0.3)
    plt.show()

tfidf_feature_names = tfidf_vectorizer.get_feature_names_out()
plot_top_words(
    nmf, tfidf_feature_names, n_top_words, "Tópicos no modelo NMF (norma de Frobenius)"
)

## Ajustar o modelo NMF com a divergência generalizada de Kullback-Leibler
print(
    "\n" * 2,
    "Ajustando o modelo NMF (divergência generalizada de Kullback-Leibler "
    "com recursos tf-idf, n_samples=%d e n_features=%d..."
    % (n_samples, n_features),
)
nmf = NMF(
    n_components=n_components,
    random_state=1,
    init=init,
    beta_loss="kullback-leibler",
    solver="mu",
    max_iter=1000,
    alpha_W=0.00005,
    alpha_H=0.00005,
    l1_ratio=0.5,
).fit(tfidf)

## Plotar as palavras principais para o modelo NMF com a divergência generalizada de Kullback-Leibler
tfidf_feature_names = tfidf_vectorizer.get_feature_names_out()
plot_top_words(
    nmf,
    tfidf_feature_names,
    n_top_words,
    "Tópicos no modelo NMF (divergência generalizada de Kullback-Leibler)",
)

## Ajustar o modelo MiniBatchNMF
from sklearn.decomposition import MiniBatchNMF

batch_size = 128

print(
    "\n" * 2,
    "Ajustando o modelo MiniBatchNMF (norma de Frobenius) com recursos tf-idf "
    "n_samples=%d e n_features=%d, batch_size=%d..."
    % (n_samples, n_features, batch_size),
)
## ... (restante do código)

Aplicar LDA

Aplicaremos modelos LDA com recursos tf.

from sklearn.decomposition import LatentDirichletAllocation

print(
    "\n" * 2,
    "Ajustando modelos LDA com recursos tf, n_samples=%d e n_features=%d..."
    % (n_samples, n_features),
)
lda = LatentDirichletAllocation(
    n_components=n_components,
    max_iter=5,
    learning_method="online",
    learning_offset=50.0,
    random_state=0,
)
t0 = time()
lda.fit(tf)
print("concluído em %0.3fs." % (time() - t0))

tf_feature_names = tf_vectorizer.get_feature_names_out()
plot_top_words(lda, tf_feature_names, n_top_words, "Tópicos no modelo LDA")

Resumo

Neste laboratório, aprendemos como aplicar a Fatoração de Matrizes Não-Negativas e a Alocação de Dirichlet Latente em um conjunto de documentos para extrair modelos aditivos da estrutura temática do conjunto. Também aprendemos como plotar os tópicos, cada um representado como um gráfico de barras usando as poucas palavras principais com base nos pesos.