Fundamentos prácticos

1

Aplica Platzidoro en este curso y asegura el éxito de tu aprendizaje

2

Los fundamentos de machine learning que aprenderás

3

Introducción a Numpy

4

Introducción y manipulación de datos con Pandas

5

Introducción a ScikitLearn

6

Comandos básicos de las librerías usadas en el curso (Numpy, Pandas y ScikitLearn)

Regresión Lineal y Logística

7

¿Qué es la predicción de datos?

8

Sobreajuste y subajuste en los datos

9

Regresión lineal simple y regresión lineal múltiple

10

Regresión lineal simple con Scikit-Learn: división de los datos

11

Regresión lineal simple con Scikit-Learn: creación del modelo

12

Regresión logística con Scikit-Learn: definición y división de datos

13

Regresión logística con Scikit-Learn: evaluación del modelo

14

Matriz de confusión

15

PlatziDoro Cápsula 1

Árboles de decisión

16

¿Qué es un árbol de decisión y cómo se divide?

17

Comprendiendo nuestro data set para la creación de un árbol de decisión

18

Creando un clasificador con Scikit-Learn

19

Entrenamiento del modelo de clasificación

20

Visualización del árbol de decisión

K-Means

21

¿Qué es K-Means?

22

Cargando el data set de Iris

23

Construcción y evaluación del modelo con K-Means

24

Graficación del modelo

25

PlatziDoro Cápsula 2

Aprendizaje profundo

26

Introducción al aprendizaje profundo

27

Conceptos básicos de Tensor Flow

28

Red neuronal convolucional

29

Conociendo el set de datos para la creación de la red neuronal

30

Crea y entrena tu primera red neuronal convolucional con Tensor Flow

31

Evaluación de la red convolucional

32

PlatziDoro Cápsula 3

Despedida

33

Recomendaciones para analizar correctamente tu problema

34

Siguientes pasos para continuar aprendendiendo de Machine Learning

Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Graficación del modelo

24/34
Recursos

Aportes 38

Preguntas 7

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Buenas tardes a todos, para aquellos que obtuvieron una precisión del 36-37% (al menos para este caso en particular) es debido a que trabajaron con los datos directamente sin estandarizarlos previamente (estoy seguro que el tema de estandarización será tratado en clases posteriores, así que no teman). Haciendo uso de la estandarización pude obtener una precisión de 0.89. A continuación, dejo mi código para que puedan observar la estandarización de datos.

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import datasets
from sklearn import metrics
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler #Necesario para la estandarizacion de los datos

Descarga de los datos de Vinos

vinos = datasets.load_wine()
variables = np.array(vinos.feature_names)
x_vinos = vinos.data
y_vinos = vinos.target

Normalizacion de los valores de “X”

scaler = StandardScaler()
scaler.fit(vinos.data)
x_scaled = scaler.transform(vinos.data)
x = pd.DataFrame(x_scaled, columns=variables, ) #Si deseas trabajar con los datos sin estandarizar, solo cambia x_scaled por x_vinos
y = pd.DataFrame(y_vinos, columns= ["Target"])
x.head(5)

Elaboracion del Modelo y Metodo del Codo

wccs =[]
n = 1
acc = 0
for i in range(1, 11):
    codo = KMeans(n_clusters = i, max_iter = 1000, random_state = 0)
    codo.fit(x)
    y_kmeans = codo.predict(x)
    wccs.append(codo.inertia_)
    accuracy =  round(metrics.adjusted_rand_score(y_vinos, y_kmeans), 4)
    print(f'Cantidad de Centroides: {i} ---  Precision: {accuracy}')
    if accuracy > acc:
        acc = accuracy
        n = i
plt.plot(range(1, 11), wcss)
plt.title('Metodo del Codo')
plt.xlabel('Numero de centroides')
plt.ylabel('WCSS')
plt.show()
print(f"Se recomienda emplear una cantidad de {n} centroides, para asi garantizar una precision de {acc}")


Ejecucion del modelo KMeans con la cantidad de centroides seleccionados

modelo = KMeans(n_clusters = n, max_iter = 1000)
modelo.fit(x)
y_labels = modelo.labels_
y_kmeans = modelo.predict(x)
print('predicciones ', y_kmeans)
y_kmeans_df = pd.DataFrame(y_kmeans, columns = ['Prediction'])

Precision

accuracy =  metrics.adjusted_rand_score(y_vinos, y_kmeans)
print(round(accuracy, 5))

Vizualizacion del modelo

# Concateno el dataset de entrada con el de la prediccion
Z = pd.concat([x, y_kmeans_df], axis = 1)
# Grafico
sns.pairplot(Z, hue = 'Prediction')

En el dataset de vinos, la razón por la que debemos normalizar los datos antes de aplicar el modelo es porque estamos trabajando con datos que miden diferentes cosas, como la intensidad del color, la alcalinidad, el grado de alcohol, etc, estos son valores que no pueden ser comparados entre sí (es como sumar peras con manzanas) y por eso se debe estandarizar, es decir, aplicar un proceso estadístico que hace que todos los datos se ajusten a una curva de distribución normal y se situen en una misma escala que permita su comparacion, por eso es que el accuracy aumenta desde un 36-37%, hasta un 89%. Pueden leer más sobre la estandarización aquí.

Creo que esto nos deja una lección más de lo importante que es conocer nuestros datos antes empezar a trabajar con ellos

Hola comparto mi código para el dataset de wine

from sklearn import metrics
from sklearn.cluster import KMeans
from sklearn import datasets
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# Cargamos informacion de wines
wines = datasets.load_wine()

