No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Reg铆strate

Comienza en:

5D
3H
58M
14S

K-Means en Python

27/28
Recursos

Aportes 24

Preguntas 5

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

No creo poder hacer este c贸digo yo solo en este momento 馃槮
Alguien m谩s ?

Esta es la forma en la que use el array A[1] para poder diferenciar los grupos que se forman:

# Guardo en las listas G_1, G_2 y G_3 la posicion en la que estan los valores 1,2 o 3 de mi array A[1]
G_1 = []
G_2 = []
G_3 = []
for i in range(len(A[1])):
    if A[1][i] == 1:
        G_1.append(i)
    elif A[1][i] == 2:
        G_2.append(i)
    elif A[1][i] == 3:
        G_3.append(i)
        
# Separar los datos para poder graficarlos
X_1 = [X[:,0][G_1[i]] for i in range(len(G_1))]
Y_1 = [X[:,1][G_1[i]] for i in range(len(G_1))]

X_2 = [X[:,0][G_2[i]] for i in range(len(G_2))]
Y_2 = [X[:,1][G_2[i]] for i in range(len(G_2))]

X_3 = [X[:,0][G_3[i]] for i in range(len(G_3))]
Y_3 = [X[:,1][G_3[i]] for i in range(len(G_3))]

Para graficarlo:

fig,ax = plt.subplots(1,1,figsize=(7,7),dpi=100)

ax.scatter( X_1, Y_1, color='red', label='Grupo 1')
ax.scatter( X_2, Y_2, color='blue', label='Grupo 2')
ax.scatter( X_3, Y_3, color='black', label='Grupo 3')
ax.set_xlim(-1.5,2.5)
ax.set_ylim(-2,2)
plt.legend()
plt.show()

