CNTK - Grandes conjuntos de datos y en memoria

En este capítulo, aprenderemos cómo trabajar con conjuntos de datos grandes y en memoria en CNTK.

Entrenamiento con pequeños conjuntos de datos en memoria

Cuando hablamos de introducir datos en el entrenador CNTK, puede haber muchas formas, pero dependerá del tamaño del conjunto de datos y del formato de los datos. Los conjuntos de datos pueden ser pequeños en memoria o grandes conjuntos de datos.

En esta sección, trabajaremos con conjuntos de datos en memoria. Para ello, utilizaremos los siguientes dos marcos:

  • Numpy
  • Pandas

Usando matrices Numpy

Aquí, trabajaremos con un conjunto de datos generado aleatoriamente en CNTK. En este ejemplo, vamos a simular datos para un problema de clasificación binaria. Supongamos que tenemos un conjunto de observaciones con 4 características y queremos predecir dos posibles etiquetas con nuestro modelo de aprendizaje profundo.

Ejemplo de implementación

Para esto, primero debemos generar un conjunto de etiquetas que contengan una representación de un vector caliente de las etiquetas que queremos predecir. Se puede hacer con la ayuda de los siguientes pasos:

Step 1 - Importar el numpy paquete de la siguiente manera -

import numpy as np
num_samples = 20000

Step 2 - Luego, genere un mapeo de etiquetas usando np.eye funciona de la siguiente manera:

label_mapping = np.eye(2)

Step 3 - Ahora usando np.random.choice función, recopile las 20000 muestras aleatorias de la siguiente manera:

y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)

Step 4 - Ahora, por fin, utilizando la función np.random.random, genere una matriz de valores de punto flotante aleatorios de la siguiente manera:

x = np.random.random(size=(num_samples, 4)).astype(np.float32)

Una vez que generamos una matriz de valores aleatorios de punto flotante, necesitamos convertirlos a números de punto flotante de 32 bits para que puedan coincidir con el formato esperado por CNTK. Sigamos los pasos a continuación para hacer esto:

Step 5 - Importe las funciones de capa densa y secuencial del módulo cntk.layers de la siguiente manera -

from cntk.layers import Dense, Sequential

Step 6- Ahora, necesitamos importar la función de activación para las capas en la red. Vamos a importar elsigmoid como función de activación -

from cntk import input_variable, default_options
from cntk.ops import sigmoid

Step 7- Ahora, necesitamos importar la función de pérdida para entrenar la red. Vamos a importarbinary_cross_entropy como función de pérdida -

from cntk.losses import binary_cross_entropy

Step 8- A continuación, necesitamos definir las opciones predeterminadas para la red. Aquí, proporcionaremos elsigmoidfunción de activación como configuración predeterminada. Además, cree el modelo utilizando la función de capa secuencial de la siguiente manera:

with default_options(activation=sigmoid):
model = Sequential([Dense(6),Dense(2)])

Step 9 - A continuación, inicialice un input_variable con 4 funciones de entrada que sirven como entrada para la red.

features = input_variable(4)

Step 10 - Ahora, para completarlo, necesitamos conectar la variable de características a la NN.

z = model(features)

Entonces, ahora tenemos un NN, con la ayuda de los siguientes pasos, entreneémoslo usando un conjunto de datos en memoria:

Step 11 - Para entrenar este NN, primero necesitamos importar el alumno de cntk.learnersmódulo. Nosotros importaremossgd alumno de la siguiente manera:

from cntk.learners import sgd

Step 12 - Junto con esa importación el ProgressPrinter desde cntk.logging módulo también.

from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)

Step 13 - A continuación, defina una nueva variable de entrada para las etiquetas de la siguiente manera -

labels = input_variable(2)

Step 14 - Para entrenar el modelo NN, a continuación, necesitamos definir una pérdida usando el binary_cross_entropyfunción. Además, proporcione el modelo zy la variable de etiquetas.

loss = binary_cross_entropy(z, labels)

Step 15 - A continuación, inicialice el sgd alumno de la siguiente manera:

learner = sgd(z.parameters, lr=0.1)

Step 16- Por último, llame al método de tren en la función de pérdida. Además, proporcione los datos de entrada,sgd aprendiz y el progress_printer.−

training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])

Ejemplo de implementación completo

import numpy as np
num_samples = 20000
label_mapping = np.eye(2)
y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)
x = np.random.random(size=(num_samples, 4)).astype(np.float32)
from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid
from cntk.losses import binary_cross_entropy
with default_options(activation=sigmoid):
   model = Sequential([Dense(6),Dense(2)])
features = input_variable(4)
z = model(features)
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(2)
loss = binary_cross_entropy(z, labels)
learner = sgd(z.parameters, lr=0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])

Salida