# Separamos nuestra dataset
X_wines = wines.data
Y_wines = wines.target

# Llevo los datos a una estructura de DataFrame
xw = pd.DataFrame(X_wines, columns = ['Alcohol', 'Malic Acid', 'Ash', 'Alcalinity of Ash', 'Magnesium', 
                                      'Total Phenols', 'Flavanoids', 'Nonflavanoid Phenols', 'Proanthocyanins', 
                                      'Colour Intensity', 'Hue', 'OD280/OD315 of diluted wines', 'Proline'])
yw = pd.DataFrame(Y_wines, columns = ['Target'])
xw.head(5)

# Ploteo para encontrar el numero de clusters de acuerdo a 
# metodo del codo
wcss = []
for i in range(1, 11):
    kmeans = KMeans(n_clusters=i, max_iter=1000, random_state=0)
    kmeans.fit(xw)
    yw_kmeans = kmeans.predict(xw)
    wcss.append(kmeans.inertia_)
    accuracy =  metrics.adjusted_rand_score(Y_wines, yw_kmeans)
    print(f'numero de n_clusters: {i} accurracy {accuracy}')
plt.plot(range(1, 11), wcss)
plt.title('ELBOW METHOD')
plt.xlabel('NUMBER OF CLUSTERS')
plt.ylabel('WCSS')
plt.show()
# Aplico el modelo de KMeans
modelw = KMeans(n_clusters = 3, max_iter = 1000)
modelw.fit(xw)
yw_labels = modelw.labels_
yw_kmeans = modelw.predict(xw)
print('predicciones ', yw_kmeans)
yw_kmeans_df = pd.DataFrame(yw_kmeans, columns = ['Prediction'])

# Precisión del modelo
accuracyw =  metrics.adjusted_rand_score(Y_wines, yw_kmeans)
print(accuracyw)

# Concateno el dataset de entrada con el de la prediccion
Z = pd.concat([xw, yw_kmeans_df],axis=1)

# Grafico para ver relación de las features con respecto a las 
# valores de la predicción, poniendo color según (0,1,2) 
# considerando las tres clases.
sns.pairplot(Z, hue = 'Prediction')

Para lo que obtengo la siguiente gráfica, aqui no se ve depronto muy claro pero en el colab se ve bien:

Aqui se puede ver la relacion interesante que hay entre la feature proline con las clases y las demas features.

Adjunto codigo con los estandarizados, el cual hace pasar el modelo del 37% al 89%

<h1>Ejemplo de Vinos</h1>
from sklearn.cluster import KMeans
from sklearn import datasets
from sklearn import metrics

import pandas as pd
import matplotlib.pyplot as plt

%matplotlib inline

from sklearn.preprocessing import StandardScaler #Necesario para la estandarizacion de los datos

wine = datasets.load_wine()
wine

scaler = StandardScaler()
scaler.fit(wine.data)
x_scaler = scaler.transform(wine.data)

nombre_columnas = wine.feature_names

#x = pd.DataFrame(wine.data, columns=nombre_columnas)
x = pd.DataFrame(x_scaler, columns=nombre_columnas)
y = pd.DataFrame(wine.target, columns=['Target'])

x

El DataFrame generado por pandas tiene un tamaño de 178 filas por 13 columnas.

x_plot = x['alcohol']
y_plot = x['color_intensity']

plt.scatter(x_plot, y_plot, c='b')
plt.xlabel('Cantidad de Alcohol')
plt.ylabel('Intensidad del Color')

plt.show()

model = KMeans(n_clusters=3, max_iter=1000)
model.fit(x)

y_kmeans = model.predict(x)

precision = metrics.adjusted_rand_score(wine.target, y_kmeans)
precision

  • n_clusters=2 -> 0.3694
  • n_clusters=3 -> 0.3711
  • n_clusters=4 -> 0.3034
  • n_clusters=5 -> 0.3115
  • n_clusters=6 -> 0.2909
  • n_clusters=7 -> 0.2209
  • n_clusters=8 -> 0.1978
  • n_clusters=9 -> 0.1739
x_plot = x['alcohol']
y_plot = x['color_intensity']

plt.scatter(x_plot, y_plot, c=y_kmeans, s=30)
plt.xlabel('Cantidad de Alcohol')
plt.ylabel('Intensidad del Color')

plt.show()

Se concluye que no hay relacion entre la cantidad de alcohol que tiene un vino y la intensidad de su color 😦

Si estandarizamos los datos (???) podemos obtener una precision del 89% aproximadamente.

scaler = StandardScaler()
scaler.fit(wine.data)
x_scaler = scaler.transform(wine.data)
### WINE ANALYSIS

wine = datasets.load_wine()
wine

x = pd.DataFrame(wine.data, columns=wine.feature_names)
y = pd.DataFrame(wine.target, columns=["Target"])

corr = x.corr()
corr.style.background_gradient(cmap='coolwarm')

plt.scatter(x['flavanoids'],x['total_phenols'], s=30)
plt.xlabel('flavanoids',fontsize=10)
plt.ylabel('total_phenols',fontsize=10)
plt.show()

model = KMeans(n_clusters=3,max_iter=1000)
model.fit(x)

y_labels = model.labels_

acuracy = metrics.adjusted_rand_score(wine.target, y_labels)
print(acuracy)

##### 0.37111371823084754

new_x = x[["flavanoids","total_phenols","malic_acid","hue","od280/od315_of_diluted_wines"]]
model = KMeans(n_clusters=3,max_iter=1000)
model.fit(new_x)

y_labels = model.labels_

acuracy = metrics.adjusted_rand_score(wine.target, y_labels)
print(acuracy)

