CNTK - Conjuntos de dados sem memória

Neste capítulo, será explicado como medir o desempenho de conjuntos de dados sem memória.

Nas seções anteriores, discutimos sobre vários métodos para validar o desempenho de nosso NN, mas os métodos que discutimos são aqueles que lidam com os conjuntos de dados que cabem na memória.

Aqui, surge a pergunta sobre os conjuntos de dados sem memória, porque no cenário de produção, precisamos de muitos dados para treinar NN. Nesta seção, vamos discutir como medir o desempenho ao trabalhar com fontes de minibatch e loop manual de minibatch.

Fontes de minibatch

Ao trabalhar com conjuntos de dados sem memória, ou seja, fontes de minibatch, precisamos de uma configuração ligeiramente diferente para perda, bem como métrica, do que a configuração que usamos ao trabalhar com pequenos conjuntos de dados, ou seja, conjuntos de dados em memória. Primeiro, veremos como configurar uma maneira de alimentar o treinador do modelo NN.

A seguir estão as etapas de implementação -

Step 1 - Primeiro, de cntk.O módulo io importa os componentes para criar a fonte do minibatch da seguinte maneira−

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

Step 2 - Em seguida, crie uma nova função chamada say create_datasource. Esta função terá dois parâmetros a saber, nome de arquivo e limite, com um valor padrão deINFINITELY_REPEAT.

def create_datasource(filename, limit =INFINITELY_REPEAT)

Step 3 - Agora, dentro da função, usando StreamDefclass crate uma definição de fluxo para os rótulos que lê do campo rótulos que tem três recursos. Também precisamos definiris_sparse para False como segue -

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

Step 4 - Em seguida, crie para ler os recursos arquivados do arquivo de entrada, crie outra instância de StreamDef do seguinte modo.

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

Step 5 - Agora, inicialize o CTFDeserializerclasse de instância. Especifique o nome do arquivo e os fluxos que precisamos desserializar da seguinte forma -

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

Step 6 - Em seguida, precisamos criar uma instância de minisourceBatch usando o desserializador da seguinte forma -

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

Step 7- Por fim, precisamos fornecer fonte de treinamento e teste, que criamos nas seções anteriores também. Estamos usando o conjunto de dados de flores de íris.

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

Depois de criar MinibatchSourceexemplo, precisamos treiná-lo. Podemos usar a mesma lógica de treinamento usada quando trabalhamos com pequenos conjuntos de dados na memória. Aqui, vamos usarMinibatchSource exemplo, como a entrada para o método de trem na função de perda da seguinte forma -

A seguir estão as etapas de implementação -

Step 1 - Para registrar o resultado da sessão de treinamento, primeiro importe o ProgressPrinter de cntk.logging módulo da seguinte forma -

from cntk.logging import ProgressPrinter

Step 2 - Em seguida, para configurar a sessão de treinamento, importe o trainer e training_session de cntk.train módulo da seguinte forma -

from cntk.train import Trainer, training_session

Step 3 - Agora, precisamos definir algum conjunto de constantes como minibatch_size, samples_per_epoch e num_epochs como segue -

minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
max_samples = samples_per_epoch * num_epochs

Step 4 - A seguir, para saber como ler os dados durante o treinamento em CNTK, precisamos definir um mapeamento entre a variável de entrada da rede e os fluxos na fonte do minibatch.

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

Step 5 - Em seguida, para registrar a saída do processo de treinamento, inicialize o progress_printer variável com um novo ProgressPrinterinstância. Além disso, inicialize otrainer e fornecê-lo com o modelo da seguinte maneira−

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

Step 6 - Por fim, para iniciar o processo de treinamento, precisamos invocar o training_session funcionar da seguinte forma -

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()

Depois de treinar o modelo, podemos adicionar validação a esta configuração usando um TestConfig objeto e atribuí-lo ao test_config argumento de palavra-chave do train_session função.

A seguir estão as etapas de implementação -

Step 1 - Primeiro, precisamos importar o TestConfig classe do módulo cntk.train como segue -

