📜  CNTK-内存不足数据集

📅  最后修改于: 2020-12-10 05:09:27             🧑  作者: Mango


在本章中,将说明如何测量内存不足数据集的性能。

在前面的部分中,我们讨论了各种方法来验证NN的性能,但是我们所讨论的方法是处理适合内存的数据集的方法。

在这里,出现了关于内存不足数据集的问题,因为在生产场景中,我们需要大量数据来训练NN 。在本节中,我们将讨论在使用微型批处理源和手动微型批处理循环时如何测量性能。

小批量货源

当使用内存不足的数据集(即小批量来源)时,与用于小型数据集(即内存中的数据集)时使用的设置相比,我们需要的损耗和度量设置略有不同。首先,我们将了解如何建立一种将数据馈送到NN模型训练器的方法。

以下是实施步骤-

步骤1-首先,从cntk。 io模块按如下方式导入用于创建minibatch源的组件-

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

步骤2-接下来,创建一个名为say create_datasource的新函数。该函数将具有两个参数,即filename和limit,其默认值为INFINITELY_REPEAT

def create_datasource(filename, limit =INFINITELY_REPEAT)

步骤3-现在,在函数,通过使用StreamDef类为从具有三个功能的labels字段读取的标签创建流定义。我们还需要将is_sparse设置为False ,如下所示:

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

步骤4-接下来,创建以读取输入文件中归档的功能,如下所示创建另一个StreamDef实例。

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

步骤5-现在,初始化CTFDeserializer实例类。指定我们需要反序列化的文件名和流,如下所示:

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

步骤6-接下来,我们需要使用反序列化器创建minisourceBatch的实例,如下所示-

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

步骤7-最后,我们需要提供培训和测试资源,这也是我们在上一节中创建的。我们正在使用鸢尾花数据集。

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

创建MinibatchSource实例后,我们需要对其进行培训。我们可以使用与处理小型内存数据集时相同的训练逻辑。在这里,我们将使用MinibatchSource实例,作为损失函数的train方法的输入,如下所示:

以下是实施步骤-

步骤1-为了记录培训课程的输出,请首先从cntk.logging模块导入ProgressPrinter ,如下所示:

from cntk.logging import ProgressPrinter

步骤2-接下来,要设置培训课程,请从cntk.train模块导入培训师training_session ,如下所示:

from cntk.train import Trainer, training_session

步骤3-现在,我们需要定义一些常量集,例如minibatch_sizesamples_per_epochnum_epochs ,如下所示:

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

步骤4-接下来,为了知道如何在CNTK训练期间读取数据,我们需要定义网络的输入变量和minibatch源中的流之间的映射。

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

步骤5-接下来要记录训练过程的输出,请使用新的ProgressPrinter实例初始化progress_printer变量。另外,初始化训练器并为其提供以下模型-

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

步骤6-最后,要开始训练过程,我们需要按以下方式调用training_session函数-

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

训练完模型后,我们可以使用TestConfig对象将验证添加到此设置,并将其分配给train_session函数的test_config关键字参数。

以下是实施步骤-

步骤1-首先,我们需要从模块cntk.train导入TestConfig类,如下所示:

from cntk.train import TestConfig

步骤2-现在,我们需要使用test_source作为输入来创建TestConfig的新实例-

Test_config = TestConfig(test_source)

完整的例子

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)

输出

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

手动小批量循环

正如我们在上面看到的,通过在CNTK中使用常规API进行训练时使用度量,可以很容易地测量训练期间和训练后NN模型的性能。但是,另一方面,使用手动minibatch循环时,事情不会那么容易。

在这里,我们使用下面给出的模型,该模型也具有在先前部分中创建的Iris Flower数据集的4个输入和3个输出-

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)

接下来,将模型的损失定义为交叉熵损失函数和前面几节中使用的F度量度量的组合。我们将使用criteria_factory实用工具,将其创建为CNTK函数对象,如下所示-

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
}

现在,我们已经定义了损失函数,我们将看到如何在培训师中使用它来设置手动培训课程。

以下是实施步骤-

步骤1-首先,我们需要导入所需的程序包(例如numpypandas)以加载和预处理数据。

import pandas as pd
import numpy as np

步骤2-接下来,为了在培训期间记录信息,请按以下方式导入ProgressPrinter类:

from cntk.logging import ProgressPrinter

步骤3-然后,我们需要从cntk.train模块导入trainer模块,如下所示-

from cntk.train import Trainer

步骤4-接下来,如下创建一个ProgressPrinter的新实例-

progress_writer = ProgressPrinter(0)

步骤5-现在,我们需要使用参数loss,学习者和progress_writer初始化培训器,如下所示:

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

步骤6-接下来,为了训练模型,我们将创建一个循环,该循环将遍历数据集三十次。这将是外部训练循环。

for _ in range(0,30):

步骤7-现在,我们需要使用熊猫从磁盘加载数据。然后,为了以小批量加载数据集,请将chunksize关键字参数设置为16。

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

步骤8-现在,为循环创建一个内部训练,以迭代每个迷你批

for df_batch in input_data:

第9步-现在,这个循环里,阅读使用ILOC索引的前四列,作为拥有从训练并将其转换为FLOAT32 –

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

步骤10-现在,读取最后一列作为要训练的标签,如下所示-

label_values = df_batch.iloc[:,-1]

步骤11-接下来,我们将使用一键向量将标签字符串转换为其数字表示,如下所示-

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

步骤12-之后,进行标签的数字表示。接下来,将它们转换为numpy数组,因此按以下方式更容易使用它们-

label_values = label_values.values

步骤13-现在,我们需要创建一个新的numpy数组,该数组具有与已转换的标签值相同的行数。

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

步骤14-现在,为了创建一键编码标签,请基于数字标签值选择列。

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

步骤15-最后,我们需要在训练器上调用train_minibatch方法,并为minibatch提供已处理的功能和标签。

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

完整的例子

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

输出

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

在上面的输出中,我们同时获得了损失和训练期间指标的输出。这是因为我们在函数对象中结合了度量和损失,并在训练器配置中使用了进度打印机。

现在,为了评估模型的性能,我们需要执行与训练模型相同的任务,但是这次,我们需要使用Evaluator实例来测试模型。在以下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()

现在,我们将获得类似以下的输出-

输出

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