Como vimos en los anteriores artículos de Blog estamos realizando un experimento de clasificación lo suficientemente complejo para permitirnos probar las distintas tecnologías existentes en el mercado y las diferencias relativas a los siguientes 4 puntos:
1) Performance
2) Consumo de recursos
3) Dificultad para implementar la algorítmica asociada
4) Tiempo de aprendizaje
Para la realización del experimento estamos utilizando un conjunto de datos de caracteres alfanuméricos en formato imagen (28x28) provistos por Google para la realización del curso "Deep Learning by Google" a través de la plataforma Udacity.
Es un conjunto de caracteres NOMINST en distintas formas y formatos simulando lo que sería un reconocimiento de escritura natural sobre 10 clases de caracteres y etiquetados por una clase de 0 a 9. de esta forma la correspondencia será:
A - 0
B - 1
C - 2
D - 3
E - 4
F - 5
G - 6
H - 7
I - 8
J - 9
Para estos experimentos trabajamos con un conjunto de 200.000 datos de entrenamiento y dos conjuntos de validación y test de 10.000 sucesos.
Todos los conjuntos han sido previamente mezclados aleatoriamente para el experimento y almacenados en fichero con formato cpickle para reproducir las mismas circunstancias en todos los experimentos.
H2O.ai 3.10
H2O es una plataforma de análisis predictivo y aprendizaje automático de código abierto, trabaja en memoria, de forma distribuida, siendo rápida y escalable, lo que permite construir modelos de aprendizaje automático para grandes conjuntos de datos de un forma rápida y comprensible y proporcionando una producción fácil de los modelos en un entorno empresarial.El código básico de H2O está escrito en Java. El analizador de datos de H2O tiene inteligencia incorporada para adivinar el esquema del dataset entrante y admite la ingesta de datos de múltiples fuentes en varios formatos.
Los algoritmos que aporta se reducen en las siguientes familias:
AL igual que Spark ™ implementa el concepto de hyper-parámetros que nos puede servir para optimizar los distintas configuraciones del modelo de aprendizaje, dentro de unos rangos, buscando de una forma cómoda la mejor configuración de estos reduciendo bastante el tiempo de codificación.
En nuestro caso utilizaremos el algoritmo GLM para nuestro experimento.
En nuestro caso utilizaremos el algoritmo GLM para nuestro experimento.
Inicialización
Lo primero que vamos a hacer es cargar las librerías y módulos necesarios.
# These are all the modules we'll be using later. Make sure you can import them
# before proceeding further.
Ahora pasamos a inicializar las Variables y convertilas en H2OFrames para poder trabajar con el modelo.
Y liberamos Memoria
Probaremos ahora a definir y entrenar el modelo.
glm_multi_v1.predict(test_dataset_h2o[:-1])
accuraccy = (glm_multi_v1.predict(train_dataset_h2o[:-1])[0] == train_dataset_h2o[-1])
print('Train Accuracy: %s'% (accuraccy.sum()/ accuraccy.nrows))
accuraccy = (glm_multi_v1.predict(valid_dataset_h2o[:-1])[0] == valid_dataset_h2o[-1])
print('Valid Accuracy: %s'% (accuraccy.sum()/ accuraccy.nrows))
accuraccy = (glm_multi_v1.predict(test_dataset_h2o[:-1])[0] == test_dataset_h2o[-1])
print('Test Accuracy: %s'% (accuraccy.sum()/ accuraccy.nrows))
Resultados:
Time = 853.3969919681549
Training dataset Accuracy = 0.836965
Valid dataset Accuracy = 0.8332
Test dataset Accuracy = 0.8986
from __future__ import print_function
import matplotlib.pyplot as plt
import numpy as np
import os
import pickle as pickle
import time
import sys
import h2o
# Config the matplotlib backend as plotting inline in IPython
%matplotlib inline
Y Cargamos la imagenes empaquetadas en un fichero cPickle.
Nos basamos en un conjunto de imagenes 28X28 NOMINST (provisto por Google) de distintos tipos de fuentes para los caracteres y etiquetas asociadas:
[A,B,C,D,E,F,G,H,I,J] = [0,1,2,3,4,5,6,7,8,9]
os.chdir('d:/Data/Gdeeplearning-Udacity')
pickle_file = 'notMNIST.pickle'
with open(pickle_file, 'rb') as f:
save = pickle.load(f)
train_dataset = save['train_dataset']
train_labels = save['train_labels']
valid_dataset = save['valid_dataset']
valid_labels = save['valid_labels']
test_dataset = save['test_dataset']
test_labels = save['test_labels']
del save # hint to help gc free up memory
print('Training set', train_dataset.shape, train_labels.shape)
print('Validation set', valid_dataset.shape, valid_labels.shape)
print('Test set', test_dataset.shape, test_labels.shape)
Como vemos nuestras imágenes y etiquetas han sido perfectamente cargadas y estamos listos para trabajar con ellas.
Training set (200000, 28, 28) (200000,)
Validation set (10000, 28, 28) (10000,)
Test set (10000, 28, 28) (10000,)
Validation set (10000, 28, 28) (10000,)
Test set (10000, 28, 28) (10000,)
GLM on H2O.ai
Lo primero que vamos a realizar es la inicialización del entorno H2O.
h2o.init()
Obteniendo la siguiente salida:
Ahora pasamos a inicializar las Variables y convertilas en H2OFrames para poder trabajar con el modelo.
def reformat(dataset, labels):
dataset = dataset.reshape((-1, image_size * image_size)).astype(np.float32)
# Map 0 to [1.0, 0.0, 0.0 ...], 1 to [0.0, 1.0, 0.0 ...]
labels = labels.reshape((-1, 1)).astype(str)
#labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32)
return dataset, labels
tf_train_dataset, tf_train_labels = reformat(train_dataset, train_labels)
tf_valid_dataset, tf_valid_labels = reformat(valid_dataset, valid_labels)
tf_test_dataset, tf_test_labels = reformat(test_dataset, test_labels)
train_dataset_h2o = h2o.H2OFrame(python_obj=tf_train_dataset)
.cbind(h2o.H2OFrame(python_obj=tf_train_labels).asfactor())
valid_dataset_h2o = h2o.H2OFrame(python_obj=tf_valid_dataset)
.cbind(h2o.H2OFrame(python_obj=tf_valid_labels).asfactor())
test_dataset_h2o = h2o.H2OFrame(python_obj=tf_test_dataset)
.cbind(h2o.H2OFrame(python_obj=tf_test_labels).asfactor())
Y liberamos Memoria
#deleting non used memory
train_dataset = []
train_labels = []
test_dataset = []
test_labels = []
valid_dataset = []
valid_labels = []
Experimentos
Probaremos ahora a definir y entrenar el modelo.
image_size = 28
num_labels = 10
from h2o.estimators.glm import H2OGeneralizedLinearEstimator
glm_multi_v1 = H2OGeneralizedLinearEstimator(model_id='glm_v1',family='multinomial',solver='AUTO',\
nfolds=4,alpha=0.0 ,lambda_=0.001,\
score_each_iteration = True,early_stopping=True, seed = 1234)
predictors_X = train_dataset_h2o.col_names[:-1]
results_y = train_dataset_h2o.col_names[-1]
start=time.time()
glm_multi_v1.train(x=predictors_X, y=results_y, \
training_frame=train_dataset_h2o, \
validation_frame=valid_dataset_h2o)
stop = time.time()
print('time %s' % (stop-start))
accuraccy = (glm_multi_v1.predict(train_dataset_h2o[:-1])[0] == train_dataset_h2o[-1])
print('Train Accuracy: %s'% (accuraccy.sum()/ accuraccy.nrows))
accuraccy = (glm_multi_v1.predict(valid_dataset_h2o[:-1])[0] == valid_dataset_h2o[-1])
print('Valid Accuracy: %s'% (accuraccy.sum()/ accuraccy.nrows))
accuraccy = (glm_multi_v1.predict(test_dataset_h2o[:-1])[0] == test_dataset_h2o[-1])
print('Test Accuracy: %s'% (accuraccy.sum()/ accuraccy.nrows))
Resultados:
Time = 853.3969919681549
Training dataset Accuracy = 0.836965
Valid dataset Accuracy = 0.8332
Test dataset Accuracy = 0.8986
Los resultados obtenidos son muy similares a los obtenidos con los modelos anteriores pero con un consumo de recursos y tiempo de aprendizaje muy equilibrado.
Desde el punto de vista de rendimiento
Conclusión
Si bien la tecnología aportada es menos potente a priori que Spark ™, en base al catálogo de características, los resultados para este problema son similares (incluso superiores) pero con unos tiempos de aprendizaje y consumo de recursos mucho mas eficientes.
Dado su alto grado de interactividad lo hace indicado para todo tipo de problemas y, en base a su alta capacidad de escalabilidad (sobre cluster propio o sobre un cluster Spark ™) junto con su especialización puede ser muy valido para sistemas en producción donde la homogeneidad tecnológica y la escalabilidad sean el factor diferencial.
A nivel curva de aprendizaje y complejidad es similar a Spark ™ y, por tanto, no es especialmente intuitivo si bien la gran cantidad de información que aporta de forma sencilla mejora sustancialmente dicha percepción.
Cabe destacar que todos estos factores le han hecho ser parte del famoso Cuadrante mágico de Gartner 2017 en el apartado de herramientas asociadas a la Ciencia de Datos.