Ejemplo de Mineria de Datos.

 

Preparación de datos

A lo largo de esta práctica veremos como aplicar diferentes tecnicas para la carga y preparación de datos:

  1. Carga de un conjunto de datos
  2. Análisis de los datos
    2.1 Análisis estadístico básico
    2.2 Análisis expxloratorio de los datos
  3. Reducción de la dimensionalidad
  4. Entrenamiento y test

Para eso necesitaremos las siguientes librerías:

In [1]:
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

1. Carga del conjunto de datos

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.

Ejercicio: Cargad el conjunto de datos "Wine Recognition" y mostrad:
- el número y nombre de los atributos (variables que podrían ser usadas para predecir la respuesta "wine_class")
- el número de filas del conjunto de datos
- verificad si hay o no "missing values" y en que columnas
Sugerencia: Si usáis sklearn (sklearn.datasets.load_wine), explorad las diferents 'keys' del objecto obtenido. Sugerencia: Igual os resulta útil pasar los datos (atributos + target) a un dataframe de pandas.
In [2]:
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()
Primer análisis de los datos
Out[2]:
alcoholmalic_acidashalcalinity_of_ashmagnesiumtotal_phenolsflavanoidsnonflavanoid_phenolsproanthocyaninscolor_intensityhueod280/od315_of_diluted_winesprolineclasses
014.231.712.4315.6127.02.803.060.282.295.641.043.921065.0class_0
113.201.782.1411.2100.02.652.760.261.284.381.053.401050.0class_0
213.162.362.6718.6101.02.803.240.302.815.681.033.171185.0class_0
314.371.952.5016.8113.03.853.490.242.187.800.863.451480.0class_0
413.242.592.8721.0118.02.802.690.391.824.321.042.93735.0class_0
In [3]:
print("Descripción de los datos")
df.describe()
Descripción de los datos
Out[3]:
alcoholmalic_acidashalcalinity_of_ashmagnesiumtotal_phenolsflavanoidsnonflavanoid_phenolsproanthocyaninscolor_intensityhueod280/od315_of_diluted_winesproline
count178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000
mean13.0006182.3363482.36651719.49494499.7415732.2951122.0292700.3618541.5908995.0580900.9574492.611685746.893258
std0.8118271.1171460.2743443.33956414.2824840.6258510.9988590.1244530.5723592.3182860.2285720.709990314.907474
min11.0300000.7400001.36000010.60000070.0000000.9800000.3400000.1300000.4100001.2800000.4800001.270000278.000000
25%12.3625001.6025002.21000017.20000088.0000001.7425001.2050000.2700001.2500003.2200000.7825001.937500500.500000
50%13.0500001.8650002.36000019.50000098.0000002.3550002.1350000.3400001.5550004.6900000.9650002.780000673.500000
75%13.6775003.0825002.55750021.500000107.0000002.8000002.8750000.4375001.9500006.2000001.1200003.170000985.000000
max14.8300005.8000003.23000030.000000162.0000003.8800005.0800000.6600003.58000013.0000001.7100004.0000001680.000000
In [4]:
print("El número de líneas es: " + str(df.shape[0]) + " y el número de columnas: "+ str(df.shape[1]))
El número de líneas es: 178 y el número de columnas: 14
In [5]:
print("No existe ningún null")

df.isnull().sum()
No existe ningún null
Out[5]:
alcohol                         0
malic_acid                      0
ash                             0
alcalinity_of_ash               0
magnesium                       0
total_phenols                   0
flavanoids                      0
nonflavanoid_phenols            0
proanthocyanins                 0
color_intensity                 0
hue                             0
od280/od315_of_diluted_wines    0
proline                         0
classes                         0
dtype: int64

2. Análisis de los datos

2.1 Análisis estadístico básico

