J'essaie de calculer silhouette score
car je trouve le nombre optimal de clusters à créer, mais j'obtiens une erreur qui dit:
ValueError: Number of labels is 1. Valid values are 2 to n_samples - 1 (inclusive)
Je n'arrive pas à comprendre la raison de cela. Voici le code que j'utilise pour regrouper et calculer silhouette score
.
J'ai lu le csv qui contient le texte à regrouper et j'exécute K-Means
sur les valeurs du cluster n
. Quelle pourrait être la raison pour laquelle j'obtiens cette erreur?
#Create cluster using K-Means
#Only creates graph
import matplotlib
#matplotlib.use('Agg')
import re
import os
import nltk, math, codecs
import csv
from nltk.corpus import stopwords
from gensim.models import Doc2Vec
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.metrics import silhouette_score
model_name = checkpoint_save_path
loaded_model = Doc2Vec.load(model_name)
#Load the test csv file
data = pd.read_csv(test_filename)
overview = data['overview'].astype('str').tolist()
overview = filter(bool, overview)
vectors = []
def split_words(text):
return ''.join([x if x.isalnum() or x.isspace() else " " for x in text ]).split()
def preprocess_document(text):
sp_words = split_words(text)
return sp_words
for i, t in enumerate(overview):
vectors.append(loaded_model.infer_vector(preprocess_document(t)))
sse = {}
silhouette = {}
for k in range(1,15):
km = KMeans(n_clusters=k, max_iter=1000, verbose = 0).fit(vectors)
sse[k] = km.inertia_
#FOLLOWING LINE CAUSES ERROR
silhouette[k] = silhouette_score(vectors, km.labels_, metric='euclidean')
best_cluster_size = 1
min_error = float("inf")
for cluster_size in sse:
if sse[cluster_size] < min_error:
min_error = sse[cluster_size]
best_cluster_size = cluster_size
print(sse)
print("====")
print(silhouette)
L'erreur est produite parce que vous avez une boucle pour un nombre différent de clusters n
. Lors de la première itération, n_clusters
Est 1
et cela conduit à all(km.labels_ == 0)
à True
. =
En d'autres termes, vous n'avez qu'un seul cluster avec l'étiquette (ainsi, np.unique(km.labels_)
imprime array([0], dtype=int32)
).
silhouette_score
nécessite plus de 1 étiquettes de cluster. Cela provoque l'erreur. Le message d'erreur est clair.Exemple:
from sklearn import datasets
from sklearn.cluster import KMeans
import numpy as np
iris = datasets.load_iris()
X = iris.data
y = iris.target
km = KMeans(n_clusters=3)
km.fit(X,y)
# check how many unique labels do you have
np.unique(km.labels_)
#array([0, 1, 2], dtype=int32)
Nous avons 3 clusters/labels de cluster différents.
silhouette_score(X, km.labels_, metric='euclidean')
0.38788915189699597
La fonction fonctionne bien.
Maintenant, causons l'erreur:
km2 = KMeans(n_clusters=1)
km2.fit(X,y)
silhouette_score(X, km2.labels_, metric='euclidean')
ValueError: Number of labels is 1. Valid values are 2 to n_samples - 1 (inclusive)
De la documentation,
Notez que le coefficient de silhouette n'est défini que si le nombre d'étiquettes est 2 <= n_labels <= n_samples - 1
Donc, une façon de résoudre ce problème est au lieu d'utiliser for k in range(1,15)
, essayez de démarrer l'itération à partir de k = 2, qui est for k in range(2,15)
. Ça marche pour moi.