手动小批量循环
正如我们在上面看到的,通过在 CNTK 中使用常规 API 进行训练时使用这些指标,可以很容易地衡量我们的 NN 模型在训练期间和之后的性能。但是,另一方面,在使用手动小批量循环时事情不会那么容易。
在这里,我们使用下面给出的模型,其中包含来自 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-measure 度量的组合。我们将使用标准工厂实用程序,将其创建为 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 步 - 首先,我们需要导入所需的包,如numpy和pandas来加载和预处理数据。
import pandas as pd
import numpy as np
第 2 步 - 接下来,为了在训练期间记录信息,导入ProgressPrinter类,如下所示 -
from cntk.logging import ProgressPrinter
第 3 步- 然后,我们需要从 cntk.train 模块导入训练器模块,如下所示 -
from cntk.train import Trainer
第 4 步- 接下来,创建ProgressPrinter的新实例,如下所示 -
progress_writer = ProgressPrinter(0)
第 5 步- 现在,我们需要使用参数 loss、learner 和progress_writer初始化训练器,如下所示 -
trainer = Trainer(z, loss, learner, progress_writer)
第 6 步- 接下来,为了训练模型,我们将创建一个循环,将在数据集上迭代 30 次。这将是外部训练循环。
第 7 步- 现在,我们需要使用 pandas 从磁盘加载数据。然后,为了以小批量加载数据集,请将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 步- 接下来,我们将使用 one-hot 向量将标签字符串转换为它们的数字表示,如下所示 -
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 步 - 现在,为了创建 one-hot 编码标签,请根据数字标签值选择列。
encoded_labels[np.arange(label_values.shape[0]), label_values] = 1.
第 15 步- 最后,我们需要在训练器上调用train_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;