Práctica 2. Continuación#

SOM como un Clasificador#

Los mapas auto-organizativos de Kohonen también se pueden utilizar como clasificadores mediante un aprendizaje supervisado que utiliza parte de los datos para entrenar la red y ajustar los pesos de cada neurona de manera que se minimize el error de salida y deja otra parte de los datos para comprobar si el entrenamiento ha sido eficaz.

Ejemplo 1. Selección de un conjunto de entrenamiento#

Elige de manera aleatoria un conjunto de entrenamiento que contenga un 70% de los datos de som.wine (manteniendo la primera columna que contiene la información de la bodega de origen). A partir de este conjunto, creamos el conjunto de entrenamiento y el conjunto de comprobación escalados.

Para que la comparación sea adecuada, el segundo se debe escalar con referencia al conjunto de entrenamiento. A partir de éstos, creamos dos listas donde detallamos el conjunto que se va comprobar respecto a que atributo, en nuestro caso, las bodegas (Cultivars)

Las bodegas son:

Cultivars grapes = (Nebbiolo, Barberas, Grignolino)

#!git clone https://github.com/cgg-upm/upm-dma-som
#!dir upm-dma-som\som
#!copy upm-dma-som\som\som.py .\*.*
#!copy upm-dma-som\som\utils.py .\*.*
from som import som
from utils import somutils
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.metrics import confusion_matrix
# Se preparan las columnas a tratar
df_wine = pd.read_csv('data/wine.csv', header=None)
df_wine.columns = ['label', 'alcohol',
    'malic acid', 'ash',
    'ash alkalinity',
    'magnesium', 'tot. phenols',
    'flavanoids', 'non-flav. phenols',
    'proanth',
    'col. int.', 'col. hue',
    'OD ratio'
    ,'proline']
# Se borra la columna de la etiqueta
#df_wine = df_wine.drop('label', axis=1)
df_wine.head()
label alcohol malic acid ash ash alkalinity magnesium tot. phenols flavanoids non-flav. phenols proanth col. int. col. hue OD ratio proline
0 1 14.23 1.71 2.43 15.6 127 2.80 3.06 0.28 2.29 5.64 1.04 3.92 1065
1 1 13.20 1.78 2.14 11.2 100 2.65 2.76 0.26 1.28 4.38 1.05 3.40 1050
2 1 13.16 2.36 2.67 18.6 101 2.80 3.24 0.30 2.81 5.68 1.03 3.17 1185
3 1 14.37 1.95 2.50 16.8 113 3.85 3.49 0.24 2.18 7.80 0.86 3.45 1480
4 1 13.24 2.59 2.87 21.0 118 2.80 2.69 0.39 1.82 4.32 1.04 2.93 735
X, y = df_wine.values[:,1:14], df_wine.values[:,0]
scaler = StandardScaler()
X_std = scaler.fit_transform(X)
X_train, X_test, y_train, y_test =train_test_split(X_std, y, test_size=0.3, random_state=1, stratify=y)
df = pd.DataFrame(X_train)
df.columns = ['alcohol',
    'malic acid', 'ash',
    'ash alkalinity',
    'magnesium', 'tot. phenols',
    'flavanoids', 'non-flav. phenols',
    'proanth',
    'col. int.', 'col. hue',
    'OD ratio'
    ,'proline']
df.head()
alcohol malic acid ash ash alkalinity magnesium tot. phenols flavanoids non-flav. phenols proanth col. int. col. hue OD ratio proline
0 1.691550 -0.346811 0.487926 -0.809251 0.930918 2.491446 1.466525 -0.981875 1.032155 1.186068 -0.427544 1.184071 2.334574
1 -0.284874 0.981731 -1.412851 -1.049479 -1.386122 -1.065731 -0.782361 0.549108 -1.333159 -0.717240 -1.129518 -0.694478 -1.193845
2 0.209232 2.561618 -0.170035 0.752231 -0.473348 -0.889474 -1.404820 1.999513 -0.071658 1.229325 -1.568252 -1.598441 -0.069719
3 -0.346638 -0.526343 -0.316249 0.902373 -1.105268 -1.466313 -0.270338 0.951998 0.068508 -0.760497 -0.339797 -0.270745 -0.824444
4 0.196879 0.021231 1.109334 -0.268738 0.088358 0.808997 1.215533 -0.498407 2.135968 0.269020 0.318304 0.788587 1.395148
cultivares=['Nebbiolo', 'Barberas', 'Grignolino']
y_cultivar = [ cultivares[int(lbl)-1] for lbl in y_train]
df = pd.DataFrame(y_cultivar)
df.columns = ['Cultivar']
df.head()
Cultivar
0 Nebbiolo
1 Barberas
2 Grignolino
3 Barberas
4 Nebbiolo

Ejercicio 1. Clasificación del conjunto de entrenamiento y cálculo de errores#

Utiliza un SOM del mismo tamaño y malla que en la sección anterior y el comando supersom del paquete kohonen para obtener la clasificación del conjunto testdata.

Halla la matriz de confusion y dertermina el error cometido en la clasificación.

nrows = 20
ncols = 20
smm = som(nrows=nrows,ncols=ncols)
nrows = 20
ncols = 20
dimensions = X_train.shape[1]
#vicinity = "rectangular"
vicinity = "hexagonal"
smm = som(nrows=nrows,
          ncols=ncols,
          dimension=dimensions,
          vicinity=vicinity)
smm.train_super_SOM(train_data=X_train, y_train=y_train, epochs=10)
Hide code cell output
  0%|                                                                                                                                                     | 0/10 [00:00<?, ?it/s]
 40%|████████████████████████████████████████████████████████▍                                                                                    | 4/10 [00:00<00:00, 38.14it/s]
 90%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▉              | 9/10 [00:00<00:00, 39.23it/s]
100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 10/10 [00:00<00:00, 38.09it/s]

<som.som at 0x1c9c36d5d90>
y_pred = smm.getPredict(X_train)
smm.score(y_pred, y_train)
0.9596774193548387
y_pred = smm.getPredict(X_test)
smm.score(y_pred, y_test)
0.9444444444444444

Matriz de confusión#

CMD = ConfusionMatrixDisplay(confusion_matrix(y_true=y_test, y_pred=y_pred), display_labels=cultivares).plot()
_images/5452ca2eef929787af5689ae9c2742884aa7da53e5ffbee339b6675198f33c28.png

Mapa con las estimaciones#

somutils.plotEstimationMap(pSom=smm, figsize=(7,5))
_images/55b40617459309be6aa1fa5afa3e4d07254d15e8f2945553db1ebdeb82e97098.png

Ejercicio#

Repite la práctica (clustering y clasificación) usando:

  • subconjuntos de los datos wine (nota: scatter matrix)

  • variando los parámetros del SOM (neuronas, funciones) Compara los resultados obtenidos.