from cntk.train import TestConfig

Step 2 - Agora, precisamos criar uma nova instância do TestConfig com o test_source como entrada−

Test_config = TestConfig(test_source)

Exemplo 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)

Resultado

-------------------------------------------------------------------
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;

Loop de minibatch manual

Como vimos acima, é fácil medir o desempenho de nosso modelo NN durante e após o treinamento, usando as métricas ao treinar com APIs regulares em CNTK. Mas, por outro lado, as coisas não serão tão fáceis ao trabalhar com um loop de minibatch manual.

Aqui, estamos usando o modelo fornecido abaixo com 4 entradas e 3 saídas do conjunto de dados Iris Flower, criado também nas seções 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)

Em seguida, a perda para o modelo é definida como a combinação da função de perda de entropia cruzada e a métrica de medida F como usada nas seções anteriores. Vamos usar ocriterion_factory utilitário, para criá-lo como um objeto de função CNTK, conforme mostrado abaixo -

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
}

Agora, como definimos a função de perda, veremos como podemos usá-la no treinador, para configurar uma sessão de treinamento manual.

A seguir estão as etapas de implementação -

Step 1 - Primeiro, precisamos importar os pacotes necessários, como numpy e pandas para carregar e pré-processar os dados.

import pandas as pd
import numpy as np

Step 2 - Em seguida, para registrar informações durante o treinamento, importe o ProgressPrinter classe como segue -

from cntk.logging import ProgressPrinter

Step 3 - Então, precisamos importar o módulo do treinador do módulo cntk.train da seguinte forma -

from cntk.train import Trainer

Step 4 - Em seguida, crie uma nova instância de ProgressPrinter como segue -

progress_writer = ProgressPrinter(0)

Step 5 - Agora, precisamos inicializar o treinador com os parâmetros a perda, o aluno e o progress_writer como segue -

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

Step 6−A seguir, para treinar o modelo, criaremos um loop que irá iterar sobre o conjunto de dados trinta vezes. Este será o ciclo de treinamento externo.

for _ in range(0,30):

Step 7- Agora, precisamos carregar os dados do disco usando o pandas. Então, para carregar o conjunto de dados emmini-batches, colocou o chunksize argumento de palavra-chave para 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 - Agora, crie um treinamento interno para que o loop itere sobre cada um dos mini-batches.

for df_batch in input_data:

Step 9 - Agora, dentro deste loop, leia as primeiras quatro colunas usando o iloc indexador, como o features para treinar e convertê-los em float32 -

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

Step 10 - Agora, leia a última coluna como os rótulos para treinar, como segue -

label_values = df_batch.iloc[:,-1]

Step 11 - A seguir, usaremos vetores one-hot para converter as strings de rótulo em sua apresentação numérica da seguinte forma -

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

Step 12- Em seguida, faça a apresentação numérica das etiquetas. Em seguida, converta-os em uma matriz numpy, para que seja mais fácil trabalhar com eles da seguinte maneira -

label_values = label_values.values

Step 13 - Agora, precisamos criar uma nova matriz numpy que tenha o mesmo número de linhas que os valores de rótulo que convertemos.

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

Step 14 - Agora, a fim de criar rótulos com codificação one-hot, selecione as colunas com base nos valores numéricos dos rótulos.

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

Step 15 - Por fim, precisamos invocar o train_minibatch no treinador e fornecer os recursos processados ​​e rótulos para o minibatch.

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

Exemplo 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})

Resultado

-------------------------------------------------------------------
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
[………]

Na saída acima, obtivemos a saída para a perda e a métrica durante o treinamento. É porque combinamos uma métrica e perda em um objeto de função e usamos uma impressora de progresso na configuração do treinador.

Agora, a fim de avaliar o desempenho do modelo, precisamos realizar a mesma tarefa do treinamento do modelo, mas desta vez, precisamos usar um Evaluatorinstância para testar o modelo. É mostrado no seguinte 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()

Agora, obteremos a saída algo como o seguinte−

Resultado

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