Confundido acerca de cómo aplicar KMeans en mi conjunto de datos con características extraídas
-
16-10-2019 - |
Pregunta
Estoy intentando aplicar un uso básico del paquete scikitlearn KMeans Clustering, para crear diferentes clusters que podría usar para identificar una determinada actividad.Por ejemplo, en mi conjunto de datos a continuación, tengo diferentes eventos de uso (0,...,11) y cada evento tiene la potencia utilizada y la duración.
Basado en el Wattage
, Duration
, y timeOfDay
, Me gustaría agruparlos en diferentes grupos para ver si puedo crear grupos y clasificar manualmente las actividades individuales de cada grupo.
Estaba teniendo problemas con el paquete KMeans porque creo que mis valores debían estar en forma de números enteros.Y luego, ¿cómo trazaría los grupos en un diagrama de dispersión?Sé que necesito colocar los puntos de datos originales en el gráfico y luego tal vez pueda separarlos por color del grupo.
km = KMeans(n_clusters = 5)
myFit = km.fit(activity_dataset)
Wattage time_stamp timeOfDay Duration (s)
0 100 2015-02-24 10:00:00 Morning 30
1 120 2015-02-24 11:00:00 Morning 27
2 104 2015-02-24 12:00:00 Morning 25
3 105 2015-02-24 13:00:00 Afternoon 15
4 109 2015-02-24 14:00:00 Afternoon 35
5 120 2015-02-24 15:00:00 Afternoon 49
6 450 2015-02-24 16:00:00 Afternoon 120
7 200 2015-02-24 17:00:00 Evening 145
8 300 2015-02-24 18:00:00 Evening 65
9 190 2015-02-24 19:00:00 Evening 35
10 100 2015-02-24 20:00:00 Evening 45
11 110 2015-02-24 21:00:00 Evening 100
Editar:Aquí está el resultado de una de mis ejecuciones de K-Means Clustering.¿Cómo interpreto las medias que son cero?¿Qué significa esto en términos del grupo y las matemáticas?
print (waterUsage[clmns].groupby(['clusters']).mean())
water_volume duration timeOfDay_Afternoon timeOfDay_Evening \
clusters
0 0.119370 8.689516 0.000000 0.000000
1 0.164174 11.114241 0.474178 0.525822
timeOfDay_Morning outdoorTemp
clusters
0 1.0 20.821613
1 0.0 25.636901
Solución
Para la agrupación, sus datos deben ser números enteros.Además, dado que k-means utiliza una distancia euclidiana, tener una columna categórica no es una buena idea.Por lo tanto, también debes codificar la columna. timeOfDay
en tres variables ficticias.Por último, no olvides estandarizar tus datos.Puede que esto no sea importante en su caso, pero en general, corre el riesgo de que el algoritmo se oriente en la dirección con los valores más grandes, que no es lo que desea.
Así que descargué sus datos, los puse en .csv e hice un ejemplo muy simple.Puede ver que estoy usando un marco de datos diferente para la agrupación en sí y luego, una vez que recupero las etiquetas del grupo, las agrego a la anterior.
Tenga en cuenta que omito la marca de tiempo variable; dado que el valor es único para cada registro, solo confundirá el algoritmo.
import pandas as pd
from scipy import stats
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('C:/.../Dataset.csv',sep=';')
#Make a copy of DF
df_tr = df
#Transsform the timeOfDay to dummies
df_tr = pd.get_dummies(df_tr, columns=['timeOfDay'])
#Standardize
clmns = ['Wattage', 'Duration','timeOfDay_Afternoon', 'timeOfDay_Evening',
'timeOfDay_Morning']
df_tr_std = stats.zscore(df_tr[clmns])
#Cluster the data
kmeans = KMeans(n_clusters=2, random_state=0).fit(df_tr_std)
labels = kmeans.labels_
#Glue back to originaal data
df_tr['clusters'] = labels
#Add the column into our list
clmns.extend(['clusters'])
#Lets analyze the clusters
print df_tr[clmns].groupby(['clusters']).mean()
Esto puede decirnos cuáles son las diferencias entre los grupos.Muestra los valores medios del atributo por cada grupo.Parece que el grupo 0 son personas nocturnas con alto consumo, mientras que el 1 son personas matutinas con bajo consumo.
clusters Wattage Duration timeOfDay_Afternoon timeOfDay_Evening timeOfDay_Morning
0 225.000000 85.000000 0.166667 0.833333 0.0
1 109.666667 30.166667 0.500000 0.000000 0.5
También pediste visualización.Esto es complicado, porque todo lo que está por encima de dos dimensiones es difícil de leer.Entonces puse un diagrama de dispersión. Duration
contra Wattage
y coloreé los puntos según el grupo.
Puedes ver que parece bastante razonable, excepto el punto azul que hay allí.
#Scatter plot of Wattage and Duration
sns.lmplot('Wattage', 'Duration',
data=df_tr,
fit_reg=False,
hue="clusters",
scatter_kws={"marker": "D",
"s": 100})
plt.title('Clusters Wattage vs Duration')
plt.xlabel('Wattage')
plt.ylabel('Duration')