CNTK-ニューラルネットワークの分類
この章では、CNTKを使用してニューラルネットワークを分類する方法について説明します。
前書き
分類は、特定の入力データのカテゴリ出力ラベルまたは応答を予測するプロセスとして定義できます。 分類された出力は、モデルがトレーニングフェーズで学習した内容に基づいて、「黒」、「白」、「スパム」、「スパムなし」などの形式になります。
一方、数学的には、入力変数Xから出力変数Yへのマッピング関数言う f を近似するタスクです。
分類の問題の典型的な例は、電子メールのスパム検出です。 「スパム」と「スパムなし」の2つの出力カテゴリしか存在できないことは明らかです。
そのような分類を実装するには、最初に「スパム」および「スパムなし」の電子メールがトレーニングデータとして使用される分類子のトレーニングを行う必要があります。 分類子のトレーニングが成功すると、未知のメールを検出するために使用できます。
ここでは、次のようなアイリスの花データセットを使用して4-5-3 NNを作成します-
- 4入力ノード(各予測値に1つ)。
- 5つの非表示の処理ノード。
- 3出力ノード(虹彩データセットには3つの可能な種があるため)。
データセットの読み込み
アイリスの花のデータセットを使用します。このデータセットから、はがきの幅と長さ、および花弁の幅と長さの物理的特性に基づいてアイリスの花の種を分類します。 データセットは、さまざまな種類のアイリスの花の物理的特性を記述しています-
- 分離長
- 分離幅
- 花びらの長さ
- 花びらの幅
- クラス、つまり アイリスセトサまたはアイリスバーシカラーまたはアイリスバージニカ
前の章で以前使用した iris.CSV ファイルもあります。 Pandas ライブラリを使用してロードできます。 ただし、それを使用したり、分類子にロードしたりする前に、トレーニングファイルとテストファイルを準備して、CNTKで簡単に使用できるようにする必要があります。
トレーニングとテストファイルの準備
アイリスデータセットは、MLプロジェクトで最も人気のあるデータセットの1つです。 それは150のデータ項目を持ち、生データは次のようになります-
先に述べたように、各行の最初の4つの値は、さまざまな品種の物理的特性を表しています。 アイリス花の花弁長、花弁幅、花弁長、花弁幅。
ただし、CNTKで簡単に使用できる形式でデータを変換する必要があります。その形式は.ctfファイルです(前のセクションでも1つのiris.ctfを作成しました)。 それは次のようになります-
上記のデータで、| attribsタグはフィーチャー値の開始をマークし、| speciesはクラスラベル値をタグ付けします。 アイテムIDを追加することもできますが、他の任意のタグ名を使用することもできます。 たとえば、次のデータを見てください-
アイリスデータセットには合計150のデータアイテムがあり、この例では、80〜20のホールドアウトデータセットルールを使用します。 トレーニング用に80%(120アイテム)のデータアイテム、テスト用に残りの20%(30アイテム)のデータアイテム。
分類モデルの構築
まず、データファイルをCNTK形式で処理する必要があります。そのために、次のように create_reader という名前のヘルパー関数を使用します-
次に、NNのアーキテクチャー引数を設定し、データファイルの場所を指定する必要があります。 それは次のpythonコードの助けを借りて行うことができます-
今、次のコードラインの助けを借りて、私たちのプログラムは訓練されていないNNを作成します-
次に、デュアルのトレーニングされていないモデルを作成したら、学習者アルゴリズムオブジェクトを設定し、それを使用してトレーナートレーニングオブジェクトを作成する必要があります。 SGDラーナーと cross_entropy_with_softmax 損失関数を使用します-
次のように学習アルゴリズムをコーディングします-
ここで、トレーナーオブジェクトを使い終わったら、トレーニングデータを読み取るリーダー関数を作成する必要があります。
それでは、NNモデルをトレーニングします。
トレーニングが終了したら、テストデータアイテムを使用してモデルを評価しましょう-
訓練されたNNモデルの精度を評価した後、目に見えないデータの予測を行うためにそれを使用します-
完全な分類モデル
Import numpy as np
Import cntk as C
def create_reader(path, input_dim, output_dim, rnd_order, sweeps):
x_strm = C.io.StreamDef(field='attribs', shape=input_dim, is_sparse=False)
y_strm = C.io.StreamDef(field='species', shape=output_dim, is_sparse=False)
streams = C.io.StreamDefs(x_src=x_strm, y_src=y_strm)
deserial = C.io.CTFDeserializer(path, streams)
mb_src = C.io.MinibatchSource(deserial, randomize=rnd_order, max_sweeps=sweeps)
return mb_src
def main():
print("Using CNTK version = " + str(C.__version__) + "\n")
input_dim = 4
hidden_dim = 5
output_dim = 3
train_file = ".\\...\\" #provide the name of the training file(120 data items)
test_file = ".\\...\\" #provide the name of the test file(30 data items)
X = C.ops.input_variable(input_dim, np.float32)
Y = C.ops.input_variable(output_dim, np.float32)
with C.layers.default_options(init=C.initializer.uniform(scale=0.01, seed=1)):
hLayer = C.layers.Dense(hidden_dim, activation=C.ops.tanh, name='hidLayer')(X)
oLayer = C.layers.Dense(output_dim, activation=None, name='outLayer')(hLayer)
nnet = oLayer
model = C.ops.softmax(nnet)
tr_loss = C.cross_entropy_with_softmax(nnet, Y)
tr_clas = C.classification_error(nnet, Y)
max_iter = 2000
batch_size = 10
learn_rate = 0.01
learner = C.sgd(nnet.parameters, learn_rate)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])
max_iter = 2000
batch_size = 10
lr_schedule = C.learning_parameter_schedule_per_sample([(1000, 0.05), (1, 0.01)])
mom_sch = C.momentum_schedule([(100, 0.99), (0, 0.95)], batch_size)
learner = C.fsadagrad(nnet.parameters, lr=lr_schedule, momentum=mom_sch)
trainer = C.Trainer(nnet, (tr_loss, tr_clas), [learner])
rdr = create_reader(train_file, input_dim, output_dim, rnd_order=True, sweeps=C.io.INFINITELY_REPEAT)
iris_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
for i in range(0, max_iter):
curr_batch = rdr.next_minibatch(batch_size, input_map=iris_input_map) trainer.train_minibatch(curr_batch)
if i % 500 == 0:
mcee = trainer.previous_minibatch_loss_average
macc = (1.0 - trainer.previous_minibatch_evaluation_average) *100
print("batch %4d: mean loss = %0.4f, accuracy = %0.2f%% " \ % (i, mcee, macc))
print("\nEvaluating test data \n")
rdr = create_reader(test_file, input_dim, output_dim, rnd_order=False, sweeps=1)
iris_input_map = { X : rdr.streams.x_src, Y : rdr.streams.y_src }
num_test = 30
all_test = rdr.next_minibatch(num_test, input_map=iris_input_map) acc = (1.0 - trainer.test_minibatch(all_test))* 100
print("Classification accuracy = %0.2f%%" % acc)
np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[dtype=np.float32)
print("\nPredicting species for input features: ")
print(unknown[0])
pred_prob = model.eval(unknown)
np.set_printoptions(precision = 4, suppress=True)
print("Prediction probabilities: ")
print(pred_prob[0])
if __name__== ”__main__”:
main()
出力
トレーニング済みモデルを保存する
このアイリスデータセットには150のデータアイテムしかないため、NN分類子モデルをトレーニングするのに数秒しかかかりませんが、数百または数千のデータアイテムを含む大規模なデータセットのトレーニングには数時間または数日かかる場合があります。
モデルを保存できるので、モデルを最初から保持する必要はありません。 次のPythonコードの助けを借りて、訓練されたNNを保存できます-
以下は上記で使用された* save()*関数の引数です-
- ファイル名は* save()*関数の最初の引数です。 ファイルのパスとともに書き込むこともできます。
- 別のパラメーターは format パラメーターで、デフォルト値は C.ModelFormat.CNTKv2 です。
トレーニング済みモデルの読み込み
トレーニング済みモデルを保存すると、そのモデルを非常に簡単にロードできます。 * load()*関数のみを使用する必要があります。 これを次の例で確認してみましょう-
保存されたモデルの利点は、保存されたモデルをロードすると、モデルがトレーニングされたばかりのように使用できることです。