Build info:
     Built time: *** ** **** 21:40:10
     Last modified date: *** *** ** 21:08:46 2019
     Build type: Release
     Build target: CPU-only
     With ASGD: yes
     Math lib: mkl
     Build Branch: HEAD
     Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
     MPI distribution: Microsoft MPI
     MPI version: 7.0.12437.6
-------------------------------------------------------------------
average   since   average   since examples
loss      last    metric    last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.52      1.52      0         0     32
1.51      1.51      0         0     96
1.48      1.46      0         0    224
1.45      1.42      0         0    480
1.42       1.4      0         0    992
1.41      1.39      0         0   2016
1.4       1.39      0         0   4064
1.39      1.39      0         0   8160
1.39      1.39      0         0  16352

Usando Pandas DataFrames

Las matrices Numpy son muy limitadas en lo que pueden contener y una de las formas más básicas de almacenar datos. Por ejemplo, una única matriz n-dimensional puede contener datos de un solo tipo de datos. Pero, por otro lado, para muchos casos del mundo real, necesitamos una biblioteca que pueda manejar más de un tipo de datos en un solo conjunto de datos.

Una de las bibliotecas de Python llamada Pandas facilita el trabajo con este tipo de conjuntos de datos. Introduce el concepto de DataFrame (DF) y nos permite cargar conjuntos de datos desde el disco almacenados en varios formatos como DF. Por ejemplo, podemos leer DF almacenados como CSV, JSON, Excel, etc.

Puede aprender la biblioteca Python Pandas con más detalle en https://www.tutorialspoint.com/python_pandas/index.htm.

Ejemplo de implementación

En este ejemplo, vamos a utilizar el ejemplo de clasificación de tres posibles especies de flores de iris en función de cuatro propiedades. También hemos creado este modelo de aprendizaje profundo en las secciones anteriores. El modelo es el siguiente:

from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid, log_softmax
from cntk.losses import binary_cross_entropy
model = Sequential([
Dense(4, activation=sigmoid),
Dense(3, activation=log_softmax)
])
features = input_variable(4)
z = model(features)

El modelo anterior contiene una capa oculta y una capa de salida con tres neuronas para que coincida con el número de clases que podemos predecir.

A continuación, usaremos el train método y lossfunción para entrenar la red. Para esto, primero debemos cargar y preprocesar el conjunto de datos del iris, de modo que coincida con el diseño y formato de datos esperados para el NN. Se puede hacer con la ayuda de los siguientes pasos:

Step 1 - Importar el numpy y Pandas paquete de la siguiente manera -

import numpy as np
import pandas as pd

Step 2 - A continuación, use el read_csv función para cargar el conjunto de datos en la memoria -

df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’,
 ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)

Step 3 - Ahora, necesitamos crear un diccionario que mapeará las etiquetas en el conjunto de datos con su representación numérica correspondiente.

label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}

Step 4 - Ahora, usando iloc indexador en el DataFrame, seleccione las primeras cuatro columnas de la siguiente manera:

x = df_source.iloc[:, :4].values

Step 5−A continuación, debemos seleccionar las columnas de especies como etiquetas para el conjunto de datos. Se puede hacer de la siguiente manera:

y = df_source[‘species’].values

Step 6 - Ahora, necesitamos mapear las etiquetas en el conjunto de datos, lo cual se puede hacer usando label_mapping. Además, useone_hot codificación para convertirlos en matrices de codificación one-hot.

y = np.array([one_hot(label_mapping[v], 3) for v in y])

Step 7 - A continuación, para usar las características y las etiquetas mapeadas con CNTK, necesitamos convertirlos a ambos en flotantes -

x= x.astype(np.float32)
y= y.astype(np.float32)

Como sabemos, las etiquetas se almacenan en el conjunto de datos como cadenas y CNTK no puede funcionar con estas cadenas. Esa es la razón, necesita vectores codificados one-hot que representen las etiquetas. Para esto, podemos definir una función digamosone_hot como sigue -

def one_hot(index, length):
result = np.zeros(length)
result[index] = index
return result

Ahora, tenemos la matriz numpy en el formato correcto, con la ayuda de los siguientes pasos podemos usarlos para entrenar nuestro modelo:

Step 8- Primero, necesitamos importar la función de pérdida para entrenar la red. Vamos a importarbinary_cross_entropy_with_softmax como función de pérdida -

from cntk.losses import binary_cross_entropy_with_softmax

Step 9 - Para entrenar a este NN, también necesitamos importar el alumno de cntk.learnersmódulo. Nosotros importaremossgd alumno de la siguiente manera:

from cntk.learners import sgd

Step 10 - Junto con esa importación el ProgressPrinter desde cntk.logging módulo también.

from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)

Step 11 - A continuación, defina una nueva variable de entrada para las etiquetas de la siguiente manera -

labels = input_variable(3)

