CNTK - Conjuntos de datos sin memoria

En este capítulo, se explicará cómo medir el rendimiento de conjuntos de datos sin memoria.

En secciones anteriores, hemos discutido sobre varios métodos para validar el rendimiento de nuestro NN, pero los métodos que hemos discutido son los que se ocupan de los conjuntos de datos que caben en la memoria.

Aquí, surge la pregunta sobre los conjuntos de datos sin memoria, porque en el escenario de producción, necesitamos muchos datos para entrenar NN. En esta sección, analizaremos cómo medir el rendimiento cuando se trabaja con fuentes de minibatch y bucle de minibatch manual.

Fuentes de minibatch

Mientras trabajamos con conjuntos de datos sin memoria, es decir, fuentes de minibatch, necesitamos una configuración de pérdida ligeramente diferente, así como métrica, que la configuración que usamos al trabajar con conjuntos de datos pequeños, es decir, conjuntos de datos en memoria. Primero, veremos cómo configurar una forma de alimentar datos al entrenador del modelo NN.

Los siguientes son los pasos de implementación:

Step 1 - Primero, desde cntk.El módulo io importa los componentes para crear la fuente del minibatch de la siguiente manera:

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

Step 2 - A continuación, cree una nueva función llamada decir create_datasource. Esta función tendrá dos parámetros, a saber, nombre de archivo y límite, con un valor predeterminado deINFINITELY_REPEAT.

def create_datasource(filename, limit =INFINITELY_REPEAT)

Step 3 - Ahora, dentro de la función, usando StreamDefclass crate una definición de flujo para las etiquetas que se lee en el campo de etiquetas que tiene tres características. También necesitamos estableceris_sparse a False como sigue

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

Step 4 - 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 5 - Ahora, inicialice el CTFDeserializerclase de instancia. Especifique el nombre de archivo y los flujos que necesitamos deserializar de la siguiente manera:

deserializer = CTFDeserializer(filename, StreamDefs(labels=
label_stream, features=features_stream)

Step 6 - A continuación, necesitamos crear una instancia de minisourceBatch usando deserializador de la siguiente manera -

Minibatch_source = MinibatchSource(deserializer, randomize=True, max_sweeps=limit)
return minibatch_source

Step 7- Por último, debemos proporcionar una fuente de capacitación y prueba, que también creamos en secciones anteriores. Estamos utilizando un conjunto de datos de flores de iris.

training_source = create_datasource(‘Iris_train.ctf’)
test_source = create_datasource(‘Iris_test.ctf’, limit=1)

Una vez que crea MinibatchSourceejemplo, 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 ejemplo, como entrada para el método de tren en la función de pérdida de la siguiente manera:

Los siguientes son los pasos de implementación:

Step 1 - Para registrar el resultado de la sesión de entrenamiento, primero importe el 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, training_session

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
max_samples = samples_per_epoch * num_epochs

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

input_map = {
   features: training_source.streams.features,
   labels: training_source.streams.labels
}

Step 5 - Junto a registrar la salida del proceso de entrenamiento, inicialice el progress_printer variable con una nueva ProgressPrinterejemplo. Además, inicialice eltrainer y proporcione el modelo de la siguiente manera:

progress_writer = ProgressPrinter(0)
trainer: training_source.streams.labels

Step 6 - Por fin, para iniciar el proceso de formación, necesitamos invocar el training_session funciona de la siguiente manera:

session = training_session(trainer,
   mb_source=training_source,
   mb_size=minibatch_size,
   model_inputs_to_streams=input_map,
   max_samples=max_samples,
   test_config=test_config)
session.train()

Una vez que entrenamos el modelo, podemos agregar validación a esta configuración usando un TestConfig objeto y asígnelo al test_config argumento de palabra clave del train_session función.

Los siguientes son los pasos de implementación:

Step 1 - Primero, necesitamos importar el TestConfig clase del módulo cntk.train como sigue

from cntk.train import TestConfig

Step 2 - Ahora, necesitamos crear una nueva instancia del TestConfig con el test_source como entrada

Test_config = TestConfig(test_source)

Ejemplo completo

from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer, INFINITY_REPEAT
def create_datasource(filename, limit =INFINITELY_REPEAT)
labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)
feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)
deserializer = CTFDeserializer(filename, StreamDefs(labels=label_stream, features=features_stream)
Minibatch_source = MinibatchSource(deserializer, randomize=True, max_sweeps=limit)
return minibatch_source
training_source = create_datasource(‘Iris_train.ctf’)
test_source = create_datasource(‘Iris_test.ctf’, limit=1)
from cntk.logging import ProgressPrinter
from cntk.train import Trainer, training_session
minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
max_samples = samples_per_epoch * num_epochs
input_map = {
   features:   training_source.streams.features,
   labels: training_source.streams.labels
 }
progress_writer = ProgressPrinter(0)
trainer: training_source.streams.labels
session = training_session(trainer,
   mb_source=training_source,
   mb_size=minibatch_size,
   model_inputs_to_streams=input_map,
   max_samples=max_samples,
   test_config=test_config)
session.train()
from cntk.train import TestConfig
Test_config = TestConfig(test_source)

Salida

-------------------------------------------------------------------
average   since   average   since  examples
loss      last    metric    last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.57      1.57     0.214    0.214   16
1.38      1.28     0.264    0.289   48
[………]
Finished Evaluation [1]: Minibatch[1-1]:metric = 69.65*30;

Bucle de minibatch manual

Como vemos anteriormente, es fácil medir el rendimiento de nuestro modelo NN durante y después del entrenamiento, utilizando las métricas cuando se entrena con API regulares en CNTK. Pero, por otro lado, las cosas no serán tan fáciles mientras se trabaja con un bucle de minibatch manual.

Aquí, estamos utilizando el modelo que se muestra a continuación con 4 entradas y 3 salidas del conjunto de datos Iris Flower, creado también en secciones anteriores.

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

A continuación, la pérdida para el modelo se define como la combinación de la función de pérdida de entropía cruzada y la métrica de medida F como se usó en las secciones anteriores. Vamos a utilizar elcriterion_factory utilidad, para crear esto como un objeto de función CNTK como se muestra a continuación

import cntk
from cntk.losses import cross_entropy_with_softmax, fmeasure
@cntk.Function
def criterion_factory(outputs, targets):
   loss = cross_entropy_with_softmax(outputs, targets)
   metric = fmeasure(outputs, targets, beta=1)
   return loss, metric
loss = criterion_factory(z, labels)
learner = sgd(z.parameters, 0.1)
label_mapping = {
   'Iris-setosa': 0,
   'Iris-versicolor': 1,
   'Iris-virginica': 2
}

Ahora, como hemos definido la función de pérdida, veremos cómo podemos utilizarla en el entrenador, para configurar una sesión de entrenamiento manual.

Los siguientes son los pasos de implementación:

Step 1 - Primero, necesitamos importar los paquetes requeridos como numpy y pandas para cargar y preprocesar los datos.

import pandas as pd
import numpy as np

Step 2 - A continuación, para registrar información durante el entrenamiento, importe el ProgressPrinter clase de la siguiente manera

from cntk.logging import ProgressPrinter

Step 3 - Entonces, necesitamos importar el módulo de entrenador del módulo cntk.train de la siguiente manera -

from cntk.train import Trainer

Step 4 - A continuación, cree una nueva instancia de ProgressPrinter como sigue -

progress_writer = ProgressPrinter(0)

Step 5 - Ahora, necesitamos inicializar el entrenador con los parámetros la pérdida, el alumno y el progress_writer como sigue -

trainer = Trainer(z, loss, learner, progress_writer)

Step 6−A continuación, para entrenar el modelo, crearemos un ciclo que iterará sobre el conjunto de datos treinta veces. Este será el ciclo de entrenamiento externo.

for _ in range(0,30):

Step 7- Ahora, necesitamos cargar los datos desde el disco usando pandas. Luego, para cargar el conjunto de datos enmini-batches, selecciona el chunksize argumento de palabra clave a 16.

input_data = pd.read_csv('iris.csv',
names=['sepal_length', 'sepal_width','petal_length','petal_width', 'species'],
index_col=False, chunksize=16)

Step 8 - Ahora, cree un ciclo de entrenamiento interno para iterar sobre cada uno de los mini-batches.

for df_batch in input_data:

Step 9 - Ahora dentro de este ciclo, lea las primeras cuatro columnas usando el iloc indexador, como el features para entrenar y convertirlos a float32 -

feature_values = df_batch.iloc[:,:4].values
feature_values = feature_values.astype(np.float32)

Step 10 - Ahora, lea la última columna como las etiquetas para entrenar, de la siguiente manera -

label_values = df_batch.iloc[:,-1]

Step 11 - A continuación, usaremos vectores one-hot para convertir las cadenas de etiquetas a su presentación numérica de la siguiente manera -

label_values = label_values.map(lambda x: label_mapping[x])

Step 12- Después de eso, tome la presentación numérica de las etiquetas. A continuación, conviértalos en una matriz numpy, para que sea más fácil trabajar con ellos de la siguiente manera:

label_values = label_values.values

Step 13 - Ahora, necesitamos crear una nueva matriz numpy que tenga el mismo número de filas que los valores de etiqueta que hemos convertido.

encoded_labels = np.zeros((label_values.shape[0], 3))

Step 14 - Ahora, para crear etiquetas codificadas en caliente, seleccione las columnas según los valores numéricos de la etiqueta.

encoded_labels[np.arange(label_values.shape[0]), label_values] = 1.

Step 15 - Por fin, necesitamos invocar el train_minibatch en el entrenador y proporcione las características procesadas y etiquetas para el minibatch.

trainer.train_minibatch({features: feature_values, labels: encoded_labels})

Ejemplo completo

from cntk import default_options, input_variable
from cntk.layers import Dense, Sequential
from cntk.ops import log_softmax, relu, sigmoid
from cntk.learners import sgd
model = Sequential([
   Dense(4, activation=sigmoid),
   Dense(3, activation=log_softmax)
])
features = input_variable(4)
labels = input_variable(3)
z = model(features)
import cntk
from cntk.losses import cross_entropy_with_softmax, fmeasure
@cntk.Function
def criterion_factory(outputs, targets):
   loss = cross_entropy_with_softmax(outputs, targets)
   metric = fmeasure(outputs, targets, beta=1)
   return loss, metric
loss = criterion_factory(z, labels)
learner = sgd(z.parameters, 0.1)
label_mapping = {
   'Iris-setosa': 0,
   'Iris-versicolor': 1,
   'Iris-virginica': 2
}
import pandas as pd
import numpy as np
from cntk.logging import ProgressPrinter
from cntk.train import Trainer
progress_writer = ProgressPrinter(0)
trainer = Trainer(z, loss, learner, progress_writer)
for _ in range(0,30):
   input_data = pd.read_csv('iris.csv',
      names=['sepal_length', 'sepal_width','petal_length','petal_width', 'species'],
      index_col=False, chunksize=16)
for df_batch in input_data:
   feature_values = df_batch.iloc[:,:4].values
   feature_values = feature_values.astype(np.float32)
   label_values = df_batch.iloc[:,-1]
label_values = label_values.map(lambda x: label_mapping[x])
label_values = label_values.values
   encoded_labels = np.zeros((label_values.shape[0], 3))
   encoded_labels[np.arange(label_values.shape[0]), 
label_values] = 1.
   trainer.train_minibatch({features: feature_values, labels: encoded_labels})

Salida

-------------------------------------------------------------------
average    since    average   since  examples
loss       last      metric   last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.45       1.45     -0.189    -0.189   16
1.24       1.13     -0.0382    0.0371  48
[………]

En el resultado anterior, obtuvimos tanto el resultado de la pérdida como la métrica durante el entrenamiento. Esto se debe a que combinamos una métrica y una pérdida en un objeto de función y usamos una impresora de progreso en la configuración del entrenador.

Ahora, para evaluar el desempeño del modelo, necesitamos realizar la misma tarea que con el entrenamiento del modelo, pero esta vez, necesitamos usar un Evaluatorinstancia para probar el modelo. Se muestra en el siguiente código Python

from cntk import Evaluator
evaluator = Evaluator(loss.outputs[1], [progress_writer])
input_data = pd.read_csv('iris.csv',
   names=['sepal_length', 'sepal_width','petal_length','petal_width', 'species'],
index_col=False, chunksize=16)
for df_batch in input_data:
   feature_values = df_batch.iloc[:,:4].values
   feature_values = feature_values.astype(np.float32)
   label_values = df_batch.iloc[:,-1]
   label_values = label_values.map(lambda x: label_mapping[x])
   label_values = label_values.values
   encoded_labels = np.zeros((label_values.shape[0], 3))
   encoded_labels[np.arange(label_values.shape[0]), label_values] = 1.
   evaluator.test_minibatch({ features: feature_values, labels:
      encoded_labels})
evaluator.summarize_test_progress()

Ahora, obtendremos un resultado parecido al siguiente:

Salida

Finished Evaluation [1]: Minibatch[1-11]:metric = 74.62*143;