Ejercicio: Realizad un análisis estadístico básico:
- Variables categóricas: - Calculad la frecuencia. - Haced un gráfico de barras.
- Variables numéricas: - Calculad estadísticos descriptivos básicos: media, mediana, desviación estandard, ... - Haced un histograma de las variables: alcohol, magnesium y color_intensity
Sugerencia: podéis usar la librería 'pandas' y sus funciones 'describe' y 'value_counts'
In [6]:
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);
Cálculo de la frecuéncia
Frecuéncia
class_1    71
class_0    59
class_2    48
dtype: int64
In [7]:
print("Estadísticos descriptivos básicos:")
df[num_cols_no_categoric].describe()
Estadísticos descriptivos básicos:
Out[7]:
alcoholmalic_acidashalcalinity_of_ashmagnesiumtotal_phenolsflavanoidsnonflavanoid_phenolsproanthocyaninscolor_intensityhueod280/od315_of_diluted_winesproline
count178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000178.000000
mean13.0006182.3363482.36651719.49494499.7415732.2951122.0292700.3618541.5908995.0580900.9574492.611685746.893258
std0.8118271.1171460.2743443.33956414.2824840.6258510.9988590.1244530.5723592.3182860.2285720.709990314.907474
min11.0300000.7400001.36000010.60000070.0000000.9800000.3400000.1300000.4100001.2800000.4800001.270000278.000000
25%12.3625001.6025002.21000017.20000088.0000001.7425001.2050000.2700001.2500003.2200000.7825001.937500500.500000
50%13.0500001.8650002.36000019.50000098.0000002.3550002.1350000.3400001.5550004.6900000.9650002.780000673.500000
75%13.6775003.0825002.55750021.500000107.0000002.8000002.8750000.4375001.9500006.2000001.1200003.170000985.000000
max14.8300005.8000003.23000030.000000162.0000003.8800005.0800000.6600003.58000013.0000001.7100004.0000001680.000000
In [8]:
print("Histograma de las variables: alcohol")

graf1  = sns.distplot(df['alcohol'],kde=0)
Histograma de las variables: alcohol
In [9]:
print("Histograma de las variables: color_intensity")
graf3  = sns.distplot(df['color_intensity'],kde=0,color="red")
Histograma de las variables: color_intensity
In [10]:
print("Histograma de las variables: magnesium")
graf2  = sns.distplot(df['magnesium'],kde=0,color="green")
Histograma de las variables: magnesium
Análisis: Comentad los resultados.

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.

2.2 Análisis exploratorio de los datos

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.

In [11]:
feats_to_explore = ['alcohol', 'magnesium', 'color_intensity']
Ejercicio: Usando una librería gráfica, como por ejemplo "matplotlib", realizad un gráfico del histograma de valores para cada uno de los atributos seleccionados, separados por los valores de la clase respuesta. Los tres gráficos tienen que estar sobrepuestos, es decir, por ejemplo, en el histograma de la feature "alcohol" tienen que haber en un solo gráfico tres histogramas, uno por cada clase de vino. Añadid una leyenda para saber a que clase corresponde cada histograma. La finalidad es observar como se distribuye cada uno de los atributos en función de la clase que tengan, para poder identificar de manera visual y rápida si algunos atributos permiten diferenciar de forma clara las diferentes clases de vinos.
Sugerencia: podéis usar el parámetro "alpha" en los gráficos para que se aprecien los tres histogramas.
In [12]:
for i in [0,1,2]:
    sns.distplot(df['alcohol'][data.target==i],
                 kde=False,label='{
                }'.format(i))

plt.legend()
Out[12]:
<matplotlib.legend.Legend at 0x1246dcf98>
In [13]:
for i in [0,1,2]:
    sns.distplot(df['color_intensity'][data.target==i],kde=False,label='{}'.format(i))

plt.legend()
Out[13]:
<matplotlib.legend.Legend at 0x105b58898>
In [14]:
for i in [0,1,2]:
    sns.distplot(df['magnesium'][data.target==i],kde=False,
                 label='{
                }'.format(i))

plt.legend()
Out[14]:
<matplotlib.legend.Legend at 0x105b6bfd0>
Análisis:
Mirando los histogramas, ¿que atributo parece tener más peso a la hora de clasificar un vino? ¿Cual parece tener menos peso?

La intensidad del color, mientras qeu el de menor peso el magnesium. Realmente el color esta más agrupado y diferenciado que el resto.

Ejercicio: Usando los histogramas anteriores, añadid una linia vertical indicando la media de cada uno de los histogramas (tres por gráfico). Pintad las linias del mismo color que el histograma para que quede claro a cual hacen referencia. Añadid a la leyenda, la clase de vino y la desviación estandard en cuestión. La finalidad es verificar numéricamente las diferencias identificadas anteriormente de forma visual.
Sugerencia: podeis usar "axvline", de matplotlib axis, para las linias verticales.
In [15]:
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()
Out[15]:
<matplotlib.legend.Legend at 0x125295dd8>