2014-12-15 21 views
7

Ho un elenco di documenti e il punteggio tf-idf per ogni parola univoca nell'intero corpus. Come visualizzo quello su una trama 2-d per darmi un indicatore di quanti cluster avrò bisogno di eseguire k-means?Come faccio a visualizzare i punti dati dei vettori tf-idf per il clustering dei kmea?

Ecco il mio codice:

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 

Come potete vedere, io sono in grado di trasformare le mie frasi in una matrice documento TF-IDF. Ma non sono sicuro di come tracciare i punti dati del punteggio tf-idf.

Stavo pensando:

  1. aggiungere più variabili, come la lunghezza del documento e qualcos'altro
  2. fanno PCA per ottenere una potenza di 2 dimensioni

Grazie

+0

Questa domanda probabilmente dovrebbe essere in datascience, non stackoverflow? – fnl

risposta

1

Secondo il vostro requisito puoi tracciare il tuo scipy.sparse.csr.csr_matrix

TfidfVectorizer.fit_transform() ti darà (id documento, no termine) punteggio tf-idf. ora puoi creare una matrice numpy per termine come asse x e documentare come asse y, la seconda opzione è tracciare (temm, tf-tdf score) o puoi tracciare 3-d con (termine, documento, frequenza) qui puoi anche applicare PCA.

Basta creare una matrice numpy da scipy.sparse.csr.csr_matrix e utilizzare matplotlib.

+0

Puoi mostrare del codice su come farlo con il primo e/o il secondo metodo? – jxn

4

PCA è un approccio. Per TF-IDF ho anche utilizzato il multiplo package di Scikit Learn per la riduzione della dimensione non lineare. Una cosa che trovo utile è quella di etichettare i miei punti in base ai punteggi TF-IDF.

Ecco un esempio (necessità di inserire l'implementazione TF-IDF all'inizio):

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() 
+0

Ho appena notato il tuo "richiamo da credibili e/o fonti ufficiali". Per ora lascerò la mia risposta originale, ma potrei sostituirla avere il tempo di generare una risposta più accademica. – andrew

2

Sto facendo qualcosa di simile in questo momento, cercando di tracciare in 2D, tf-idf i punteggi per un set di dati di testo. Il mio approccio, simile ai suggerimenti di altri commenti, è l'utilizzo di PCA e t-SNE da parte di 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()