Step 12 - Para entrenar el modelo NN, a continuación, necesitamos definir una pérdida usando el binary_cross_entropy_with_softmaxfunción. También proporcione el modelo zy la variable de etiquetas.

loss = binary_cross_entropy_with_softmax (z, labels)

Step 13 - A continuación, inicialice el sgd alumno de la siguiente manera:

learner = sgd(z.parameters, 0.1)

Step 14- Por último, llame al método de tren en la función de pérdida. Además, proporcione los datos de entrada,sgd aprendiz y el progress_printer.

training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=
[progress_writer],minibatch_size=16,max_epochs=5)

Ejemplo de implementación completo

from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid, log_softmax
from cntk.losses import binary_cross_entropy
model = Sequential([
Dense(4, activation=sigmoid),
Dense(3, activation=log_softmax)
])
features = input_variable(4)
z = model(features)
import numpy as np
import pandas as pd
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
x = df_source.iloc[:, :4].values
y = df_source[‘species’].values
y = np.array([one_hot(label_mapping[v], 3) for v in y])
x= x.astype(np.float32)
y= y.astype(np.float32)
def one_hot(index, length):
result = np.zeros(length)
result[index] = index
return result
from cntk.losses import binary_cross_entropy_with_softmax
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(3)
loss = binary_cross_entropy_with_softmax (z, labels)
learner = sgd(z.parameters, 0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer],minibatch_size=16,max_epochs=5)

Salida

Build info:
     Built time: *** ** **** 21:40:10
     Last modified date: *** *** ** 21:08:46 2019
     Build type: Release
     Build target: CPU-only
     With ASGD: yes
     Math lib: mkl
     Build Branch: HEAD
     Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
     MPI distribution: Microsoft MPI
     MPI version: 7.0.12437.6
-------------------------------------------------------------------
average    since    average   since   examples
loss        last     metric   last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.1         1.1        0       0      16
0.835     0.704        0       0      32
1.993      1.11        0       0      48
1.14       1.14        0       0     112
[………]

Entrenamiento con grandes conjuntos de datos

En la sección anterior, trabajamos con pequeños conjuntos de datos en memoria usando Numpy y pandas, pero no todos los conjuntos de datos son tan pequeños. Especialmente los conjuntos de datos que contienen imágenes, videos y muestras de sonido son grandes.MinibatchSourcees un componente que puede cargar datos en trozos, proporcionado por CNTK para trabajar con conjuntos de datos tan grandes. Algunas de las características deMinibatchSource Los componentes son los siguientes:

  • MinibatchSource puede evitar que NN se sobreajuste al aleatorizar automáticamente las muestras leídas desde la fuente de datos.

  • Tiene una canalización de transformación incorporada que se puede utilizar para aumentar los datos.

  • Carga los datos en un subproceso en segundo plano separado del proceso de entrenamiento.

En las siguientes secciones, exploraremos cómo usar una fuente de minibatch con datos sin memoria para trabajar con grandes conjuntos de datos. También exploraremos cómo podemos usarlo para alimentar para entrenar a un NN.

Crear instancia de MinibatchSource

En la sección anterior, usamos el ejemplo de la flor de iris y trabajamos con un pequeño conjunto de datos en memoria usando Pandas DataFrames. Aquí, reemplazaremos el código que usa datos de un pandas DF conMinibatchSource. Primero, necesitamos crear una instancia deMinibatchSource con la ayuda de los siguientes pasos:

Ejemplo de implementación

Step 1 - Primero, desde cntk.io módulo importe los componentes para el minibatchsource de la siguiente manera:

from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer,
 INFINITY_REPEAT

Step 2 - Ahora, usando StreamDef class, cree una definición de flujo para las etiquetas.

labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)

Step 3 - A continuación, cree para leer las características archivadas desde el archivo de entrada, cree otra instancia de StreamDef como sigue.

feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)

Step 4 - Ahora, necesitamos proporcionar iris.ctf archivo como entrada e inicializar el deserializer como sigue -

deserializer = CTFDeserializer(‘iris.ctf’, StreamDefs(labels=
label_stream, features=features_stream)

Step 5 - Por fin, necesitamos crear una instancia de minisourceBatch mediante el uso deserializer como sigue -

Minibatch_source = MinibatchSource(deserializer, randomize=True)

Creación de una instancia de MinibatchSource: ejemplo de implementación completo

from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer, INFINITY_REPEAT
labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)
feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)
deserializer = CTFDeserializer(‘iris.ctf’, StreamDefs(labels=label_stream, features=features_stream)
Minibatch_source = MinibatchSource(deserializer, randomize=True)

Creando archivo MCTF

Como ha visto anteriormente, estamos tomando los datos del archivo 'iris.ctf'. Tiene el formato de archivo llamado CNTK Text Format (CTF). Es obligatorio crear un archivo CTF para obtener los datos delMinibatchSourceinstancia que creamos arriba. Veamos cómo podemos crear un archivo CTF.

Ejemplo de implementación

Step 1 - Primero, necesitamos importar los paquetes pandas y numpy de la siguiente manera -

import pandas as pd
import numpy as np

Step 2- A continuación, necesitamos cargar nuestro archivo de datos, es decir, iris.csv en la memoria. Luego, guárdelo en eldf_source variable.

df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)

