Как визуализировать точки данных векторов tf-idf для кластеризации kmeans?

У меня есть список документов и оценка tf-idf для каждого уникального слова во всем корпусе. Как мне визуализировать это на 2-мерном графике, чтобы оценить, сколько кластеров мне понадобится для запуска k-средних?

Вот мой код:

sentence_list=["Hi how are you", "Good morning" ...]
vectorizer=TfidfVectorizer(min_df=1, stop_words='english', decode_error='ignore')
vectorized=vectorizer.fit_transform(sentence_list)
num_samples, num_features=vectorized.shape
print "num_samples:  %d, num_features: %d" %(num_samples,num_features)
num_clusters=10

Как видите, я могу преобразовать свои предложения в матрицу документа tf-idf. Но я не уверен, как построить точки данных для оценки tf-idf.

Я думал:

  1. Добавьте больше переменных, таких как длина документа и что-то еще
  2. сделать PCA, чтобы получить 2 измерения

Спасибо


person jxn    schedule 15.12.2014    source источник
comment
Этот вопрос, вероятно, должен быть в науке о данных, а не в stackoverflow?   -  person fnl    schedule 17.01.2015


Ответы (4)


В настоящий момент я делаю нечто подобное, пытаясь построить в 2D-графике оценки tf-idf для набора данных текстов. Мой подход, аналогичный предложениям в других комментариях, заключается в использовании PCA и t-SNE из scikit-learn.

import matplotlib.pyplot as plt
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE

num_clusters = 10
num_seeds = 10
max_iterations = 300
labels_color_map = {
    0: '#20b2aa', 1: '#ff7373', 2: '#ffe4e1', 3: '#005073', 4: '#4d0404',
    5: '#ccc0ba', 6: '#4700f9', 7: '#f6f900', 8: '#00f91d', 9: '#da8c49'
}
pca_num_components = 2
tsne_num_components = 2

# texts_list = some array of strings for which TF-IDF is being computed

# calculate tf-idf of texts
tf_idf_vectorizer = TfidfVectorizer(analyzer="word", use_idf=True, smooth_idf=True, ngram_range=(2, 3))
tf_idf_matrix = tf_idf_vectorizer.fit_transform(texts_list)

# create k-means model with custom config
clustering_model = KMeans(
    n_clusters=num_clusters,
    max_iter=max_iterations,
    precompute_distances="auto",
    n_jobs=-1
)

labels = clustering_model.fit_predict(tf_idf_matrix)
# print labels

X = tf_idf_matrix.todense()

# ----------------------------------------------------------------------------------------------------------------------

reduced_data = PCA(n_components=pca_num_components).fit_transform(X)
# print reduced_data

fig, ax = plt.subplots()
for index, instance in enumerate(reduced_data):
    # print instance, index, labels[index]
    pca_comp_1, pca_comp_2 = reduced_data[index]
    color = labels_color_map[labels[index]]
    ax.scatter(pca_comp_1, pca_comp_2, c=color)
plt.show()



# t-SNE plot
embeddings = TSNE(n_components=tsne_num_components)
Y = embeddings.fit_transform(X)
plt.scatter(Y[:, 0], Y[:, 1], cmap=plt.cm.Spectral)
plt.show()
person gorjanz    schedule 01.02.2017
comment
Отлично. Как пометить точки по их имени на диаграмме разброса? - person SVK; 07.09.2019
comment
Если кто-то хочет выполнить PCA на разреженных представлениях, TruncatedSVD от sklearn создан специально для этой цели. - person Ender; 21.02.2021

PCA - это один из подходов. Для TF-IDF я также использовал пакет Scikit Learn для нелинейного уменьшения размеров. Одна вещь, которую я считаю полезной, - это маркировать мои очки на основе результатов TF-IDF.

Вот пример (нужно вставить свою реализацию TF-IDF в начале):

from sklearn import manifold

# Insert your TF-IDF vectorizing here

##
# Do the dimension reduction
##
k = 10 # number of nearest neighbors to consider
d = 2 # dimensionality
pos = manifold.Isomap(k, d, eigen_solver='auto').fit_transform(.toarray())

##
# Get meaningful "cluster" labels
##
#Semantic labeling of cluster. Apply a label if the clusters max TF-IDF is in the 99% quantile of the whole corpus of TF-IDF scores
labels = vectorizer.get_feature_names() #text labels of features
clusterLabels = []
t99 = scipy.stats.mstats.mquantiles(X.data, [ 0.99])[0]
clusterLabels = []
for i in range(0,vectorized.shape[0]):
    row = vectorized.getrow(i)
    if row.max() >= t99:
        arrayIndex = numpy.where(row.data == row.max())[0][0]
        clusterLabels.append(labels[row.indices[arrayIndex]])
    else:
        clusterLabels.append('')
##
# Plot the dimension reduced data
##
pyplot.xlabel('reduced dimension-1')
pyplot.ylabel('reduced dimension-2')
for i in range(1, len(pos)):
    pyplot.scatter(pos[i][0], pos[i][1], c='cyan')
    pyplot.annotate(clusterLabels[i], pos[i], xytext=None, xycoords='data', textcoords='data', arrowprops=None)

pyplot.show()
person andrew    schedule 15.01.2015
comment
Я только что заметил, что ваш рисунок из заслуживающих доверия и / или официальных источников предостерегает. Я пока оставлю свой исходный ответ, но, возможно, заменим его, чтобы получить более академический ответ. - person andrew; 15.01.2015

Я полагаю, вы искали t-SNE Ван дер Маатена и Хинтона.

Публикация: http://jmlr.org/papers/volume9/vandermaaten08a/vandermaaten08a.pdf < / а>

person fnl    schedule 17.01.2015


В соответствии с вашим требованием вы можете построить свой scipy.sparse.csr.csr_matrix

TfidfVectorizer.fit_transform () даст вам (идентификатор документа, номер термина) оценку tf-idf. теперь вы можете создать матрицу numpy по сроку в качестве оси x и документ в качестве оси Y, второй вариант - построить (temm, tf-tdf score) или вы можете построить 3-d с помощью (срок, документ, частота) здесь вы также можете применить PCA.

Просто создайте матрицу numpy из scipy.sparse .csr.csr_matrix и используйте matplotlib.

person aibotnet    schedule 11.01.2015
comment
Не могли бы вы показать код, как это сделать с помощью первого и / или второго метода? - person jxn; 27.01.2015