![](

import pandas as pd
import matplotlib.pyplot as plt

clusters = list(zip(X,A[1]))

df = pd.DataFrame(clusters,columns=["Vectores","k"])
k = df.groupby("k")
k1 = k.get_group(1).iloc[:,0]
k2 = k.get_group(2).iloc[:,0]
k3 = k.get_group(3).iloc[:,0]

grupo1 = np.array([k1]).astype(float).reshape(101,2)
grupo2 = np.array([k2]).astype(float).reshape(99,2)
grupo3 = np.array([k3]).astype(float).reshape(100,2)

fig,ax = plt.subplots(1,1,figsize=(7,7),dpi=120)
ax.scatter( grupo1[:,0],grupo1[:,1], color='red',label='Grupo1')
ax.scatter( grupo2[:,0],grupo2[:,1], color="green", label = 'Grupo2')
ax.scatter( grupo3[:,0],grupo3[:,1], color="black", label = ' Grupo3')
ax.set_xlim(-1.5,2.5)
ax.set_ylim(-2,2)
plt.legend()
plt.show()

A mi al correr de nuevo el algoritmo me dio esta distribucion de puntos:

![](

Aqui la soluci贸n para el dataset fetch_openml
Me base en el c贸digo del google colab, solo le cambie me peque帽as cosas.

Me tard贸 bastante en procesar, y pense que no me cargar铆a, asi que lo deje un largo tiempo, despues de 30 iteracioes este es mi resultado.

from sklearn.datasets import fetch_openml
import random

X, y = fetch_openml('mnist_784', version=1, return_X_y=True)
import itertools
a = list(itertools.product(range(3),range(3)))
X_array = np.array(X)
X_array.shape
A = Kmeans_alg(X_array,random.choices(X_array,k=9))
fig, ax = plt.subplots(3,3,figsize=(7,7),dpi=120)
for i,j in zip(a,A[0]):
        ax[i[0]][i[1]].imshow(j.reshape(28,28))
plt.show()

Para gr谩ficar los grupos, les recomiendo usar pandas y la librer铆a seaborns.

import pandas as pd 
import seaborn as sns

gruping = A[1].reshape(-1,1)
arr = np.concatenate((X, gruping),axis=1)

df = pd.DataFrame(arr,columns=['x', 'y', 'group'])

fig,ax= plt.subplots(1,1,figsize=(7,7),dpi=300)
sns.scatterplot(x='x',y='y',hue='group',data=df, palette='deep')
for i in A[0]:
    ax.scatter(i[0],i[1],c='black',linewidths=3)
plt.show()

La verdad no se si dejarlo como aporte o como pregunta porque no se el fetch_openml me regreso un DataFrame en lugar de un arreglo de Numpy, adem谩s yo pensaba que as铆 como trabajaba con Numpy lo pod铆a hacer con Pandas pero no me dejo. Tuve que revisar el tipo de dato que me regresaba para darme cuenta de eso, para poder cambiar de Pandas a Numpy lo que hice fue:

X = np.array(X)

La verdad es algo simple pero me tarde bastante para darme cuenta jajajaja. Aun as铆 pude obtener los resultados aunque tardo m谩s de 7 minutos en obtener los centroides.

En el caso de los colores fue sencillo porque lo primero que hice fue hacer un arreglo booleano para cada grupo de la siguiente manera:

red = A[1]==1
blue = A[1]==2
green = A[1]==3

Despu茅s utilizando esos arreglos hice tres arreglos diferentes para definir cada cluster de la siguiente manera:

X_red=Y[red]
X_blue=Y[blue]
X_green=Y[green]

Y finalmente realic茅 la gr谩fica. Dejo mi archivo que realic茅 en Deepnote para el proyecto final. Me encantar铆a recibir sus sugerencias.

Mi codigo de grafica:

  1. Creo una lista con la cantidad de grupos
  2. Pregunto cual esta en cada lista y la agrego a un sub-indice de gropus
groups = [ [] for i in range(len(A[0]))]
for i in range(len(groups)):
  for j in range(len(A[1])):
    if A[1][j] == i+1:
      groups[i].append(j)
  1. Creo 2 listas grandes, allx y ally que van a contener a todos los X y Y de cada sub-lista
allx = []
for j in range(len(groups)):
  val = [X[:,0][groups[j][i]] for i in range(len(groups[j]))]
  allx.append(val)

ally = [ ]
for j in range(len(groups)):
  val = [X[:,1][groups[j][i]] for i in range(len(groups[j]))]
  ally.append(val)
  1. Grafico, iterando igualmente con len(groups)
fig,ax = plt.subplots(1,1,figsize=(7,7),dpi=100)
for i in range(len(groups)):
    ax.scatter(allx[i], ally[i])
plt.show()

Todo esta mas claro en mi notebook 鈾

Bueno el ultimo reto demora en procesar sera motivo para investigar la librer铆a fetchopenml

import numpy as np 
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_openml
import itertools
import random

def group_assignment(data, centroids):
    grouping_vec_c = np.zeros((len(data)))
    for i in range(len(data)): # recorrido de toda la data
        dist = np.zeros(len(centroids))
        for j in range(len(centroids)): # recorrido de centroides en este caso son 3 para obtener la distancia con cada centroide
            dist[j] = np.linalg.norm(data[i] - centroids[j]) # vector dist contiene las distancias de cada vector de data con cada centroide.
        min_dist = min(dist)        # min_dist contiene la distancia minima del versos data - centroides
        for j in range(len(centroids)): # con este for encontramos el indice de la distancia minima ubicada en ese vector con el dato actual
            if min_dist == dist[j]:
                grouping_vec_c[i] = j + 1 # al vector grouping_vec_c que esta vinculado al vector data  se le asigna un grupo segun cercania a los centriodes 1, 2, y 3
    return grouping_vec_c


def update_centroid(data, grouping, centroids):
    new_centroids = []
    for i in range(len(centroids)): # bucle para recorrer los centroides
        cent = np.zeros(len(data[0])) # porque nbo hacer un np.zeros(1)
        count = 0
        for j in range(len(data)): # bucle para para recorrer la daa
            if grouping[j] == i + 1:    # compara si el vector de grupos grouping_vec_c asociado a lo vector data comparado con su grupo.
                cent = cent + data[j]
                count += 1
        group_average =  cent/count # vector promedio de cada grupo asociado a cada centroide
        new_centroids.append(group_average) # nuevo vector de centroides es el promedio de cada grupo de centroides
    return new_centroids

def clustering_objetive(data, grouping, centroids):
    J_obj = 0
    for i in range (len(data)):     # recorre data
        for j in range(len(centroids)): # recorre centroides
            if grouping[i] == j + 1:    # compara cada grupo de data asignado al vector grouping_vec_c
                J_obj += np.linalg.norm(data[i] - centroids[j])**2 # obtiene la suma de las distancias entre el vetor centroide y su grupo de datos asignados
    J_obj = J_obj/len(data) #promedio de la suma de distancias vinculadas a a todos los centroides
    return J_obj    # promedio de distancias


def Kmeans_alg(data, centroids):
    iteration = 0
    J_obj_vector = []
    Stop = False
    while Stop == False:
        grouping = group_assignment(data, centroids) # ingresamos data y centroides para obtener el vector grouping vinculando el vector data a cada grupo
        new_centroids = update_centroid(data, grouping, centroids) # Ingresamos datam grouping y centroids para obtener el nuevo vector de centroides
        J_obj = clustering_objetive(data, grouping, new_centroids)  # Ingresamos data, grouping y new_centroids para obtener el promedio de distancias dato de grupo vs centroide de grupo
        J_obj_vector.append(J_obj) # Vector J_Obj almacena el promedio de distancias por grupo-centroide
        iteration +=1
        if np.linalg.norm(np.array(new_centroids) - np.array(centroids)) < 1e-6: #compara la distancia entre centroides viejos vs los nuevos centroides para ver si se mueven poco
            Stop = True
        else:
            centroids = new_centroids   
    return new_centroids, grouping, J_obj_vector, iteration

if __name__ == '__main__':

    fig,ax = plt.subplots(1,1,figsize=(7,7),dpi=120)
    X = np.concatenate([[0.3*np.random.randn(2) for i in range(100)],\
                        [[1,1] + 0.3*np.random.randn(2) for i in range(100)], \
                        [[1,-1]+ 0.3* np.random.randn(2) for i in range(100)]])
    ax.scatter( X[:,0],X[:,1])
    ax.set_xlim(-1.5,2.5)
    ax.set_ylim(-2,2)
    #plt.show()

    A = Kmeans_alg(X, X[:3])
    fig, ax = plt.subplots(1, 1, figsize=(7,7),dpi=120)
    plt.plot(list(range(A[-1])), A[2])
    #plt.show()

    grouping = A[1]
    
    v_grupo1 = []
    v_grupo2 = []
    v_grupo3 = []

    fig, ax = plt.subplots(1, 1, figsize=(7,7), dpi=100)
    for i, d_val in enumerate(X):
        if grouping[i] == 1:
            v_grupo1.append(d_val)
        elif grouping[i] == 2:
            v_grupo2.append(d_val)
        elif grouping[i] == 3:
            v_grupo3.append(d_val)

    x1, y1 = zip(*v_grupo1)
    x2, y2 = zip(*v_grupo2)
    x3, y3 = zip(*v_grupo3)
    
    ax.scatter(x1, y1, color='red', label='Grupo 1')     
    ax.scatter(x2, y2, color='blue', label='Grupo 2') 
    ax.scatter(x3, y3, color='green', label='Grupo 3')  

    ax.set_xlim(-1.5,2.5)
    ax.set_ylim(-2,2)
    plt.legend()
    plt.show()

    # B, y = fetch_openml('mnist_784', version=1, return_X_y=True)
    
    # A = Kmeans_alg(B, random.choices(B,k=9))
    # a = list(itertools.product(list(range(3)),list(range(3))))
    # fig, ax = plt.subplots(3,3,figsize=(7,7),dpi=120)
    # for i,j in zip(a,A[0]):
    #         ax[i[0]][i[1]].imshow(j.reshape(28,28))

    # plt.show()

Creamos una lista de colores

ListColor = []
for i in range(len(A[1])):
  if A[1][i]==1.0:
    ListColor.append('red')
  if A[1][i]==2.0:
    ListColor.append('green')
  if A[1][i]==3.0:
    ListColor.append('blue')

Y luego lo agregamos cuando imprimamos los elementos

fig,ax = plt.subplots(1,1,figsize=(7,7),dpi=120)
ax.scatter( X[:,0],X[:,1],color=ListColor)
ax.set_xlim(-1.5,2.5)
ax.set_ylim(-2,2)
plt.show()

Antes de ver, les comparto una implementaci贸n que hice en el curso de pensamiento probabil铆stico:

github.com/Erik-Lopez/kmeans-implementation

Hola, en la versi贸n actual de pandas existe un problema con el m茅todo reshape, por lo que debemos utilizar el m茅todo .values.reshape para poder ingresar los valores a nuestro algoritmo. Tambi茅n hay que utilizar la b煤squeda por 铆ndice con .iloc

A continuaci贸n los cambios para poder utilizar los algoritmos

import random
X_reshape = [ X.iloc[i].values.reshape(28,28) for i in range(len(X))]
C = kmeans(X_reshape,random.choices(X_reshape,k=10))

Luego los resultados fueron

https://circuitdigest.com/microcontroller-projects/raspberry-pi-based-emotion-recognition-using-opencv-tensorflow-and-keras

El reconocimiento de imagenes lo uso con la raspberry Pi, muy facil de implementar el projecto, con tensorflow y keras

RETO 1

G1 = np.array([X[i] for i in range(len(X)) if A[1][i] == 1])
G2 = np.array([X[i] for i in range(len(X)) if A[1][i] == 2])
G3 = np.array([X[i] for i in range(len(X)) if A[1][i] == 3])

fig,ax = plt.subplots(1,1,figsize=(7,7),dpi=120)
ax.scatter( G1[:,0], G1[:,1], color="red", label='Grupo 1')
ax.scatter( G2[:,0], G2[:,1], color="blue", label='Grupo 2')
ax.scatter( G3[:,0], G3[:,1], color="green", label='Grupo 3')
ax.set_xlim(-1.5,2.5)
ax.set_ylim(-2,2)
plt.legend()
plt.show()

RETO 2

Este reto fue muy interesante. Lo primero es que fue necesario hacer esto X=np.array(X) para que el c贸digo funcionara con el dataset de los n煤meros, ya que X era de tipo dataframe en lugar de un arreglo de numpy. La clusterizaci贸n se realiza en 10 grupos (lo 10 digitos).

from sklearn.datasets import fetch_openml
import matplotlib.pyplot as plt
import numpy as np
import random
import itertools

X, y = fetch_openml('mnist_784', version=1, return_X_y=True)
X=np.array(X)
A = Kmeans_alg(X,random.choices(X,k=10))
a = list(itertools.product(list(range(3)),list(range(4))))

fig, ax = plt.subplots(3,4,figsize=(7,7),dpi=120)
for i,j in zip(a,A[0]):
        ax[i[0]][i[1]].imshow(j.reshape(28,28))
plt.show()

obteniendo lo siguiente:

esto que vemos es el grupo de vectores representativos, por eso es que se ven algo difusos, ya que fue la mejor adaptaci贸n que el algoritmo encontr贸. Tambien podemos notar que la clusterizaci贸n no es lo suficientemente buena para este caso, ya que repite n煤meros como el 1, adem谩s de que le cuesta diferenciar el n煤mero 4 y 5. Y bueno, el 7 ni aparece por ah铆 XD.


Hice otro c贸digo para ver si estimaba correctamente los n煤meros. Le pedi que me mostrara los primeros n煤meros que reconociera como un tres

a partir de esto estimo una eficiencia de aproximadamente 60% para detectar el n煤mero tres .

Con el n煤mero seis le fue mucho mejor.
El c贸digo que us茅 es el siguiente:

G1 = np.array([X[i] for i in range(len(X)) if A[1][i] == 3])
b = list(itertools.product(list(range(4)),list(range(4))))

fig, ax = plt.subplots(4,4,figsize=(7,7),dpi=120)
for i,j in zip(b,G1):
        ax[i[0]][i[1]].imshow(j.reshape(28,28))
plt.show()

OJO! el vector A[1] (el cual me indica a qu茅 cluster se asign贸 cada vector) no necesariamente coincide con el n煤mero que se busca hallar (parece obvio pero yo tambien tuve la duda).

Reto 1

Hola a todos comparto mi soluci贸n al reto propuesto en esta clase. Fue laborioso pero aprend铆 mucho:

Este es el c贸digo con el que agrupe:

position= A[1]
point= X
g_1= []
g_2= []
g_3= []

for indice, valor in enumerate(point):
  if position[indice] == 1:
    g_1.append(valor)
  elif position[indice] == 2:
    g_2.append(valor)
  elif position[indice] == 3:
    g_3.append(valor)

g_1= np.array(g_1)
g_2= np.array(g_2)
g_3= np.array(g_3)

Este fue el c贸digo con el que grafique:

fig,ax  = plt.subplots(1,1,figsize=(7,7),dpi=120)
ax.scatter(g_1[:,0],g_1[:,1], linestyle='dashed',label='Grupo 1',color="black")
ax.scatter(g_2[:,0],g_2[:,1], linestyle='dashed',label='Grupo 2',color="orange")
ax.scatter(g_3[:,0],g_3[:,1], linestyle='dashed',label='Grupo 3',color="brown")
ax.set_xlabel('A')
ax.set_ylabel('B')
ax.legend()
ax.set_xlim(-1.5,2.5)
ax.set_ylim(-2,2)
plt.show()

Esta fue la gr谩fica resultante:

Reto 2 de la clase: Obtenci贸n de vectores principales para dibujar del 0 al 9.

Reto de visualizaci贸n de vectores de acuerdo a los vectores.

Paso 1:Poner los datos en un dataframe

df_cluster=pd.DataFrame([list(X[:,0]),list(X[:,1]),list(A[1])])
df_cluster=df_cluster.T
df_cluster[2]=df_cluster[2].astype('int')
df_cluster[2]=df_cluster[2].astype('str')
df_cluster=df_cluster.rename(columns={0: "V1.1", 1:"V1.2",2: "GR"})
df_cluster.head()

Paso 2: Graficar

fig,ax = plt.subplots(1,1,figsize=(7,7),dpi=120)
colorres = {'1':'red', '2':'green', '3':'blue'}

grouped = df_cluster.groupby('GR')
for key, group in grouped:
    keys=str(key)
    group.plot(ax=ax, kind='scatter', x='V1.1', y='V1.2', label=key, color=colorres[keys])

plt.show()

ax.set_xlim(-1.5,2.5)
ax.set_ylim(-2,2)
ax.legend()
plt.show()

C贸digo para seccionar los cluster por colores

fig,ax = plt.subplots(1,1,figsize=(7,7),dpi=120)

colores = []
for x,a in zip(X,A[1]):
    if a == 1.:
        a = 'red'
    if a == 2.:
        a = 'blue'
    if a == 3.:
        a = 'green'
    colores.append(a)
    
ax.scatter(X[:,0],X[:,1],color=colores)

ax.set_xlim(-1.5,2.5)
ax.set_ylim(-2,2)
plt.show()```

Adjunto mi imagen 馃槈

mi soluci贸n para el grafico de los grupos 馃

A = Kmeans_alg(X,X[:3])
B=A[1]
g1=[]
g2=[]
g3=[]
for grupo in range(len(B)):
  if B[grupo]==1:
    g1.append([X[grupo,0],X[grupo,1]])
  elif B[grupo]==2:
    g2.append([X[grupo,0],X[grupo,1]])
  elif B[grupo]==3:
    g3.append([X[grupo,0],X[grupo,1]])
g1=np.array(g1)
g2=np.array(g2)
g3=np.array(g3)

fig,ax = plt.subplots(1,1,figsize=(7,7),dpi=100)
ax.scatter(g1[:,0],g1[:,1], color="blue", label='G1')
ax.scatter(g2[:,0],g2[:,1], color="red", label="G2")
ax.scatter(g3[:,0],g3[:,1], color="green", label="G3")
ax.set_xlim(-1.5,2.5)
ax.set_ylim(-2,2)
plt.legend()
plt.show()
colors = A[1]
fig,ax = plt.subplots(1,1,figsize=(7,7),dpi=120)
X = np.concatenate([[0.3*np.random.randn(2) for i in range(100)],\
                    [[1,1] + 0.3*np.random.randn(2) for i in range(100)], \
                    [[1,-1]+ 0.3* np.random.randn(2) for i in range(100)]])
ax.scatter( X[:,0],X[:,1], c= colors, label= colors)
ax.set_xlim(-1.5,2.5)
ax.set_ylim(-2,2)
plt.show()```

Mi codigo para graficar los clusters con colores

color_arr = ('red','blue','green')
fig, ax = plt.subplots(1,1,figsize=(7,7),dpi=120)
cluster_matrix = [[] for i in range(int(np.max(A[1])))]

for i in range(len(X)):
  idx = int(A[1][i]-1)
  cluster_matrix[idx].append(X[i])

for (i,cluster) in enumerate(cluster_matrix):
  cluster = np.asarray(cluster)
  ax.scatter(cluster[:,0],cluster[:,1], c=color_arr[i])
# Grafica los centroides con una x morada
ax.scatter(np.asarray(A[0])[:,0], np.asarray(A[0])[:,1], marker='X', s=70, c = 'purple')

Tengo una duda en la funcion update_centroid()
la siguiente linea de c贸digo

cent = np.zeros(len(data[0]))

porque no solo ponerle [0,0] si siempre da lo mismo, o es se utiliza para algo mas?

As铆 me qued贸 con colores![](