Einführung
In diesem Lab werden wir die Nichtnegative Matrix Faktorisierung (NMF) und die Latente Dirichlet Allokation (LDA) auf einem Korpus von Dokumenten anwenden, um additive Modelle der Thematik des Korpus zu extrahieren. Die Ausgabe wird ein Diagramm der Themen sein, wobei jedes Thema als Balkendiagramm dargestellt wird, das die ersten paar Wörter basierend auf den Gewichten zeigt.
Tipps für die VM
Nachdem der Start der VM abgeschlossen ist, klicken Sie in der oberen linken Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu nutzen.
Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund der Einschränkungen von Jupyter Notebook nicht automatisiert werden.
Wenn Sie während des Lernens Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback, und wir werden das Problem für Sie prompt beheben.
Lade den Datensatz
Wir werden den 20 Newsgroups-Datensatz laden und ihn vektorisieren. Wir verwenden einige Heuristiken, um frühzeitig nutzlose Begriffe zu filtern: Die Beiträge werden von Kopfzeilen, Fußzeilen und zitierten Antworten befreit, und übliche englische Wörter, Wörter, die nur in einem Dokument oder in mindestens 95% der Dokumente auftauchen, werden entfernt.
from sklearn.datasets import fetch_20newsgroups
n_samples = 2000
n_features = 1000
print("Lade Datensatz...")
data, _ = fetch_20newsgroups(
shuffle=True,
random_state=1,
remove=("headers", "footers", "quotes"),
return_X_y=True,
)
data_samples = data[:n_samples]
Extrahiere Merkmale
Wir werden Merkmale aus dem Datensatz extrahieren, indem wir tf-idf-Merkmale für die NMF und einfache Termzähler-Merkmale für die LDA verwenden.
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
## Verwende tf-idf-Merkmale für die NMF.
print("Extrahiere tf-idf-Merkmale für die 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)
## Verwende einfache Termzähler-Merkmale für die LDA.
print("Extrahiere tf-Merkmale für die 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)
Wendet NMF an
Wir werden NMF mit zwei verschiedenen Zielfunktionen anwenden: die Frobenius-Norm und die verallgemeinerte Kullback-Leibler-Divergenz. Letztere ist äquivalent zu Probabilistic Latent Semantic Indexing.
from sklearn.decomposition import NMF
n_components = 10
n_top_words = 20
init = "nndsvda"
## Passt das NMF-Modell an
print(
"Passt das NMF-Modell (Frobenius-Norm) mit tf-idf-Merkmalen, "
"n_samples=%d und n_features=%d an..." % (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)
## Zeichnet die wichtigsten Wörter für das NMF-Modell
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"Topic {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, "Topics in NMF model (Frobenius norm)"
)
## Passt das NMF-Modell mit der verallgemeinerten Kullback-Leibler-Divergenz an
print(
"\n" * 2,
"Passt das NMF-Modell (verallgemeinerte Kullback-Leibler "
"Divergenz) mit tf-idf-Merkmalen, n_samples=%d und n_features=%d an..."
% (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)
## Zeichnet die wichtigsten Wörter für das NMF-Modell mit der verallgemeinerten Kullback-Leibler-Divergenz
tfidf_feature_names = tfidf_vectorizer.get_feature_names_out()
plot_top_words(
nmf,
tfidf_feature_names,
n_top_words,
"Topics in NMF model (generalized Kullback-Leibler divergence)",
)
## Passt das MiniBatchNMF-Modell an
from sklearn.decomposition import MiniBatchNMF
batch_size = 128
print(
"\n" * 2,
"Passt das MiniBatchNMF-Modell (Frobenius-Norm) mit tf-idf "
"Merkmalen, n_samples=%d und n_features=%d, batch_size=%d an..."
% (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)
## Zeichnet die wichtigsten Wörter für das MiniBatchNMF-Modell mit der Frobenius-Norm
tfidf_feature_names = tfidf_vectorizer.get_feature_names_out()
plot_top_words(
mbnmf,
tfidf_feature_names,
n_top_words,
"Topics in MiniBatchNMF model (Frobenius norm)",
)
## Passt das MiniBatchNMF-Modell mit der verallgemeinerten Kullback-Leibler-Divergenz an
print(
"\n" * 2,
"Passt das MiniBatchNMF-Modell (verallgemeinerte Kullback-Leibler "
"Divergenz) mit tf-idf Merkmalen, n_samples=%d und n_features=%d, "
"batch_size=%d an..." % (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)
## Zeichnet die wichtigsten Wörter für das MiniBatchNMF-Modell mit der verallgemeinerten Kullback-Leibler-Divergenz
tfidf_feature_names = tfidf_vectorizer.get_feature_names_out()
plot_top_words(
mbnmf,
tfidf_feature_names,
n_top_words,
"Topics in MiniBatchNMF model (generalized Kullback-Leibler divergence)",
)
Wendet LDA an
Wir werden LDA-Modelle mit tf-Merkmalen anwenden.
from sklearn.decomposition import LatentDirichletAllocation
print(
"\n" * 2,
"Passt LDA-Modelle mit tf-Merkmalen an, n_samples=%d und 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("fertig in %0.3fs." % (time() - t0))
tf_feature_names = tf_vectorizer.get_feature_names_out()
plot_top_words(lda, tf_feature_names, n_top_words, "Topics in LDA model")
Zusammenfassung
In diesem Lab haben wir gelernt, wie man Nichtnegative Matrixfaktorisierung und Latent Dirichlet Allokation auf einem Korpus von Dokumenten anwendet, um additive Modelle der Themensstruktur des Korpus zu extrahieren. Wir haben auch gelernt, wie man die Themen darstellt, wobei jeder als Balkendiagramm dargestellt wird, das die ersten paar Wörter basierend auf den Gewichten verwendet.