Step 3 - Ahora, usando ilocindexador como características, tome el contenido de las primeras cuatro columnas. Además, use los datos de la columna de especies de la siguiente manera:

features = df_source.iloc[: , :4].values
labels = df_source[‘species’].values

Step 4- A continuación, necesitamos crear un mapeo entre el nombre de la etiqueta y su representación numérica. Se puede hacer creandolabel_mapping como sigue -

label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}

Step 5 - Ahora, convierta las etiquetas en un conjunto de vectores codificados one-hot de la siguiente manera -

labels = [one_hot(label_mapping[v], 3) for v in labels]

Ahora, como hicimos antes, cree una función de utilidad llamada one_hotpara codificar las etiquetas. Se puede hacer de la siguiente manera:

def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result

Como hemos cargado y preprocesado los datos, es hora de almacenarlos en el disco en el formato de archivo CTF. Podemos hacerlo con la ayuda de seguir el código de Python:

With open(‘iris.ctf’, ‘w’) as output_file:
for index in range(0, feature.shape[0]):
feature_values = ‘ ‘.join([str(x) for x in np.nditer(features[index])])
label_values = ‘ ‘.join([str(x) for x in np.nditer(labels[index])])
output_file.write(‘features {} | labels {} \n’.format(feature_values, label_values))

Creación de un archivo MCTF: ejemplo de implementación completo

import pandas as pd
import numpy as np
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
features = df_source.iloc[: , :4].values
labels = df_source[‘species’].values
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
labels = [one_hot(label_mapping[v], 3) for v in labels]
def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result
With open(‘iris.ctf’, ‘w’) as output_file:
for index in range(0, feature.shape[0]):
feature_values = ‘ ‘.join([str(x) for x in np.nditer(features[index])])
label_values = ‘ ‘.join([str(x) for x in np.nditer(labels[index])])
output_file.write(‘features {} | labels {} \n’.format(feature_values, label_values))

Alimentando los datos

Una vez que crea MinibatchSource,ejemplo, tenemos que entrenarlo. Podemos usar la misma lógica de entrenamiento que usamos cuando trabajamos con pequeños conjuntos de datos en memoria. Aquí usaremosMinibatchSource instancia como entrada para el método de tren en la función de pérdida de la siguiente manera:

Ejemplo de implementación

Step 1 - Para registrar el resultado de la sesión de entrenamiento, primero importe ProgressPrinter desde cntk.logging módulo de la siguiente manera -

from cntk.logging import ProgressPrinter

Step 2 - A continuación, para configurar la sesión de formación, importe el trainer y training_session desde cntk.train módulo de la siguiente manera -

from cntk.train import Trainer,

Step 3 - Ahora, necesitamos definir un conjunto de constantes como minibatch_size, samples_per_epoch y num_epochs como sigue -

minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30

Step 4 - A continuación, para saber CNTK cómo leer datos durante el entrenamiento, necesitamos definir un mapeo entre la variable de entrada para la red y los flujos en la fuente del minibatch.

input_map = {
     features: minibatch.source.streams.features,
     labels: minibatch.source.streams.features
}

Step 5 - A continuación, para registrar la salida del proceso de entrenamiento, inicialice el progress_printer variable con una nueva ProgressPrinter instancia de la siguiente manera:

progress_writer = ProgressPrinter(0)

Step 6 - Por fin, necesitamos invocar el método del tren en la pérdida de la siguiente manera -

train_history = loss.train(minibatch_source,
parameter_learners=[learner],
  model_inputs_to_streams=input_map,
callbacks=[progress_writer],
epoch_size=samples_per_epoch,
max_epochs=num_epochs)

Alimentando los datos: ejemplo de implementación completo

from cntk.logging import ProgressPrinter
from cntk.train import Trainer, training_session
minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
input_map = {
   features: minibatch.source.streams.features,
   labels: minibatch.source.streams.features
}
progress_writer = ProgressPrinter(0)
train_history = loss.train(minibatch_source,
parameter_learners=[learner],
model_inputs_to_streams=input_map,
callbacks=[progress_writer],
epoch_size=samples_per_epoch,
max_epochs=num_epochs)

Salida

-------------------------------------------------------------------
average   since   average   since  examples
loss      last     metric   last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.21      1.21      0        0       32
1.15      0.12      0        0       96
[………]