Microsoft-cognitive-toolkit-out-of-memory-datasets

提供:Dev Guides
移動先:案内検索

CNTK-メモリ不足のデータセット

この章では、メモリ不足のデータセットのパフォーマンスを測定する方法について説明します。

前のセクションでは、NNのパフォーマンスを検証するさまざまな方法について説明しましたが、ここで説明した方法は、メモリに収まるデータセットを処理する方法です。

ここでは、メモリ不足のデータセットについての質問が発生します。本番シナリオでは、 NN をトレーニングするために大量のデータが必要になるためです。 このセクションでは、ミニバッチソースと手動ミニバッチループを使用する場合のパフォーマンスを測定する方法について説明します。

ミニバッチソース

メモリ不足のデータセットを操作しているとき、つまり ミニバッチソースの場合、小さなデータセットを操作するときに使用したセットアップとは少し異なる、セットアップとメトリックのセットアップが必要です。 インメモリデータセット。 最初に、NNモデルのトレーナーにデータをフィードする方法を設定する方法を説明します。

次に、実装手順を示します。

  • ステップ1 *-まず、cntk。 ioモジュールから、次のようにミニバッチソースを作成するためのコンポーネントをインポートします-
from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer,
 INFINITY_REPEAT

ステップ2 *-次に、say *create_datasource という名前の新しい関数を作成します。 この関数には、ファイル名と制限という2つのパラメーターがあり、デフォルト値は INFINITELY_REPEAT です。

def create_datasource(filename, limit =INFINITELY_REPEAT)

ステップ3 *-関数内で、 *StreamDef クラスを使用して、3つの機能を持つラベルフィールドから読み取るラベルのストリーム定義を作成します。 また、次のように is_sparseFalse に設定する必要があります

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* インスタンスを使用します-

次に、実装手順を示します。

ステップ1 *-トレーニングセッションの出力をログに記録するには、まず次のように *cntk.logging モジュールから ProgressPrinter をインポートします-

from cntk.logging import ProgressPrinter

ステップ2 *-次に、トレーニングセッションを設定するには、次のように *cntk.train モジュールから trainer および 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でのトレーニング中にデータを読み取る方法を知るために、ネットワークの入力変数とミニバッチソースのストリーム間のマッピングを定義する必要があります。
input_map = {
   features: training_source.streams.features,
   labels: training_source.streams.labels
}

ステップ5 *-次にトレーニングプロセスの出力をログに記録するには、 *progress_printer 変数を新しい ProgressPrinter インスタンスで初期化します。 また、 trainer を初期化し、次のようにモデルを提供します

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モデルのパフォーマンスを簡単に測定できます。 しかし、一方で、手動のミニバッチループで作業している間は、それほど簡単ではありません。

ここでは、前のセクションでも作成した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メジャーメトリックの組み合わせとして定義されます。 以下に示すように、 criterion_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モジュールからトレーナーモジュールをインポートする必要があります-
from cntk.train import Trainer

ステップ4 *-次に、次のように *ProgressPrinter の新しいインスタンスを作成します-

progress_writer = ProgressPrinter(0)

ステップ5 *-次に、損失、学習者、 *progress_writer のパラメーターを使用してトレーナーを次のように初期化する必要があります-

trainer = Trainer(z, loss, learner, progress_writer)
  • ステップ6 *-次に、モデルをトレーニングするために、データセットを30回反復するループを作成します。 これが外側のトレーニングループになります。
for _ in range(0,30):

ステップ7 *-次に、パンダを使用してディスクからデータをロードする必要があります。 次に、 *mini-batches にデータセットをロードするために、 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 インデクサーを使用して最初の4つの列を、トレーニングおよび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 メソッドを呼び出し、ミニバッチの処理済みの機能とラベルを提供する必要があります。

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;