Tracer l'extraction de sujets avec NMF et LDA

Machine LearningMachine LearningBeginner
Pratiquer maintenant

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

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce laboratoire, nous allons appliquer la factorisation de matrice non négative (NMF) et l'allocation de Dirichlet latente (LDA) sur un corpus de documents pour extraire des modèles additifs de la structure thématiques du corpus. La sortie sera un graphique de thèmes, chacun représenté sous forme d'un graphique en barres utilisant les quelques premiers mots en fonction des poids.

Conseils sur la VM

Une fois le démarrage de la VM terminé, cliquez dans le coin supérieur gauche pour basculer vers l'onglet Notebook pour accéder à Jupyter Notebook pour la pratique.

Parfois, vous devrez peut-être attendre quelques secondes pour que Jupyter Notebook ait fini de charger. La validation des opérations ne peut pas être automatisée en raison des limitations de Jupyter Notebook.

Si vous rencontrez des problèmes pendant l'apprentissage, n'hésitez pas à demander à Labby. Donnez votre feedback après la session, et nous résoudrons rapidement le problème pour vous.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn(("Sklearn")) -.-> sklearn/DataPreprocessingandFeatureEngineeringGroup(["Data Preprocessing and Feature Engineering"]) sklearn(("Sklearn")) -.-> sklearn/AdvancedDataAnalysisandDimensionalityReductionGroup(["Advanced Data Analysis and Dimensionality Reduction"]) sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/feature_extraction("Feature Extraction") sklearn/AdvancedDataAnalysisandDimensionalityReductionGroup -.-> sklearn/decomposition("Matrix Decomposition") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/datasets("Datasets") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/feature_extraction -.-> lab-49319{{"Tracer l'extraction de sujets avec NMF et LDA"}} sklearn/decomposition -.-> lab-49319{{"Tracer l'extraction de sujets avec NMF et LDA"}} sklearn/datasets -.-> lab-49319{{"Tracer l'extraction de sujets avec NMF et LDA"}} ml/sklearn -.-> lab-49319{{"Tracer l'extraction de sujets avec NMF et LDA"}} end

Charger le jeu de données

Nous allons charger le jeu de données 20 newsgroups et le vectoriser. Nous utilisons quelques heuristiques pour éliminer précocement les termes inutiles : les messages sont dépouillés de leurs en-têtes, pieds de page et réponses citées, et les mots anglais courants, les mots apparaissant dans un seul document ou dans au moins 95 % des documents sont supprimés.

from sklearn.datasets import fetch_20newsgroups

n_samples = 2000
n_features = 1000

print("Chargement du jeu de données...")
data, _ = fetch_20newsgroups(
    shuffle=True,
    random_state=1,
    remove=("headers", "footers", "quotes"),
    return_X_y=True,
)
data_samples = data[:n_samples]

Extraire les caractéristiques

Nous allons extraire les caractéristiques à partir du jeu de données en utilisant les caractéristiques tf-idf pour la NMF et les comptes de termes bruts pour la LDA.

from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer

## Utiliser les caractéristiques tf-idf pour la NMF.
print("Extraction des caractéristiques tf-idf pour la 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)

## Utiliser les caractéristiques de comptage de termes bruts pour la LDA.
print("Extraction des caractéristiques tf pour la 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)

Appliquer la NMF

Nous allons appliquer la NMF avec deux fonctions objectifs différentes : la norme de Frobenius et la divergence générale de Kullback-Leibler. Cette dernière est équivalente à l'indexation sémantique latente probabiliste.

from sklearn.decomposition import NMF

n_components = 10
n_top_words = 20
init = "nndsvda"

## Ajuster le modèle NMF
print(
    "Ajustement du modèle NMF (norme de Frobenius) avec des caractéristiques tf-idf, "
    "n_samples=%d et 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)

## Tracer les mots les plus fréquents pour le modèle 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"Sujet {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, "Sujets dans le modèle NMF (norme de Frobenius)"
)

## Ajuster le modèle NMF avec la divergence générale de Kullback-Leibler
print(
    "\n" * 2,
    "Ajustement du modèle NMF (divergence générale de Kullback-Leibler "
    "divergence) avec des caractéristiques tf-idf, n_samples=%d et 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)

## Tracer les mots les plus fréquents pour le modèle NMF avec la divergence générale de Kullback-Leibler
tfidf_feature_names = tfidf_vectorizer.get_feature_names_out()
plot_top_words(
    nmf,
    tfidf_feature_names,
    n_top_words,
    "Sujets dans le modèle NMF (divergence générale de Kullback-Leibler divergence)",
)

## Ajuster le modèle MiniBatchNMF
from sklearn.decomposition import MiniBatchNMF

batch_size = 128

print(
    "\n" * 2,
    "Ajustement du modèle MiniBatchNMF (norme de Frobenius) avec tf-idf "
    "caractéristiques, n_samples=%d et n_features=%d, batch_size=%d..."
    % (n_samples, n_features, batch_size),
)
mbnmf = MiniBatchNMF(
    n_components=n_components,
    random_state=1,
    batch_size=batch_size,
    init=init,
    beta_loss="frobenius",
    alpha_W=0.00005,
    alpha_H=0.00005,
    l1_ratio=0.5,
).fit(tfidf)

## Tracer les mots les plus fréquents pour le modèle MiniBatchNMF avec la norme de Frobenius
tfidf_feature_names = tfidf_vectorizer.get_feature_names_out()
plot_top_words(
    mbnmf,
    tfidf_feature_names,
    n_top_words,
    "Sujets dans le modèle MiniBatchNMF (norme de Frobenius)",
)

## Ajuster le modèle MiniBatchNMF avec la divergence générale de Kullback-Leibler
print(
    "\n" * 2,
    "Ajustement du modèle MiniBatchNMF (divergence générale de Kullback-Leibler "
    "divergence) avec des caractéristiques tf-idf, n_samples=%d et n_features=%d, "
    "batch_size=%d..." % (n_samples, n_features, batch_size),
)
mbnmf = MiniBatchNMF(
    n_components=n_components,
    random_state=1,
    batch_size=batch_size,
    init=init,
    beta_loss="kullback-leibler",
    alpha_W=0.00005,
    alpha_H=0.00005,
    l1_ratio=0.5,
).fit(tfidf)

## Tracer les mots les plus fréquents pour le modèle MiniBatchNMF avec la divergence générale de Kullback-Leibler
tfidf_feature_names = tfidf_vectorizer.get_feature_names_out()
plot_top_words(
    mbnmf,
    tfidf_feature_names,
    n_top_words,
    "Sujets dans le modèle MiniBatchNMF (divergence générale de Kullback-Leibler divergence)",
)

Appliquer la LDA

Nous allons appliquer des modèles LDA avec des caractéristiques tf.

from sklearn.decomposition import LatentDirichletAllocation

print(
    "\n" * 2,
    "Ajustement des modèles LDA avec des caractéristiques tf, n_samples=%d et 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("terminé en %0.3fs." % (time() - t0))

tf_feature_names = tf_vectorizer.get_feature_names_out()
plot_top_words(lda, tf_feature_names, n_top_words, "Sujets dans le modèle LDA")

Sommaire

Dans ce laboratoire, nous avons appris comment appliquer la factorisation de matrice non négative et l'allocation latente de Dirichlet sur un corpus de documents pour extraire des modèles additifs de la structure thémique du corpus. Nous avons également appris comment tracer les sujets, chacun représenté sous forme d'un graphique en barres en utilisant les quelques mots les plus fréquents en fonction des poids.