En este proyecto implementaremos el algoritmo de Agrupamiento Jerárquico en Python, analizaremos un conjunto de datos que contiene información sobre los montos de gasto anual de varios clientes de diversas categorías de productos para la estructura interna.
Nuestro objetivo es agrupar los datos para que podamos ver los productos que son comprados juntos por los clientes. Por ejemplo, si una persona va a la tienda a comprar algún comestible, es muy probable que también compre “leche”, por lo tanto podemos colocar la “leche” cerca de los comestibles de la tienda; de la misma manera es muy poco probable que la misma persona compre las verduras frescas al mismo tiempo.
Si podemos predecir este comportamiento del cliente, podemos organizar la tienda, en consecuencia aumentará las ventas de artículos.
El conjunto de datos de este proyecto se puede encontrar en Kaggle bajo el nombre de “Wholesale Customers data set”, el link es el siguiente: https://bit.ly/2KECiHq.
Como todo proyecto de Machine Learning, lo primero que vamos a hacer será importar las librerías que vamos a utilizar. Por los momentos solo importaremos las de Pandas, para manipular los datos y la de Matplotlib, para analizar visualmente los datos. Posteriormente importaremos las librerías correspondientes al algoritmo de agrupamiento, por los momentos nos enfocaremos a entender los datos.
#### IMPORTAR LAS LIBRERÍAS #### import pandas as pd import matplotlib.pyplot as plt
El siguiente paso es cargar los datos que vamos a utilizar. En este punto ya debiste haber descargado los datos de Kaggle y haberlos guardado en tu computador, como siempre recomiendo es preferible guardar estos datos en la misma carpeta en donde estamos guardando el programa, de esta forma será más fácil importarlos y trabajar con ellos.
Para importar los datos usamos la instrucción read_csv junto con el nombre del archivo en donde se encuentran los datos o, si es necesario, se debe incluir la ruta en donde se encuentran guardados.
Los datos se encuentran guardados dentro de la variable “data” por lo que el siguiente paso es analizarlos.
#### CARGAR LOS DATOS #### data = pd.read_csv('Wholesale customers data.csv')
Antes de realizar el análisis veamos de que se trata cada una de las columnas con las que cuenta el conjunto de datos.
La primera columna corresponde a “Channel” o Canal y se refiere al canal de clientes que vendría siendo hoteles, restaurantes o cafetería o canal de venta al por menor.
La segunda columna se refiere a la de “Region” o Región de venta, que sería Lisboa, Oporto u otra.
A partir de la tercera columna podemos encontrar la información que realmente nos interesa, que serían los productos que se venden. Recuerda que en cada columna nos mostrará los datos correspondientes al gasto anual de los productos correspondientes a cada categoría.
Comenzamos con “Fresh” o Fresco que son los productos frescos, como verduras o vegetales.
La siguiente columna es “Milk” o Leche correspondiente a los productos lácteos.
Seguidamente encontramos “Grocery” o Comestibles referente a todos los productos que consumimos.
La siguiente columna es “Frozen” o Congelados correspondiente a los alimentos congelados.
La penúltima columna se refiere a “Detergents Paper” o Papel y Detergentes que vendría siendo todos los productos detergentes y productos de papel.
La última columna corresponde a “Delicassen” o Delicateses referente a todos esos productos que no son incluidos en las categorías mencionadas anteriormente.
Realizado este análisis inicial ahora procedemos a analizar los datos utilizando instrucciones de Python.
Veamos primero la forma de los datos para esto utilizamos la instrucción “shape”. El conjunto de datos con los que trabajaremos cuenta con 440 filas o datos y 8 columnas que vendrían siendo las características.
#Conocer la forma de los datos data.shape
Recuerda que estamos trabajando en un proyecto de aprendizaje no supervisado por lo que acá el conjunto de datos no contará con una columna de variables dependientes o en todo caso “y”, acá todas las columnas serán variables independientes o “x”.
Seguidamente verificamos si el conjunto de datos con el que estamos trabajando cuenta con datos nulos, para esto implementamos las instrucciones de Python, “isnull()” y “sum()”, con esto verificamos si existen datos nulos y a su vez los sumamos en cada columna. Una vez ejecutado este código podemos observar que ninguna columna cuenta con datos perdidos por lo que no tenemos que realizar ningún procesamiento de datos al respecto.
#Conocer los datos nulos data.isnull().sum()
Por último, verificamos el formato de los datos de cada una de las columnas del conjunto de datos, para esto utilizamos la instrucción “dtypes”. Una vez ejecutado esta línea de código podemos observar que todos los datos son enteros, es decir numéricos, por lo que no tenemos que realizar ningún procesamiento especial sobre los mismos.
#Conocer el formato de los datos data.dtypes
En este punto ya debemos entender los datos con los que estamos trabajando.
Antes de realizar el procesamiento de los datos separemos tres filas que vendrían a ser nuestros datos de muestras, los cuales utilizaremos posteriormente para verificar en qué clúster pertenecen. Estos datos los elegimos al alzar, perfectamente tu puedes elegir otros, e inclusive más.
Como te lo mencione antes, recuerda que este es un problema de aprendizaje no supervisado, acá no contamos con datos para comparar los resultados que obtenemos por lo que debemos buscar alguna forma de ver y analizar el resultado para ello separamos estos datos para ver si corresponde a algún clúster que encontremos finalizado nuestro análisis.
Para realizar esto primero definimos las filas que utilizaremos como muestra, en mi caso he seleccionado la número 26, 176 y 392, recuerda que deberán ser números entre 0 y 400 que es número de datos con el que contamos.
Como te lo mencione anteriormente estos son datos al azar tu puedes seleccionar otros sin ningún problema.
Definido esto y almacenado en la variable “índice”, ahora procedemos a ubicar esta información en nuestro conjunto de datos y almacenarla en la variable “muestras”. Para realizar esto utilizamos la instrucción “loc” junto con los números de las filas definidas anteriormente, incluimos el nombre de cada una de las columnas y eliminamos el resto de la información.
En este momento ya tenemos en la variable “muestras” las tres filas que utilizaremos posteriormente para conocer a que clúster corresponde.
Finalmente eliminamos estas filas de nuestro conjunto de datos original para que el modelo no se entrene con esta información, por lo tanto utilizamos la instrucción “drop()” junto la variable “índices”, fíjate que acá utilizamos “axis” igual a 0, esto es porque estamos eliminando filas y no columnas como normalmente hacemos.
### DATOS DE MUESTRA ### #Se selecionan unos datos al azar para posteriormente verificar el clúster #al que pertenecen indices = [26, 176, 392] muestras = pd.DataFrame(data.loc[indices], columns = data.keys()).reset_index(drop = True) data = data.drop(indices, axis = 0)
En este punto ya entendemos los datos con los que estamos trabajando y hemos separado los datos correspondientes a la muestra por lo que podemos proceder a realizar el siguiente paso que es el de procesamiento de los datos.
El procesamiento de los datos consistirá en solamente dos acciones, la primera es eliminar las columnas que no afecta a nuestro análisis y la última acción será el escalamiento de los datos ya que si observas los datos se encuentran rangos muy variantes por lo que es conveniente realizar un procesamiento de los mismos.
El primer paso para el procesamiento de los datos es eliminar las columnas que no aporta alguna información importante para nuestro análisis y esas columnas corresponden a la región y el canal, estas dos características no son importantes para nuestro objetivo final que sería conocer las relaciones de los productos más vendidos, en caso que queramos conocer la región o el canal de venta si los deberías dejar e incluir en el análisis pero para nuestro caso esta información no es necesaria por lo tanto podemos eliminar ambas columnas.
Para eliminarlas solamente debemos utilizar la instrucción “drop” junto los nombres de ambas columnas, acá también podíamos utilizar la ubicación de las mismas, ambas opciones son correctas. Al eliminar ambas columnas ya nuestro conjunto de datos no cuenta con 8 columnas sino con 6.
Este mismo procedimiento lo debemos realizar con la variable “muestras”, ya que esta es un espejo a los datos con los que vamos a trabajar. Cualquier cambio que hagamos al conjunto de datos original también lo debemos hacer a este mini conjunto de lo contrario al momento de utilizarlo nos dará error.
### PROCESAMIENTO DE LOS DATOS ### #Eliminamos las columnas de región y canal data = data.drop(['Region', 'Channel'], axis = 1) muestras = muestras.drop(['Region', 'Channel'], axis = 1)
El siguiente paso es el de realizar el escalamiento de los datos. Si observas el conjunto de datos te podrás cuenta que los rangos de datos que se manejan son muy variantes y esto puede afectar el análisis cuando apliquemos el algoritmo, por lo que es conveniente realizar el escalamiento de los datos.
Para realizar esto importamos de “sklearn” el modulo correspondiente a “preprocessing”. Acá utilizamos “normalizer()” y “fit_transform” junto con el conjunto de datos para transformar los datos.
Fíjate que ahora nuestro conjunto de datos se llama data_escalada y como puedes observar los datos son flotantes y se encuentran en una misma escala.
Exactamente como hicimos en el paso anterior, debemos escalar los datos correspondientes a las “muestras”, ahora nuestras muestras se llamarán “muestras_escalada”.
#Se realiza el escalamiento de los datos from sklearn import preprocessing data_escalada = preprocessing.Normalizer().fit_transform(data) muestras_escalada = preprocessing.Normalizer().fit_transform(muestras)
En este punto ya tenemos nuestros datos listos para que podamos trabajar con ellos con nuestro algoritmo de agrupamiento.
Ha llegado el momento de realizar el análisis de Machine Learning y más específicamente aplicar el algoritmo de Agrupamiento Jerárquico.
Procedemos a determinar las variables a evaluar, para ello simplemente definimos la variable “X” igual a data_escalada. Esto lo hacemos simplemente para utilizar la variable “X” como siempre se realiza en los proyectos de Machine Learning.
#Se determina las variables a evaluar X = data_escalada
Por lo que ahora desarrollamos el primer paso que debemos hacer en cualquier proyecto de Kmeans y es el de hallar el valor óptimo de K. Recuerda que para el algoritmo Kmeans debemos indicar el valor de K, esto se debe hacer previamente antes de implementar el algoritmo.
Seguidamente debemos determinar el número de clústeres que vamos a evaluar, para este caso utilizaremos la gráfica de un dendrograma para determinar este valor.
Para obtener la gráfica importamos desde scipy.cluster.hierarchy el modulo shc. Fíjate que acá no estamos utilizando la librería Scikit Learn sino Scipy, ya que en esta última contamos con este método para realizar la gráfica respectiva.
Seguidamente definimos el tamaño de la figura, para nuestro caso colocamos 10 y 7. Tu puedes modificar el tamaño y colocar los valores que desees.
De igual forma, colocamos el nombre de la gráfica, por su puesto será Dendrogramas.
Finalmente, configuramos la grafica. Definimos dendrograma será igual a shc.dendrogram y dentro del paréntesis escribimos shc.linkage. Recuerda que linkage se refiere a las medidas de vinculación. Acá definimos los datos que vamos a graficar que serán X y método a utilizar, para nuestro caso será “Ward”.
#Se gráfica el dendrograma para obtener el número de clúster import scipy.cluster.hierarchy as shc plt.figure(figsize=(10, 7)) plt.title("Dendrogramas") dendrograma = shc.dendrogram(shc.linkage(X, method = 'ward'))
Si ejecutamos estas líneas de código nos muestra el dendrograma correspondiente.
Para determinar el número de clústeres debemos ubicar la línea vertical más larga de todas y que no tenga ningún cruce o sea cortada por otra. Para nuestro caso sería ésta, por lo tanto el número de clústeres será 3.
Fíjate que el número acá es distinto al que obtuvimos con el método del codo que representamos en un anterior video. Es decir, cada método podrá obtener un valor distinto al número de clústeres.
Definido el número de clústeres ya podemos implementar el algoritmo de Agrupamiento Jerárquico. Para esto importamos el módulo AgglomerativeClustering desde sklearn.cluster.
Utilizamos la variable “algoritmo” para configurar el algoritmo, expliquemos cada uno de los parámetros con que configuramos al algoritmo.
El primero es “n_cluster” que vendría siendo el número de clústeres que definimos previamente, para nuestro caso este valor será 3.
El siguiente parámetro es “affinity” que se refiere a las medidas de distancia, para nuestro caso utilizaremos la euclidiana.
El último parámetro que configuraremos será “linkage”, y se refiere a las medidas de vinculación, acá utilizaremos “Ward”.
Recuerda que cada uno de estos parámetros fueron explicados anteriormente, por lo que te recomiendo que revises esa información para que entiendas mejor lo que estamos explicando acá.
Definido el algoritmo y los parámetros del mismo ahora procedemos a entrenarlo junto con los datos que ya hemos procesado previamente y se encuentran almacenados en la variable “X”. Fíjate que acá se utiliza a instrucción “fit()” para entrenar el modelo, esta es la misma instrucción de los algoritmos de aprendizaje supervisado.
#Obtenido el número de clúster se procede a definir los clústeres from sklearn.cluster import AgglomerativeClustering #Se define el algoritmo junto con el valor de K algoritmo = AgglomerativeClustering(n_clusters = 3, affinity='euclidean', linkage='ward') #Se entrena el algoritmo algoritmo.fit(X) pred1 = algoritmo.fit_predict(X)
Ahora utilicemos los datos de muestras que separamos al principio para determinar a qué clúster pertenece.
Para esto simplemente utilizamos el modelo obtenido que se encuentra en la variable “algoritmo” y la instrucción “fit_predict()” junto con los datos de muestra que fueron escalados.
#Utilicemos los datos de muestras y verifiquemos en que cluster se encuentran muestra_prediccion = algoritmo.fit_predict(muestras_escalada) for i, pred in enumerate(muestra_prediccion): print( "Muestra", i, "se encuentra en el clúster:", pred)
En caso de que tengamos nuevos datos, tenemos que ingresarlos de la misma forma que hicimos con “muestras_escalada”, recuerda que esta información deberá estar escalada y en el mismo formato que esta variable.
A continuación el código completo:
""" Algoritmo Agrupamiento Jerárquico """ import pandas as pd import matplotlib.pyplot as plt #### CARGAR LOS DATOS #### data = pd.read_csv('Wholesale customers data.csv') ### ANALIZAR LOS DATOS ### #Conocer la forma de los datos data.shape #Conocer los datos nulos data.isnull().sum() #Conocer el formato de los datos data.dtypes #Se selecionan unos datos al azar para posteriormente verificar el clúster #al que pertenecen indices = [26, 176, 392] muestras = pd.DataFrame(data.loc[indices], columns = data.keys()).reset_index(drop = True) ### PROCESAMIENTO DE LOS DATOS ### #Eliminamos las columnas de región y canal data = data.drop(['Region', 'Channel'], axis = 1) muestras = muestras.drop(['Region', 'Channel'], axis = 1) #Se realiza el escalamiento de los datos from sklearn import preprocessing data_escalada = preprocessing.Normalizer().fit_transform(data) muestras_escalada = preprocessing.Normalizer().fit_transform(muestras) ### ANÁLISIS DE MACHINE LEARNING ### #Se determina las variables a evaluar X = data_escalada #Se gráfica el dendrograma para obtener el número de clúster import scipy.cluster.hierarchy as shc plt.figure(figsize=(10, 7)) plt.title("Dendrogramas") dendrograma = shc.dendrogram(shc.linkage(X, method = 'ward')) #Obtenido el número de clúster se procede a definir los clústeres from sklearn.cluster import AgglomerativeClustering #Se define el algoritmo junto con el valor de K algoritmo = AgglomerativeClustering(n_clusters = 3, affinity='euclidean', linkage='ward') #Se entrena el algoritmo algoritmo.fit(X) pred1 = algoritmo.fit_predict(X) #Utilicemos los datos de muestras y verifiquemos en que cluster se encuentran muestra_prediccion = algoritmo.fit_predict(muestras_escalada) for i, pred in enumerate(muestra_prediccion): print( "Muestra", i, "se encuentra en el clúster:", pred)
Te agradezco tu calidad profesional, me haz guiado durante dese el 2018 en el importante aprendizaje de ML. He aprendido mucho de ti. He sido y seguiré siendo una fiel seguidora tuya.
Hola Ana, muchas gracias por tus palabras. Me alegra que la información que publico te está ayudando en tu aprendizaje. Saludos.
Muy bien explicado
Muchas gracias Cesar. Saludos.
podrias realizarlo en no jerarquico
Hola Ruben, muchas gracias por tu recomendación, la tomare en cuenta. Saludos.