###### 0.47627086172451033

plt.scatter(x['flavanoids'],x['total_phenols'], c=y_labels,s=30)
plt.xlabel('flavanoids',fontsize=10)
plt.ylabel('total_phenols',fontsize=10)
plt.show()

Les comparto como resolví el reto.

wines = datasets.load_wine()
x = wines.data
y = wines.target
x = pd.DataFrame(x, columns=wines.feature_names)
WSS = []
for i in range(1,10):
  model = KMeans(n_clusters = i , max_iter = 1000)
  model.fit(x)
  WSS.append(model.inertia_)
  print('Accuracy: ', metrics.adjusted_rand_score(y, model.predict(x)

Mi output fue.

Accuracy:  0.0 WSS: 17592296.383508474
Accuracy:  0.3694075388574537 WSS: 4543749.614531862
Accuracy:  0.37111371823084754 WSS: 2370689.686782968
Accuracy:  0.3196724933068579 WSS: 1337429.7347864588
Accuracy:  0.31158801033176253 WSS: 916379.187153917
Accuracy:  0.29090227688418224 WSS: 647326.0020260847
Accuracy:  0.2209596701158363 WSS: 412303.82825080137
Accuracy:  0.19843744177983885 WSS: 323211.55263465445
Accuracy:  0.17441376056983432 WSS: 271873.0632650521

Con lo que procedi a aplicar el metodo de codo.

plt.figure(facecolor='white')
plt.plot(range(1,10),WSS,'r-',alpha = 0.3)
plt.xlabel('Numero de cluster')
plt.ylabel('WSS')
plt.title('Metodo de Elbow')

Obteniendo.

Asi que la mejor cantidad de clusters era3.

model = KMeans(n_clusters = 3 , max_iter = 1000)
model.fit(x)

Realice la comparacion entre graficas.

plt.figure(facecolor='lightgreen')
plt.scatter(x['alcohol'],x['proanthocyanins'], c=model.predict(x) , s = 30, alpha = 0.4)
plt.xlabel('Petal Length', fontsize = 10)
plt.ylabel('Peta Width', fontsize = 10)
plt.figure(facecolor='lightgreen')
plt.scatter(x['alcohol'],x['proanthocyanins'], c=y , s = 30, alpha = 0.4)
plt.xlabel('Petal Length', fontsize = 10)
plt.ylabel('Peta Width', fontsize = 10)

Me dió muy bajo el %, supongo que es porque como no se mucho de vinos no pude escojer los parametros adecuados o cual seria la mejor solucion?


import pandas as pd
from sklearn import datasets
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

wines = datasets.load_wine()

x_wines = wines.data
y_wines = wines.target

 x = pd.DataFrame(wines.data, columns=wines.feature_names)
 y = pd.DataFrame(wines.target, columns=['Target'])
 x.head()

plt.scatter(x['total_phenols'],x['proline'], c='blue')
plt.xlabel('total_phenols')
plt.ylabel('proline')
plt.show()

model = KMeans(n_clusters=3, max_iter=1000)
model.fit(x)
y_labels = model.labels_

y_kmeans = model.predict(x)

from sklearn import metrics

accuracy = metrics.adjusted_rand_score(y_wines,y_kmeans)

accuracy
#0.37111371823084754

plt.scatter(x['total_phenols'],x['proline'], c=y_kmeans, s=30)
plt.xlabel('total_phenols', fontsize=10)
plt.ylabel('proline', fontsize=10)
plt.show()

ma da una eficiencia de 37.6 % MALISIMO


RETO:

Usando PCA podria mejorar la clusterizacion!

Hola. Intente hacer el reto con datos propios y me genero una duda. Cuando se comenzó el modulo de K-Means, Yecely hablo que es un algoritmo no supervisado (sin etiqueta o target) por lo que me genera la duda:
Como puedo yo medir el Accuracy de mi modelo si yo no tengo target?

O estoy encarando el problema de una manera errónea?

aqui estan los resultados.



from sklearn.cluster import KMeans
from sklearn import datasets
import pandas as pd

import matplotlib.pyplot as plt

wine = datasets.load_wine() # load_wines
#  wine

X_wine = wine.data
Y_wine = wine.target

x = pd.DataFrame(wine.data, columns =wine.feature_names)
y = pd.DataFrame(wine.target, columns = ['Target'])
x.head(5)

	alcohol 	malic_acid 	ash 	alcalinity_of_ash 	magnesium 	total_phenols 	flavanoids 	nonflavanoid_phenols 	proanthocyanins 	color_intensity 	hue 	od280/od315_of_diluted_wines 	proline
0 	14.23 	1.71 	2.43 	15.6 	127.0 	2.80 	3.06 	0.28 	2.29 	5.64 	1.04 	3.92 	1065.0
1 	13.20 	1.78 	2.14 	11.2 	100.0 	2.65 	2.76 	0.26 	1.28 	4.38 	1.05 	3.40 	1050.0
2 	13.16 	2.36 	2.67 	18.6 	101.0 	2.80 	3.24 	0.30 	2.81 	5.68 	1.03 	3.17 	1185.0
3 	14.37 	1.95 	2.50 	16.8 	113.0 	3.85 	3.49 	0.24 	2.18 	7.80 	0.86 	3.45 	1480.0
4 	13.24 	2.59 	2.87 	21.0 	118.0 	2.80 	2.69 	0.39 	1.82 	4.32 	1.04 	2.93 	735.0

feature2 = 'proline'
feature1 = 'hue'

plt.scatter(x[feature1], x[feature2], c = 'blue')
plt.xlabel(feature1, fontsize = 10)
plt.ylabel(feature2, fontsize = 10)

Text(0, 0.5, 'proline')

#  Construcción y evaluación del modelo con K-Means
#  unsupervised learning

model = KMeans(n_clusters = 3, max_iter = 1000)
model.fit(x)
y_labels = model.labels_

y_kmeans = model.predict(x)
print('Predicciones', y_kmeans)

Predicciones [1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 1 1 2 2 1 1 2 1 1 1 1 1 1 2 2
 1 1 2 2 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 2 0 2 0 0 2 0 0 2 2 2 0 0 1
 2 0 0 0 2 0 0 2 2 0 0 0 0 0 2 2 0 0 0 0 0 2 2 0 2 0 2 0 0 0 2 0 0 0 0 2 0
 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 2 0 0 2 2 2 2 0 0 0 2 2 0 0 2 2 0 2
 2 0 0 0 0 2 2 2 0 2 2 2 0 2 0 2 2 0 2 2 2 2 0 0 2 2 2 2 2 0]

from sklearn import metrics

accuracy = metrics.adjusted_rand_score(Y_wine, y_kmeans)
print(accuracy)

0.37111371823084754

#  Graficacion del modelo 
plt.scatter(x[feature1], x[feature2], c = y_kmeans, s= 30)
plt.xlabel(feature1, fontsize = 10)
plt.ylabel(feature2, fontsize = 10)

Text(0, 0.5, 'proline')


Solo acotar algo adicional al comentario que hicieron sobre estandarizar o escalar los datos antes de aplicar un modelo.
Hay varios tipos de estandarización, puedo mencionar 4 de ellos:

StandarScaler - NO es recomendado cuando tienes outliers
RobustScaler - SI es recomendado cuando tienes outliers
MinMaxScaler - NO es recomendado cuando tienes outliers
MaxAbsScaler - NO es recomendado cuando tienes outliers
La razón de porque uso RobustScaler y porque si es recomendado con outliers, es que este es aplicado usando la mediana, en cambio StandardScaler es usado con la media, si revisamos bien los datos, nos fijaremos que algunos features tienen outliers, y estos podrían darnos un mal resultado, en este caso eran pocos, y no afecta mucho al resultado, pero es algo a tener en cuenta cuando vayamos a realizar un trabajo profesional, les dejo mi repositorio por si se desean revisarlo.

Github

Si quieren graficar en seaborn les dejo para que puedan ver como funciono el KMeans

<code> 
sns.scatterplot(data=X  ,x="SepalLengthCm", y="SepalWidthCm", hue=prediction)

HICE EL RETO !!! UN SALUDO DESDE EL SALVADOR, LA CRIPTO NACION

from sklearn.cluster import KMeans
import numpy as np
from sklearn import datasets
import pandas as pd

import matplotlib.pyplot as plt
from sklearn import metrics

DATOS = datasets.load_wine()

DataTarget = DATOS.target

col_list = DATOS.feature_names
DataToTrain = pd.DataFrame(DATOS.data, columns = col_list)
print(col_list)

K_optimo = 0;
Mejor = 0

for K in range(2,8):

# Variamos K
model = KMeans(n_clusters= K, max_iter=1000) 

#Se entrena modelo
model.fit(DataToTrain)  

y_labels = model.labels_ 

#Creamos prediccion
y_kmeans = model.predict(DataToTrain) 

# Revisamos la precicion del modelo
accuracy = metrics.adjusted_rand_score(DataTarget, y_kmeans) 
print(K,' ',accuracy)

if accuracy > Mejor:    
    K_optimo = K
    Mejor = accuracy

print(’’)
print(f’Max accuracy: {round(Mejor,3)}% \nUsando K: {K_optimo} ')

Salida
[‘alcohol’, ‘malic_acid’, ‘ash’, ‘alcalinity_of_ash’, ‘magnesium’, ‘total_phenols’, ‘flavanoids’, ‘nonflavanoid_phenols’, ‘proanthocyanins’, ‘color_intensity’, ‘hue’, ‘od280/od315_of_diluted_wines’, ‘proline’]

2 0.3694075388574537
3 0.37111371823084754
4 0.303442531578347
5 0.31158801033176253
6 0.2909022768841822
7 0.22632105878612552

Max accuracy: 0.371%
Usando K: 3

#COMO SABEMOS QUE OPTIMO ES 3
#Aunque su exactitude es muy bajo 37%
#Grafico aleatoriamente variables alcohol y hue

K = 3

model = KMeans(n_clusters= K, max_iter=1000)
model.fit(DataToTrain)

y_labels = model.labels_

#Creamos prediccion
y_means = model.predict(DataToTrain)

plt.scatter(DataToTrain[‘alcohol’], DataToTrain[‘hue’], c=y_means, s=30)
plt.xlabel(‘Alcohol’, fontsize = 10)
plt.ylabel(‘Hue’, fontsize = 10)

(NO SALE EL GRAFICO)

Justo me hice la misma pregunta, sobre como incrementar el accuracy del modelo. Encontre entre los comentarios el tip de estandarizar los datos antes de entrenar el modelo. Y ya en código, antes de entrenar el modelo, realice los siguientes pasos que me ayudaron a tener un incremento hasta el .89

import matplotlib.pyplot as plt
import pandas as pd
from sklearn.cluster import KMeans
from sklearn import datasets
from sklearn import metrics
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import StandardScaler

x_cols = wine_data.feature_names
y_cols = wine_data.target_names

scaler = StandardScaler()
x_scaled = scaler.fit_transform(x_wine)

x = pd.DataFrame(x_scaled, columns = x_cols)
y = pd.DataFrame(wine_data.target, columns = ['Target'])

model = KMeans(n_clusters = 3, max_iter = 100000)
model.fit(x)

Y como adicional, encontré en está página, cómo generar un gráfico en 3D que nos permite ver el cruce de 3 variables, agrupando con k-means: 3D Scatter

Mi código quedó de la siguiente manera:

fig = plt.figure()
ax = fig.add_subplot(projection='3d')

plt.title('3D Scatter plot with K-Means', fontsize = 18)
ax.set_xlabel('Alcohol', fontsize = 8)
ax.set_ylabel('Malic Acid', fontsize = 8)
ax.set_zlabel('Alcalinity of hash', fontsize = 8)
ax.scatter(x['alcohol'], x['malic_acid'], x['alcalinity_of_ash'], c = y_kmeans, marker='o')

hola! si quieren visualizar los datos les dejo este link super útil 😃

esta gráfica, por ejemplo, indica que la prolina es bastante importante para determinar el tipo de vino

“Estás teniendo un sobreajuste porque estás tratando de que memorice la información, no que aprenda de la información”

Con esa frase me quedaron claras muchas cosas sobre el aprendizaje pero en el humano, que funciona de forma parecida.

Deben permitirnos analizar grandes casos y abstraerlos.
Y a veces los métodos de ciertos profesores no se prestan a un aprendizaje adecuado en sus alumnos

Resultado final 0.87, seguramente algunos obtuvimos un valor menor inicialmente, hay técnicas de normalización de datos que pueden aplicarse a estos problemas

dejo mi colab notebook para que puedan consultar el código:
https://colab.research.google.com/drive/1YtNgGxUdKkKtVcYh_ZmCGnOFgQYBQFQG?usp=sharing

Mi solución:

from sklearn.cluster import KMeans
from sklearn import datasets
import pandas as pd
import matplotlib.pyplot as plt

wine = datasets.load_wine()
x_wine = wine.data
y_wine = wine.target

wine.feature_names

['alcohol',
 'malic_acid',
 'ash',
 'alcalinity_of_ash',
 'magnesium',
 'total_phenols',
 'flavanoids',
 'nonflavanoid_phenols',
 'proanthocyanins',
 'color_intensity',
 'hue',
 'od280/od315_of_diluted_wines',
 'proline']

x = pd.DataFrame(wine.data, columns= ['alcohol',
 'malic_acid',
 'ash',
 'alcalinity_of_ash',
 'magnesium',
 'total_phenols',
 'flavanoids',
 'nonflavanoid_phenols',
 'proanthocyanins',
 'color_intensity',
 'hue',
 'od280/od315_of_diluted_wines',
 'proline'])
y = pd.DataFrame(wine.target, columns= ['Target'])
print(x.head())
print(y.head())


 alcohol  malic_acid   ash  ...   hue  od280/od315_of_diluted_wines  proline
0    14.23        1.71  2.43  ...  1.04                          3.92   1065.0
1    13.20        1.78  2.14  ...  1.05                          3.40   1050.0
2    13.16        2.36  2.67  ...  1.03                          3.17   1185.0
3    14.37        1.95  2.50  ...  0.86                          3.45   1480.0
4    13.24        2.59  2.87  ...  1.04                          2.93    735.0

[5 rows x 13 columns]
   Target
0       0
1       0
2       0
3       0
4       0

plt.scatter(x['alcohol'], x['color_intensity'], c='blue')
plt.xlabel('Alcohol', fontsize=15)
plt.ylabel('Color intensity', fontsize=15)
![image1kmeans.png](https://static.platzi.com/media/user_upload/image1kmeans-eada8d87-0ff1-4ff7-87c1-01e898cafe2c.jpg)

model = KMeans(n_clusters=3, max_iter=10000)
model.fit(x)
y_labels = model.labels_

y_kmeans = model.predict(x)
print('Predicciones: ', y_kmeans)

accuracy = metrics.adjusted_rand_score(y_wine, y_kmeans)
print('accuracy: ', accuracy)

accuracy: 0.37111371823084754

plt.scatter(x['alcohol'], x['color_intensity'], c=y_kmeans, s=30)
plt.xlabel('Alcohol', fontsize=15)
plt.ylabel('Color Intensity', fontsize=15)

![image1kmeans2.png](https://static.platzi.com/media/user_upload/image1kmeans2-38d0ace9-24c5-4da4-ba7f-62bf6ac694c7.jpg)

Pero si probamos dos caracteristicas diferentes:

plt.scatter(x['total_phenols'], x['proline'], c=y_kmeans, s=30)
plt.xlabel('total_phenols', fontsize=15)
plt.ylabel('proline', fontsize=15)

![image1kmeans3.png](https://static.platzi.com/media/user_upload/image1kmeans3-550ff854-782b-47f3-86d6-d3b1c142999d.jpg)

Les tengo una propuesta sobre el modelo trabajado:

x = x.iloc[:,2:]

Averiguen ustedes que pasa con la precisión y como separa las especies ahora

Parece que hacer clusters por alcohol y acido malico no es muy buena opcion … 😃

![](
![](
![](

hola, yo ‘‘resolví’’ el reto reciclando el código que nos mostró en el vídeo profe, pero no logro que la predicción sea de mas de 36~37 %

el codigo:

from sklearn.cluster import KMeans
from sklearn import datasets
import pandas as pd
import matplotlib.pyplot as plt
dt = datasets.load_wine()
dt.feature_names

[‘alcohol’,
‘malic_acid’,
‘ash’,
‘alcalinity_of_ash’,
‘magnesium’,
‘total_phenols’,
‘flavanoids’,
‘nonflavanoid_phenols’,
‘proanthocyanins’,
‘color_intensity’,
‘hue’,
‘od280/od315_of_diluted_wines’,
‘proline’]

x_wine = dt.data
y_wine = dt.target
x = pd.DataFrame(x_wine, columns = ['alcohol','malic_acid','ash','alcalinity_of_ash','magnesium','total_phenols','flavanoids','nonflavanoid_phenols','proanthocyanins','color_intensity','hue','od280/od315_of_diluted_wines','proline'])
y = pd.DataFrame(dt.target, columns = ['Target'])
x.head(10)
plt.scatter(x['malic_acid'], x['proline'], c='green')
plt.xlabel('malic_acid', fontsize = 10)
plt.ylabel('proline', fontsize = 10)
model = KMeans(n_clusters= 3, max_iter= 1000)
model.fit(x)
y_labels = model.labels_
y_kmeans = model.predict(x)
print('Predicciones ', y_kmeans)
from sklearn import metrics

accuracy = metrics.adjusted_rand_score(y_iris, y_kmeans)
print(accuracy)
plt.scatter(x['malic_acid'], x['proline'], c=y_kmeans, s= 30)
plt.xlabel('malic_acid', fontsize = 10)
plt.ylabel('proline', fontsize = 10)
![](data:image/png;base64,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%0AAAAASUVORK5CYII=)

Realicé el ejercicio y obtuve un Accuracy del 89 - 90% usando las categorias ‘color_intensity’ y ‘alcohol’ (probé con varias y con esta obtuve el mejor resultado), la recomendación de Diego Medina es muy importante y que ciertamente no se ha tocado muy a profundidad hasta este punto; comparto mi código por si alguno está interesado en checkarlo.

<import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import datasets
from sklearn import metrics
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler #Necesario para la estandarizacion de los datos

X_wines = wines.data
Y_wines = wines.target


scaler = StandardScaler()
scaler.fit(wines.data)
x_scaled = scaler.transform(wines.data)

x = pd.DataFrame(wines.data, columns=['alcohol',
  'malic_acid',
  'ash',
  'alcalinity_of_ash',
  'magnesium',
  'total_phenols',
  'flavanoids',
  'nonflavanoid_phenols',
  'proanthocyanins',
  'color_intensity',
  'hue',
  'od280/od315_of_diluted_wines',
  'proline'])

x = pd.DataFrame(x_scaled, columns=['alcohol',
  'malic_acid',
  'ash',
  'alcalinity_of_ash',
  'magnesium',
  'total_phenols',
  'flavanoids',
  'nonflavanoid_phenols',
  'proanthocyanins',
  'color_intensity',
  'hue',
  'od280/od315_of_diluted_wines',
  'proline'])

y = pd.DataFrame(wines.target, columns=['Target'])


plt.scatter(x['color_intensity'], x['alcohol'], c='red')
plt.xlabel('alcohol', fontsize = 10 )
plt.ylabel('color_intensity', fontsize = 10 )

model = KMeans(n_clusters=3, max_iter=10000)
model.fit(x)
y_labels = model.labels_
y_kmeans = model.predict(x)
print('Predicciones', y_kmeans)
accuracy = metrics.adjusted_rand_score(Y_wines, y_kmeans)
print('Accuracy = ', accuracy)

plt.scatter(x['color_intensity'], x['alcohol'], c=y_kmeans)
plt.xlabel('alcohol', fontsize = 10 )
plt.ylabel('color_intensity', fontsize = 10 )





>

En este ejemplo no se ha utilizado una estandarizacion para los parámetros, por eso la precisión es de tan solo el 37%

<h1>K-Means</h1>

from sklearn.cluster import KMeans
from sklearn import datasets

import pandas as pd
import matplotlib.pyplot as plt

%matplotlib inline

iris = datasets.load_iris()

El dataset iris viene incluido con SciKitLearn

x_iris = iris.data
y_iris = iris.target

x = pd.DataFrame(iris.data, columns=[‘Sepal Length’, ‘Sepal Width’, ‘Petal Length’, ‘Petal, Width’])
y = pd.DataFrame(iris.target, columns=[‘Target’])

x.head(5)

plt.scatter(x[‘Petal Length’], x[‘Petal, Width’], c=‘b’)
plt.xlabel(‘Petal Length’, fontsize=10)
plt.ylabel(‘Petal Width’, fontsize=10)

plt.show()

model = KMeans(n_clusters=3, max_iter=1000)
model.fit(x)

y_label = model.labels_

Al inicion se definio a n_cluester=2 como valor inicial para comprobar como funciona el algoritmo kmeans. Luego este valor se reemplazara por su valor verdadero.

  • n_cluester=2 me da una presicion del 0.5399
  • n_cluester=3 me da una presicion del 0.7302
  • n_cluester=4 me da una presicion del 0.6498
  • n_cluester=5 me da una presicion del 0.6078

Siempre se debe utilizar el valor mas cercano a cero.

y_kmeans = model.predict(x)
print('Predicciones: ', y_kmeans)

from sklearn import metrics

accuracy = metrics.adjusted_rand_score(y_iris, y_kmeans)
accuracy

plt.scatter(x[‘Petal Length’], x[‘Petal, Width’], c=y_kmeans, s=30)
plt.xlabel(‘Petal Length’)
plt.ylabel(‘Petal Width’)

plt.show()

  • Para graficar correctamente la separacion de los grupos por color es critico el siguiente comando c=y_kmeans.

  • El comando s=30 le indico el tamaño del punto.

# K-Means
---

from sklearn.cluster import KMeans
from sklearn import datasets

import pandas as pd
import matplotlib.pyplot as plt

%matplotlib inline

iris = datasets.load_iris()

El dataset iris viene incluido con `SciKitLearn`

x_iris = iris.data
y_iris = iris.target

x = pd.DataFrame(iris.data, columns=['Sepal Length', 'Sepal Width', 'Petal Length', 'Petal, Width'])
y = pd.DataFrame(iris.target, columns=['Target'])

x.head(5)

plt.scatter(x['Petal Length'], x['Petal, Width'], c='b')
plt.xlabel('Petal Length', fontsize=10)
plt.ylabel('Petal Width', fontsize=10)

plt.show()

model = KMeans(n_clusters=3, max_iter=1000)
model.fit(x)

y_label = model.labels_

Al inicion se definio a `n_cluester=2` como valor inicial para comprobar como funciona el algoritmo `kmeans`. Luego este valor se reemplazara por su valor verdadero.

* `n_cluester=2` me da una presicion del **0.5399**
* `n_cluester=3` me da una presicion del **0.7302**
* `n_cluester=4` me da una presicion del **0.6498**
* `n_cluester=5` me da una presicion del **0.6078**

Siempre se debe utilizar el valor mas cercano a cero.

y_kmeans = model.predict(x)
print('Predicciones: ', y_kmeans)

from sklearn import metrics

accuracy = metrics.adjusted_rand_score(y_iris, y_kmeans)
accuracy

plt.scatter(x['Petal Length'], x['Petal, Width'], c=y_kmeans, s=30)
plt.xlabel('Petal Length')
plt.ylabel('Petal Width')

plt.show()

* Para graficar correctamente la separacion de los grupos por color es critico el siguiente comando `c=y_kmeans`.

* El comando `s=30` le indico el tamaño del punto.

Hola comunidad

Dejo las imágenes de los 3 modelos según el número de centroides

Modelo A: 2 Centroides

Modelo B: 3 Centroides

Modelo C: 4 Centroides

como podría graficar en dónde queda el o los centroides?

Reto…

from sklearn.cluster import KMeans
from sklearn import datasets
from sklearn import metrics
import pandas as pd
import matplotlib.pyplot as plt

wines = datasets.load_wine()

X_wines = wines.data
Y_wines = wines.target
wines.feature_names

x = pd.DataFrame(wines.data, columns = ['alcohol',
 'malic_acid',
 'ash',
 'alcalinity_of_ash',
 'magnesium',
 'total_phenols',
 'flavanoids',
 'nonflavanoid_phenols',
 'proanthocyanins',
 'color_intensity',
 'hue',
 'od280/od315_of_diluted_wines',
 'proline'])
y = pd.DataFrame(wines.target, columns = ['Target'])
x.head(5)

plt.scatter(x['flavanoids'], x['magnesium'], c = 'blue')
plt.xlabel('Flavanoids', fontsize = 10)
plt.ylabel('magnesium', fontsize = 10)

model = KMeans(n_clusters=3, max_iter=1000)
model.fit(x)
y_labels = model.labels_
y_kmeans = model.predict(x)
print("Predicciones ", y_kmeans)

accuracy = metrics.adjusted_rand_score(Y_wines, y_kmeans)
print(accuracy)

plt.scatter(x['flavanoids'], x['magnesium'], c= y_kmeans, s = 30)
plt.xlabel('Flavanoids', fontsize = 10)
plt.ylabel('magnesium', fontsize = 10)

Gráfica de alcohol vs magnesio, use 3 clusters, me da un accuracy de 0.37

yo quiero ser mas efciente, como hago?

x = pd.DataFrame(wines.data, columns=['Alcohol','Malic acid','Ash','Alcalinity of ash','Magnesium','Total phenols',
                                   'Flavanoids','Nonflavanoid phenols','Proanthocyanins','Color intensity','Hue',
                                   'OD280/OD315 of diluted wines','Proline'])
y = pd.DataFrame(wines.target, columns=['Target'])

from sklearn.preprocessing import StandardScaler, MinMaxScaler

scaler = StandardScaler().fit(x.values)
#Aplicamos esta funcion con el metodo transform a los features, de este modo
features = scaler.transform(x.values)
x_norm = pd.DataFrame(features, columns=['Alcohol','Malic acid','Ash','Alcalinity of ash','Magnesium','Total phenols',
                                   'Flavanoids','Nonflavanoid phenols','Proanthocyanins','Color intensity','Hue',
                                   'OD280/OD315 of diluted wines','Proline'])

# método del codo
wcss = []
for i in range(1, 11):
    kmeans = KMeans(n_clusters=i, max_iter=1000, random_state=0)
    kmeans.fit(x_norm)
    y_kmeans = kmeans.predict(x_norm)
    wcss.append(kmeans.inertia_)
    accuracy =  metrics.adjusted_rand_score(y_wines, y_kmeans)
    print(f'numero de n_clusters: {i} accurracy {accuracy}')
plt.plot(range(1, 11), wcss)
plt.title('Metodo Codo')
plt.xlabel('Numeros de Cluster')

plt.show()

Me da un 0.897 de accurracy

wine = datasets.load_wine()
x = wine.data
y = wine.target
print(wine.feature_names)
print('-------------')
print(wine.target)
print(x)
print('-------------')
print(y)

x_df = pd.DataFrame(x, columns=wine.feature_names)
x_df.head()
y_df = pd.DataFrame(y, columns=['target'])
y_df.head()

wine_model = KMeans(n_clusters=3, max_iter=1000)
wine_model.fit(x_df)
y_labels = wine_model.labels_

y_kmeans = wine_model.predict(x_df)
plt.scatter(x_df['alcohol'], x_df['malic_acid'], c=y_kmeans, s=30)
plt.xlabel('alcohol', fontsize=10)
plt.ylabel('malic_acid', fontsize=10)
plt.show()

plt.scatter(x_df['alcohol'], x_df['malic_acid'], c=y_kmeans, s=30)
plt.xlabel('alcohol', fontsize=10)
plt.ylabel('malic_acid', fontsize=10)
plt.show()
names = wine.feature_names
len(names)

for i in range(len(names)-1):
    plt.scatter(x_df[names[i]], x_df[names[i+1]], c=y_kmeans, s=30)
    plt.xlabel(names[i], fontsize=10)
    plt.ylabel(names[i+1], fontsize=10)
    plt.show()

print(metrics.adjusted_rand_score(y, y_kmeans))





Un aspecto a tener en cuenta es que el análisis visual que hicimos en clase se hizo solo con los datos de los pétalos, pero el algoritmo entrenó además con la información de los sépalos. Si pudiéramos ver los datos en 4 dimensiones los puntos tienen una distribución más compleja y ahí es donde se vuelve importante K-Means.

Veo muchos comentarios diciendo que hay que escalar los datos para mejor el accuracy, calculado como **metrics.adjusted_rand_score(y_vinos, y_kmeans) **, de 0.37 a 0.87. Pero no se debe interpretar como que el 87% de los casos la predicción el correcta. Recomiendo que siempre vayamos a la documentación para ver que es lo que realmente significan los métodos que usamos para Accuracy.

Para este caso particular, sin escalar los datos se logra predecir correctamente el 18.5% de los datos. Y escalando, se predice correctamente el 34.8% de los datos. A pesar de que el accuracy nos daba 0.87, el ajuste, incluso escalando, es muy malo. Si lo pensamos de otra forma, y como hay 3 tipos de vinos, el modelo escalado es igual que clasificar el vino de una forma aleatoria.

Hola a todos, sobre la precisión del 36 al 37% con los datos de vinos, comentar que como dicen otros compañeros se realiza una normalización de los datos, esta puede ser como cuando se hace la normalización para pasar a una distribución estándar es estadística, básicamente hay que aplicarle a cada dato (xi - mu) / sigma, siendo:

  • xi: el dato.
  • mu: la media de los datos de la columna.
  • sigma: la desviación estándar de los datos de la columna.

Entonces lo que hay que hacer es obtener todas las medias y las desviaciones estándar por cada columna y usar la fórmula. Esto se hace para que todos los datos queden en una misma escala. Lo anterior es lo que hace por dentro StandardScaler utilizado por el compañero Diego Medina en su código.
Otra forma de normalizar y estandarizar los datos es (xi - mu) / Rango, siendo:

  • xi: el dato.
  • mu: la media de los datos de la columna.
  • Rango: dato máximo - dato mínimo.
    De esta forma hacemos que todos los datos estén entre -1 y 1.

Espero les sirva.
Un abrazo!

Dejo mi código probando ambas técnicas si usar StandardScaler:

from sklearn.cluster import KMeans
from sklearn import datasets
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import metrics
wine = datasets.load_wine()
X_wine = wine.data
Y_wine = wine.target
cols = wine.feature_names
x = pd.DataFrame(X_wine, columns=cols)
y = pd.DataFrame(Y_wine, columns=['Target'])
# Rango
x_norm_ran = (x - x.mean(axis=0)) / (x.max(axis=0) - x.min(axis=0))
# Desviación estándar
x_norm_std = (x - x.mean(axis=0)) / x.std(axis=0)
model_ran = KMeans(n_clusters=3, max_iter=1000)
model_ran.fit(x_norm_ran)
y_kmeans_ran = model_ran.predict(x_norm_ran)

accuracy = metrics.adjusted_rand_score(Y_wine, y_kmeans_ran)
print(f"La precición para el modelo nomalizado con Rango es : {accuracy}")

La precición para el modelo nomalizado con Rango es : 0.8536602842727953

model_std = KMeans(n_clusters=3, max_iter=1000)
model_std.fit(x_norm_std)
y_kmeans_std = model_std.predict(x_norm_std)

accuracy = metrics.adjusted_rand_score(Y_wine, y_kmeans_std)
print(f"La precición para el modelo nomalizado con desviación estándar es : {accuracy}")

La precición para el modelo nomalizado con desviación estándar es : 0.8974949815093207

Esta fue mi solución para el dataset de wines.

import pandas as pd
import sklearn.datasets as datasets
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
import sklearn.metrics as metrics
wines = datasets.load_wine()
x = pd.DataFrame(wines.data, columns=wines.feature_names)
y = pd.DataFrame(wines.target, columns=['Target'])
y_classes = wines.target
plt.scatter(x['alcohol'], x['color_intensity'], c = y_classes, s=30)
plt.xlabel('Alcohol', fontsize=10)
plt.ylabel('Color intensity', fontsize=10)
# Data normalization
norm = MinMaxScaler().fit(x)
x_norm = norm.transform(x)

#Data standardization
std_scaler = StandardScaler()
data_scaled = x_norm.copy()
data_scaled = pd.DataFrame(data_scaled, columns=wines.feature_names)
model = KMeans(n_clusters=3, max_iter=1000)
model.fit(data_scaled)
y_kmeans = model.predict(data_scaled)
print("Predictions: ", y_kmeans)
accuracy = metrics.adjusted_rand_score(y_classes, y_kmeans)
accuracy

Logré 86% de accuracy