No creo poder hacer este código yo solo en este momento 😦
Alguien más ?
Introducción al curso
Lo que aprenderás sobre álgebra lineal: vectores
Vectores
Algunos objetos matemáticos: vectores y escalares
Convención en notación
Comienza a utilizar vectores en Python
Adición entre vectores
Suma de vectores en Python
Producto escalar-vector
Producto escalar-vector en Python
Producto interno
Producto interno en Python
Proyecto: análisis de sentimientos
Funciones lineales
Funciones lineales
Algunas funciones lineales
Un teorema en funciones lineales
Funciones afines
Aproximaciones de Taylor
Ejemplo en aproximaciones de Taylor
Un modelo de regresión
Norma y distancia
Cómo calcular distancias de vectores
Distancia entre vectores
Distancia entre vectores y búsqueda de departamento
Desviación estándar
Cálculo de riesgo en inversiones
Ángulo entre vectores y correlación
Clustering
¿Qué es y por qué clustering?
Una aproximación: K-Means
K-Means en Python
Cierre
Cierre y despedida
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Aportes 26
Preguntas 5
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:
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)
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)
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()
import numpy as np
import matplotlib.pyplot as plt
def Kmeans_alg(data, centroids):
iteration = 0
J_obj_vector = []
Stop = False
while Stop == False:
grouping = group_assignment(data, centroids)
new_centroids = update_centroid(data, grouping, centroids)
J_obj = clustering_objective(data, grouping, new_centroids)
J_obj_vector.append(J_obj)
iteration += 1
if np.linalg.norm(np.array(new_centroids) - np.array(centroids)) < 1e-6:
Stop = True
else:
centroids = new_centroids
return new_centroids, grouping, J_obj_vector, iteration
def group_assignment(data, centroids):
# Implementación de asignación de grupos
pass
def update_centroid(data, grouping, centroids):
# Implementación de actualización de centroides
pass
def clustering_objective(data, grouping, centroids):
J_obj = 0
for i in range(len(data)):
for j in range(len(centroids)):
if grouping[i] == (j+1):
J_obj += np.linalg.norm(data[i] - centroids[j])**2
J_obj = J_obj/len(data)
return J_obj
# Generar datos de muestra
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)]])
# Llamar a la función Kmeans_alg
centroids, _, _, _ = Kmeans_alg(X, X[:3])
# Graficar los puntos y los centroides
plt.scatter(X[:, 0], X[:, 1], label='Puntos')
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', marker='X', label='Centroides')
plt.legend()
plt.xlabel('Eje X')
plt.ylabel('Eje Y')
plt.title('Clustering con K-means')
plt.show()
print("Centroides:")
print(centroids)
Antes de ver, les comparto una implementación que hice en el curso de pensamiento probabilístico:
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
El reconocimiento de imagenes lo uso con la raspberry Pi, muy facil de implementar el projecto, con tensorflow y keras
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()
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).
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![](
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?