A lo largo de esta práctica veremos como aplicar diferentes tecnicas para la carga y preparación de datos:
Para eso necesitaremos las siguientes librerías:
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn import datasets
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split, cross_val_score
import matplotlib.pyplot as plt
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
pd.set_option('display.max_columns', None)
%matplotlib inline
En primer lugar, debéis cargar el conjunto de datos Wine recognition (más información en el enlace https://archive.ics.uci.edu/ml/datasets/Wine). Se puede descargar de internet o se puede cargar directamente desde la librería "scikit-learn", que incorpora un conjunto de datasets muy conocidos y usados para la minería de datos y machine learning http://scikit-learn.org/stable/datasets/index.html.
from sklearn.datasets import load_wine
data = load_wine()
df = pd.DataFrame(data.data, columns=data.feature_names)
df['classes'] = pd.Categorical.from_codes(data.target, data.target_names)
print("Primer análisis de los datos")
df.head()
print("Descripción de los datos")
df.describe()
print("El número de líneas es: " + str(df.shape[0]) + " y el número de columnas: "+ str(df.shape[1]))
print("No existe ningún null")
df.isnull().sum()
print('Cálculo de la frecuéncia')
cols = df.columns
num_cols_no_categoric = df._get_numeric_data().columns
col_categoric=list(set(cols) - set(num_cols_no_categoric))
print("Frecuéncia")
print( pd.value_counts(df[col_categoric].values.flatten()))
frecuencia_data =pd.value_counts(df[col_categoric].values.flatten())
sns.catplot(x="classes", kind="count", palette="ch:.25", data=df);
print("Estadísticos descriptivos básicos:")
df[num_cols_no_categoric].describe()
print("Histograma de las variables: alcohol")
graf1 = sns.distplot(df['alcohol'],kde=0)
print("Histograma de las variables: color_intensity")
graf3 = sns.distplot(df['color_intensity'],kde=0,color="red")
print("Histograma de las variables: magnesium")
graf2 = sns.distplot(df['magnesium'],kde=0,color="green")
Respecto al target, la clase de vino, cabe destacar que el número de elementos está distribuido equitativamente entre los 3 tipos de vino, es decir, no tenemos una gran cantidad del tipo1 y muy poca del resto que complicaria las tareas de clasificación.
También es posible analizar como el alcohol es el elemento más distribuido de las tres gráficas, es decir, tenemos una gran cantidad de muestras diferentes lo que me hace deducir que será una variable dificil de utilizar para la clasificación. En otro sentido, el color de la intensidad se agrupa más y el magnesio esta muy agrupado alrededor de 90.
En este ejercicio exploraremos la relación de algunos de los atributos numéricos con la variable respuesta ("wine_class"), tanto gráficamente como cualitativamente, y analizaremos las diferentes correlaciones. Para empezar, seleccionaremos solo 3 atributos para explorar: alcohol, magnesium y color_intensity.
feats_to_explore = ['alcohol', 'magnesium', 'color_intensity']
for i in [0,1,2]:
sns.distplot(df['alcohol'][data.target==i],
kde=False,label='{
}'.format(i))
plt.legend()
for i in [0,1,2]:
sns.distplot(df['color_intensity'][data.target==i],kde=False,label='{}'.format(i))
plt.legend()
for i in [0,1,2]:
sns.distplot(df['magnesium'][data.target==i],kde=False,
label='{
}'.format(i))
plt.legend()
La intensidad del color, mientras qeu el de menor peso el magnesium. Realmente el color esta más agrupado y diferenciado que el resto.
for i in [0,1,2]:
std = round(df["alcohol"][data.target==i].std(),3)
sns.distplot(df['alcohol'][data.target==i],
kde=1,label='{} con std {}'.format(i,std))
plt.legend()
for i in [0,1,2]:
std = round(df["color_intensity"][data.target==i].std(),3)
sns.distplot(df['color_intensity'][data.target==i],
kde=1,label='{} con std {}'.format(i,std))
plt.legend()
for i in [0,1,2]:
std = round(df["magnesium"][data.target==i].std(),3)
sns.distplot(df['magnesium'][data.target==i],
kde=1,label='{} con std {}'.format(i,std))
plt.legend()
fig, (ax) = plt.subplots(1, 1, figsize=(10,6))
corr = df[feats_to_explore].corr()
hm = sns.heatmap(corr,
ax=ax, # Axes in which to draw the plot, otherwise use the currently-active Axes.
cmap="coolwarm", # Color Map.
#square=True, # If True, set the Axes aspect to “equal” so each cell will be square-shaped.
annot=True,
fmt='.2f', # String formatting code to use when adding annotations.
#annot_kws={"size": 14},
linewidths=.05)
fig.subplots_adjust(top=0.93)
fig.suptitle('Wine Attributes Correlation Heatmap',
fontsize=14,
fontweight='bold')
feats_to_explore.append("classes")
sns.pairplot( hue="classes", data= df[feats_to_explore])
Sip, cuadra que el color y el alcohol tiene una dsitribución de los datos mucho más clara que el resto (tercer nivel izquierda). También en el gráfico de correlación aparecia el valor más elevado lo que confirma la información visualizada.
En este ejercicio se aplicarán métodos de reducción de la dimensionalidad al conjunto original de datos. El objetivo es reducir el conjunto de atributos a un nuevo conjunto con menos dimensiones. Así en vez de trabajar con 3 variables elegidas al azahar, usaremos la información de todos los atributos.
from sklearn.preprocessing import StandardScaler
features = data.feature_names
# Separating out the features
x = df.loc[:, features].values
# Separating out the target
y = df.loc[:,['classes']].values
# Standardizing the features
x = StandardScaler().fit_transform(x)
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
principalComponents = pca.fit_transform(x)
principalDf = pd.DataFrame(data = principalComponents
, columns = ['principal component 1', 'principal component 2'])
principalDf
finalDf = pd.concat([principalDf, df[['classes']]], axis = 1)
finalDf
fig = plt.figure(figsize = (8,8))
ax = fig.add_subplot(1,1,1)
ax.set_xlabel('Principal Component 1', fontsize = 15)
ax.set_ylabel('Principal Component 2', fontsize = 15)
ax.set_title('2 component PCA', fontsize = 20)
targets = ['class_0', 'class_1', 'class_2']
colors = ['r', 'g', 'b']
for target, color in zip(targets,colors):
indicesToKeep = finalDf['classes'] == target
ax.scatter(finalDf.loc[indicesToKeep, 'principal component 1']
, finalDf.loc[indicesToKeep, 'principal component 2']
, c = color
, s = 50)
ax.legend(targets)
ax.grid()
features = data.feature_names
# Separating out the features
x = df.loc[:, features].values
y=data.target
from sklearn.manifold import TSNE
tsne_results = TSNE(n_components=2).fit_transform(x)
target_ids = range(len([0,1,2]))
from matplotlib import pyplot as plt
colors = 'r', 'g', 'b', 'c', 'm', 'y', 'k', 'w', 'orange', 'purple'
for i, c, label in zip(target_ids, colors, [0,1,2]):
plt.scatter(tsne_results[y == i, 0], tsne_results[y == i, 1], c=c, label=label)
plt.legend()
plt.show()
sns.scatterplot(tsne_results[:,0], tsne_results[:,1], hue=y, legend='full')
Si, creo que ha funcionado correctamente en el primer caso. Utilizando el PCA he conseguido observar de forma nítida la distribución del dataset en 3 clases de vinos mientras que en el segundo se entremezclan más y cuesta más diferenciarlos.
Los resultados son diferentes ya que los algoritmos están optimizados para diferentes dataset. Mientras que el PCA es muy útil para dataset con caracteristicas similares entre clases el TSNE es para todo lo contrario.
En este último ejercicio se trata de aplicar un método de aprendizaje supervisado, concretamente el clasificador Random Forest, para predecir la clase a la que pertenece cada vino y evaluar la precisión obtenida con el modelo. Para eso usaremos:
- El conjunto de datos original con todos los atributos
- El conjunto de datos reducido a solo 2 atributos con PCA
- El conjunto de datos reducido a solo 2 atributos con TSNE