Microsoft-cognitive-toolkit-in-memory-and-large-datasets
CNTK-インメモリと大きなデータセット
この章では、CNTKでメモリ内の大きなデータセットを操作する方法について学習します。
メモリが少ないデータセットを使用したトレーニング
CNTKトレーナーへのデータのフィードについて説明する場合、さまざまな方法がありますが、データセットのサイズとデータの形式によって異なります。 データセットは、メモリ内の小さなデータセットでも、大きなデータセットでもかまいません。
このセクションでは、メモリ内のデータセットを操作します。 このために、次の2つのフレームワークを使用します-
- ナンピー
- パンダ
Numpy配列の使用
ここでは、CNTKでランダムに生成されたnumpyベースのデータセットを使用します。 この例では、バイナリ分類問題のデータをシミュレートします。 4つの特徴を持つ一連の観測があり、ディープラーニングモデルで2つの可能なラベルを予測するとします。
実装例
このため、最初に、予測したいラベルのワンホットベクトル表現を含むラベルのセットを生成する必要があります。 それは次のステップの助けを借りて行うことができます-
ステップ1 *- *numpy パッケージを次のようにインポートします-
import numpy as np
num_samples = 20000
ステップ2 *-次に、次のように *np.eye 関数を使用してラベルマッピングを生成します-
label_mapping = np.eye(2)
ステップ3 *- *np.random.choice 関数を使用して、次のように20000個のランダムサンプルを収集します-
y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)
- ステップ4 *-ようやくnp.random.random関数を使用して、次のようにランダムな浮動小数点値の配列を生成します-
x = np.random.random(size=(num_samples, 4)).astype(np.float32)
ランダムな浮動小数点値の配列を生成したら、それらを32ビットの浮動小数点数に変換して、CNTKで予期される形式に一致させる必要があります。 これを行うには、以下の手順に従いましょう-
- ステップ5 *-次のようにcntk.layersモジュールから高密度および順次レイヤー関数をインポートします-
from cntk.layers import Dense, Sequential
- ステップ6 *-次に、ネットワークのレイヤーのアクティベーション機能をインポートする必要があります。 *シグモイド*を活性化関数としてインポートしましょう-
from cntk import input_variable, default_options
from cntk.ops import sigmoid
ステップ7 *-次に、損失関数をインポートしてネットワークをトレーニングする必要があります。 *binary_cross_entropy を損失関数としてインポートしましょう-
from cntk.losses import binary_cross_entropy
- ステップ8 *-次に、ネットワークのデフォルトオプションを定義する必要があります。 ここでは、デフォルト設定として*シグモイド*アクティベーション機能を提供します。 また、次のようにシーケンシャルレイヤー機能を使用してモデルを作成します-
with default_options(activation=sigmoid):
model = Sequential([Dense(6),Dense(2)])
ステップ9 *-次に、ネットワークの入力として機能する4つの入力フィーチャを使用して *input_variable を初期化します。
features = input_variable(4)
- ステップ10 *-次に、それを完了するために、機能変数をNNに接続する必要があります。
z = model(features)
これで、NNができました。次の手順を使用して、インメモリデータセットを使用してトレーニングします-
ステップ11 *-このNNをトレーニングするには、最初に *cntk.learners モジュールから学習者をインポートする必要があります。 sgd 学習者を次のようにインポートします-
from cntk.learners import sgd
ステップ12 *- *cntk.logging モジュールから ProgressPrinter もインポートします。
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
- ステップ13 *-次に、次のようにラベルの新しい入力変数を定義します-
labels = input_variable(2)
ステップ14 *-NNモデルをトレーニングするために、次に *binary_cross_entropy 関数を使用して損失を定義する必要があります。 また、モデルzとラベル変数を提供します。
loss = binary_cross_entropy(z, labels)
ステップ15 *-次に、 *sgd 学習器を次のように初期化します-
learner = sgd(z.parameters, lr=0.1)
ステップ16 *-最後に、損失関数でtrainメソッドを呼び出します。 また、入力データ、 *sgd ラーナー、 progress_printer を提供します。
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])
完全な実装例
import numpy as np
num_samples = 20000
label_mapping = np.eye(2)
y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)
x = np.random.random(size=(num_samples, 4)).astype(np.float32)
from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid
from cntk.losses import binary_cross_entropy
with default_options(activation=sigmoid):
model = Sequential([Dense(6),Dense(2)])
features = input_variable(4)
z = model(features)
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(2)
loss = binary_cross_entropy(z, labels)
learner = sgd(z.parameters, lr=0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])
出力
Build info:
Built time: *** ** *** *21:40:10
Last modified date:* ** *** ** 21:08:46 2019
Build type: Release
Build target: CPU-only
With ASGD: yes
Math lib: mkl
Build Branch: HEAD
Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
MPI distribution: Microsoft MPI
MPI version: 7.0.12437.6
-------------------------------------------------------------------
average since average since examples
loss last metric last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.52 1.52 0 0 32
1.51 1.51 0 0 96
1.48 1.46 0 0 224
1.45 1.42 0 0 480
1.42 1.4 0 0 992
1.41 1.39 0 0 2016
1.4 1.39 0 0 4064
1.39 1.39 0 0 8160
1.39 1.39 0 0 16352
Pandas DataFramesの使用
Numpy配列は、何を含めることができるか、データを保存する最も基本的な方法の1つに非常に制限があります。 たとえば、単一のn次元配列には、単一のデータ型のデータを含めることができます。 しかし、その一方で、実際の多くのケースでは、単一のデータセットで複数のデータ型を処理できるライブラリが必要です。
Pandasと呼ばれるPythonライブラリの1つを使用すると、このような種類のデータセットを簡単に操作できます。 DataFrame(DF)の概念を導入し、DFとしてさまざまな形式で保存されているディスクからデータセットを読み込むことができます。 たとえば、CSV、JSON、Excelなどとして保存されているDFを読み取ることができます。
Python Pandasライブラリについて詳しくは、リンク:/python_pandas/index [[[1]]]をご覧ください。
実装例
この例では、4つのプロパティに基づいて、アヤメの花の3つの可能な種を分類する例を使用します。 前のセクションでも、このディープラーニングモデルを作成しました。 モデルは次のとおりです-
from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid, log_softmax
from cntk.losses import binary_cross_entropy
model = Sequential([
Dense(4, activation=sigmoid),
Dense(3, activation=log_softmax)
])
features = input_variable(4)
z = model(features)
上記のモデルには、1つの非表示層と、予測できるクラスの数と一致する3つのニューロンを含む出力層が含まれています。
次に、 train メソッドと loss 関数を使用してネットワークをトレーニングします。 そのためには、最初にアイリスデータセットをロードして前処理し、NNの予想されるレイアウトとデータ形式に一致させる必要があります。 それは次のステップの助けを借りて行うことができます-
ステップ1 *- *numpy および Pandas パッケージを次のようにインポートします-
import numpy as np
import pandas as pd
ステップ2 *-次に、 *read_csv 関数を使用してデータセットをメモリに読み込みます-
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’,
‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
- ステップ3 *-次に、データセットのラベルを対応する数値表現にマッピングする辞書を作成する必要があります。
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
ステップ4 *-次に、 *DataFrame で iloc インデクサーを使用して、次のように最初の4列を選択します-
x = df_source.iloc[:, :4].values
- ステップ5 *-次に、データセットのラベルとして種の列を選択する必要があります。 それは次のように行うことができます-
y = df_source[‘species’].values
ステップ6 *-次に、 *label_mapping を使用してデータセット内のラベルをマップする必要があります。 また、 one_hot エンコーディングを使用して、それらをワンホットエンコーディング配列に変換します。
y = np.array([one_hot(label_mapping[v], 3) for v in y])
- ステップ7 *-次に、機能とマッピングされたラベルをCNTKで使用するには、両方を浮動小数点数に変換する必要があります-
x= x.astype(np.float32)
y= y.astype(np.float32)
ご存知のように、ラベルはデータセットに文字列として保存され、CNTKはこれらの文字列を処理できません。 そのため、ラベルを表すワンホットエンコードされたベクトルが必要です。 このために、次のように one_hot という関数を定義できます-
def one_hot(index, length):
result = np.zeros(length)
result[index] = index
return result
これで、正しい形式のnumpy配列が得られました。次の手順を使用して、それらを使用してモデルをトレーニングできます-
ステップ8 *-最初に、ネットワークをトレーニングするために損失関数をインポートする必要があります。 *binary_cross_entropy_with_softmax を損失関数としてインポートしましょう-
from cntk.losses import binary_cross_entropy_with_softmax
ステップ9 *-このNNをトレーニングするには、 *cntk.learners モジュールから学習者をインポートする必要もあります。 sgd 学習者を次のようにインポートします-
from cntk.learners import sgd
ステップ10 *- *cntk.logging モジュールから ProgressPrinter もインポートします。
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
- ステップ11 *-次に、次のようにラベルの新しい入力変数を定義します-
labels = input_variable(3)
ステップ12 *-NNモデルをトレーニングするために、次に *binary_cross_entropy_with_softmax 関数を使用して損失を定義する必要があります。 モデルzとラベル変数も提供します。
loss = binary_cross_entropy_with_softmax (z, labels)
ステップ13 *-次に、 *sgd 学習器を次のように初期化します-
learner = sgd(z.parameters, 0.1)
ステップ14 *-最後に、損失関数でtrainメソッドを呼び出します。 また、入力データ、 *sgd ラーナー、 progress_printer を提供します。
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=
[progress_writer],minibatch_size=16,max_epochs=5)
完全な実装例
from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid, log_softmax
from cntk.losses import binary_cross_entropy
model = Sequential([
Dense(4, activation=sigmoid),
Dense(3, activation=log_softmax)
])
features = input_variable(4)
z = model(features)
import numpy as np
import pandas as pd
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
x = df_source.iloc[:, :4].values
y = df_source[‘species’].values
y = np.array([one_hot(label_mapping[v], 3) for v in y])
x= x.astype(np.float32)
y= y.astype(np.float32)
def one_hot(index, length):
result = np.zeros(length)
result[index] = index
return result
from cntk.losses import binary_cross_entropy_with_softmax
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(3)
loss = binary_cross_entropy_with_softmax (z, labels)
learner = sgd(z.parameters, 0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer],minibatch_size=16,max_epochs=5)
出力
Build info:
Built time: *** ** *** *21:40:10
Last modified date:* ** *** * *21:08:46 2019
Build type: Release
Build target: CPU-only
With ASGD: yes
Math lib: mkl
Build Branch: HEAD
Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
MPI distribution: Microsoft MPI
MPI version: 7.0.12437.6
-------------------------------------------------------------------
average since average since examples
loss last metric last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.1 1.1 0 0 16
0.835 0.704 0 0 32
1.993 1.11 0 0 48
1.14 1.14 0 0 112
[………]
大規模なデータセットを使用したトレーニング
前のセクションでは、Numpyとpandasを使用して小さなインメモリデータセットを操作しましたが、すべてのデータセットがそれほど小さいわけではありません。 特に、画像、動画、音声サンプルを含むデータセットは大きいです。* MinibatchSource は、このような大きなデータセットを処理するためにCNTKによって提供される、チャンクでデータをロードできるコンポーネントです。 *MinibatchSource コンポーネントの機能のいくつかは次のとおりです-
- MinibatchSource は、データソースから読み取られたサンプルを自動的にランダム化することにより、NNが過剰適合しないようにすることができます。
- データの拡張に使用できる変換パイプラインが組み込まれています。
- トレーニングプロセスとは別のバックグラウンドスレッドでデータを読み込みます。
次のセクションでは、メモリ不足データを含むミニバッチソースを使用して、大規模なデータセットを処理する方法について説明します。 また、NNをトレーニングするためのフィードにそれを使用する方法についても説明します。
MinibatchSourceインスタンスの作成
前のセクションでは、アイリスの花の例を使用し、Pandas DataFramesを使用して小さなメモリ内データセットを操作しました。 ここでは、pandas DFからのデータを使用するコードを MinibatchSource に置き換えます。 まず、次の手順を使用して MinibatchSource のインスタンスを作成する必要があります-
実装例
ステップ1 *-まず、 *cntk.io モジュールから、次のようにminibatchsourceのコンポーネントをインポートします-
from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer,
INFINITY_REPEAT
ステップ2 *- *StreamDef クラスを使用して、ラベルのストリーム定義を作成します。
labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)
手順3 *-次に、入力ファイルからファイルされた機能を読み取るために作成し、次のように *StreamDef の別のインスタンスを作成します。
feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)
ステップ4 *-ここで、入力として *iris.ctf ファイルを提供し、次のように*デシリアライザ*を初期化する必要があります-
deserializer = CTFDeserializer(‘iris.ctf’, StreamDefs(labels=
label_stream, features=features_stream)
ステップ5 *-最後に、次のように *deserializer を使用して minisourceBatch のインスタンスを作成する必要があります-
Minibatch_source = MinibatchSource(deserializer, randomize=True)
MinibatchSourceインスタンスの作成-完全な実装例
from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer, INFINITY_REPEAT
labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)
feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)
deserializer = CTFDeserializer(‘iris.ctf’, StreamDefs(labels=label_stream, features=features_stream)
Minibatch_source = MinibatchSource(deserializer, randomize=True)
MCTFファイルの作成
上記のように、「iris.ctf」ファイルからデータを取得しています。 CNTK Text Format(CTF)というファイル形式です。 上記で作成した MinibatchSource インスタンスのデータを取得するには、CTFファイルを作成する必要があります。 CTFファイルを作成する方法を見てみましょう。
実装例
- ステップ1 *-まず、次のようにpandasパッケージとnumpyパッケージをインポートする必要があります-
import pandas as pd
import numpy as np
ステップ2 *-次に、データファイルをロードする必要があります。 iris.csvをメモリに。 次に、それを *df_source 変数に格納します。
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
ステップ3 *-次に、 *iloc インデクサーを機能として使用して、最初の4列の内容を取得します。 また、次のように種の列からのデータを使用します-
features = df_source.iloc[: , :4].values
labels = df_source[‘species’].values
ステップ4 *-次に、ラベル名とその数値表現の間のマッピングを作成する必要があります。 次のように *label_mapping を作成することで実行できます-
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
- ステップ5 *-次のように、ラベルをワンホットエンコードされたベクトルのセットに変換します-
labels = [one_hot(label_mapping[v], 3) for v in labels]
ここで、前と同じように、 one_hot というユーティリティ関数を作成してラベルをエンコードします。 それは次のように行うことができます-
def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result
データを読み込んで前処理したので、今度はCTFファイル形式でディスクに保存します。 私たちは次のPythonコードの助けを借りてそれを行うことができます-
With open(‘iris.ctf’, ‘w’) as output_file:
for index in range(0, feature.shape[0]):
feature_values = ‘ ‘.join([str(x) for x in np.nditer(features[index])])
label_values = ‘ ‘.join([str(x) for x in np.nditer(labels[index])])
output_file.write(‘features {} | labels {} \n’.format(feature_values, label_values))
MCTFファイルの作成-完全な実装例
import pandas as pd
import numpy as np
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
features = df_source.iloc[: , :4].values
labels = df_source[‘species’].values
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
labels = [one_hot(label_mapping[v], 3) for v in labels]
def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result
With open(‘iris.ctf’, ‘w’) as output_file:
for index in range(0, feature.shape[0]):
feature_values = ‘ ‘.join([str(x) for x in np.nditer(features[index])])
label_values = ‘ ‘.join([str(x) for x in np.nditer(labels[index])])
output_file.write(‘features {} | labels {} \n’.format(feature_values, label_values))
データの供給
- MinibatchSource、インスタンスを作成したら、それをトレーニングする必要があります。 小さなインメモリデータセットで作業したときと同じトレーニングロジックを使用できます。 ここでは、次のように、損失関数の学習メソッドの入力として *MinibatchSource インスタンスを使用します-
実装例
ステップ1 *-トレーニングセッションの出力をログに記録するには、まず次のように *cntk.logging モジュールからProgressPrinterをインポートします-
from cntk.logging import ProgressPrinter
ステップ2 *-次に、トレーニングセッションを設定するには、次のように *cntk.train モジュールから trainer および training_session をインポートします-
from cntk.train import Trainer,
ステップ3 *-ここで、 *minibatch_size 、 samples_per_epoch 、 num_epochs などの定数のセットを次のように定義する必要があります-
minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
- ステップ4 *-次に、トレーニング中にCNTKがデータを読み取る方法を知るために、ネットワークの入力変数とミニバッチソースのストリーム間のマッピングを定義する必要があります。
input_map = {
features: minibatch.source.streams.features,
labels: minibatch.source.streams.features
}
ステップ5 *-次に、トレーニングプロセスの出力をログに記録するには、次のように *progress_printer 変数を新しい ProgressPrinter インスタンスで初期化します-
progress_writer = ProgressPrinter(0)
- ステップ6 *-最後に、次のように損失に対してtrainメソッドを呼び出す必要があります-
train_history = loss.train(minibatch_source,
parameter_learners=[learner],
model_inputs_to_streams=input_map,
callbacks=[progress_writer],
epoch_size=samples_per_epoch,
max_epochs=num_epochs)
データの供給-完全な実装例
from cntk.logging import ProgressPrinter
from cntk.train import Trainer, training_session
minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
input_map = {
features: minibatch.source.streams.features,
labels: minibatch.source.streams.features
}
progress_writer = ProgressPrinter(0)
train_history = loss.train(minibatch_source,
parameter_learners=[learner],
model_inputs_to_streams=input_map,
callbacks=[progress_writer],
epoch_size=samples_per_epoch,
max_epochs=num_epochs)
出力
-------------------------------------------------------------------
average since average since examples
loss last metric last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.21 1.21 0 0 32
1.15 0.12 0 0 96
[………]