CNTK-ニューラルネットワーク分類
この章では、CNTKを使用してニューラルネットワークを分類する方法を学習します。
前書き
分類は、特定の入力データのカテゴリ出力ラベルまたは応答を予測するプロセスとして定義できます。モデルがトレーニングフェーズで学習した内容に基づく分類された出力は、「黒」、「白」、「スパム」、「スパムなし」などの形式になります。
一方、数学的には、マッピング関数を近似するタスクです。 f 入力変数からXと言い、出力変数からYと言います。
分類問題の典型的な例は、電子メールでのスパム検出です。出力には「スパム」と「スパムなし」の2つのカテゴリしかないことは明らかです。
このような分類を実装するには、最初に、「スパム」および「スパムなし」の電子メールがトレーニングデータとして使用される分類器のトレーニングを行う必要があります。分類器が正常にトレーニングされると、未知の電子メールを検出するために使用できます。
ここでは、次のようなアイリスフラワーデータセットを使用して4-5-3NNを作成します。
4入力ノード(予測値ごとに1つ)。
5-隠された処理ノード。
3-出力ノード(アイリスデータセットには3つの可能な種があるため)。
データセットの読み込み
がく片の幅と長さ、花びらの幅と長さの物理的特性に基づいて、アイリスの花の種を分類するアイリスの花のデータセットを使用します。データセットは、さまざまな種類のアヤメの花の物理的特性を記述しています-
がく片の長さ
がく片の幅
花びらの長さ
花びらの幅
クラスすなわちアイリスsetosaまたはアイリスversicolorまたはアイリスvirginica
我々は持っています iris.CSV前の章でも使用したファイル。それはの助けを借りてロードすることができますPandas図書館。ただし、CNTKで簡単に使用できるように、使用または分類子にロードする前に、トレーニングファイルとテストファイルを準備する必要があります。
トレーニングとテストファイルの準備
アイリスデータセットは、MLプロジェクトで最も人気のあるデータセットの1つです。150のデータ項目があり、生データは次のようになります-
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
…
7.0 3.2 4.7 1.4 versicolor
6.4 3.2 4.5 1.5 versicolor
…
6.3 3.3 6.0 2.5 virginica
5.8 2.7 5.1 1.9 virginica
前に述べたように、各行の最初の4つの値は、さまざまな品種の物理的特性、つまり、がく片の長さ、がく片の幅、花びらの長さ、アイリスの花の花びらの幅を表します。
ただし、データをCNTKで簡単に使用できる形式に変換する必要があり、その形式は.ctfファイルです(前のセクションでも1つのiris.ctfを作成しました)。次のようになります-
|attribs 5.1 3.5 1.4 0.2|species 1 0 0
|attribs 4.9 3.0 1.4 0.2|species 1 0 0
…
|attribs 7.0 3.2 4.7 1.4|species 0 1 0
|attribs 6.4 3.2 4.5 1.5|species 0 1 0
…
|attribs 6.3 3.3 6.0 2.5|species 0 0 1
|attribs 5.8 2.7 5.1 1.9|species 0 0 1
上記のデータでは、| attribsタグが機能値の開始を示し、| speciesタグがクラスラベル値を示しています。アイテムIDを追加することもできますが、他の任意のタグ名を使用することもできます。たとえば、次のデータを見てください-
|ID 001 |attribs 5.1 3.5 1.4 0.2|species 1 0 0 |#setosa
|ID 002 |attribs 4.9 3.0 1.4 0.2|species 1 0 0 |#setosa
…
|ID 051 |attribs 7.0 3.2 4.7 1.4|species 0 1 0 |#versicolor
|ID 052 |attribs 6.4 3.2 4.5 1.5|species 0 1 0 |#versicolor
…
アイリスデータセットには合計150のデータ項目があり、この例では、80〜20のホールドアウトデータセットルールを使用します。つまり、トレーニング目的で80%(120項目)のデータ項目を使用し、テスト用に残りの20%(30項目)のデータ項目を使用します。目的。
分類モデルの構築
まず、CNTK形式のデータファイルを処理する必要があります。そのために、という名前のヘルパー関数を使用します。 create_reader 次のように-
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
次に、NNのアーキテクチャ引数を設定し、データファイルの場所も指定する必要があります。それは次のPythonコードの助けを借りて行うことができます-
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)
さて、次のコード行の助けを借りて、私たちのプログラムは訓練されていないNNを作成します-
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)
ここで、トレーニングされていないデュアルモデルを作成したら、Learnerアルゴリズムオブジェクトを設定し、それを使用してTrainerトレーニングオブジェクトを作成する必要があります。SGDラーナーを使用してcross_entropy_with_softmax 損失関数-
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])
さて、Trainerオブジェクトを使い終わったら、トレーニングデータを読み取るためのリーダー関数を作成する必要があります-
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 }
NNモデルをトレーニングする時が来ました-
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)
トレーニング済みのNNモデルの精度を評価した後、それを使用して、見えないデータの予測を行います。
np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[6.4, 3.2, 4.5, 1.5]], dtype=np.float32)
print("\nPredicting Iris species for input features: ")
print(unknown[0]) pred_prob = model.eval(unknown)
np.set_printoptions(precision = 4, suppress=True)
print("Prediction probabilities are: ")
print(pred_prob[0])
完全な分類モデル
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([[7.0, 3.2, 4.7, 1.4]], 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()
出力
Using CNTK version = 2.7
batch 0: mean loss = 1.0986, mean accuracy = 40.00%
batch 500: mean loss = 0.6677, mean accuracy = 80.00%
batch 1000: mean loss = 0.5332, mean accuracy = 70.00%
batch 1500: mean loss = 0.2408, mean accuracy = 100.00%
Evaluating test data
Classification accuracy = 94.58%
Predicting species for input features:
[7.0 3.2 4.7 1.4]
Prediction probabilities:
[0.0847 0.736 0.113]
トレーニング済みモデルの保存
このアイリスデータセットには150個のデータ項目しかないため、NN分類器モデルのトレーニングには数秒しかかかりませんが、数百または数千個のデータ項目を持つ大規模なデータセットのトレーニングには数時間または数日かかる場合があります。
モデルを保存して、最初から保持する必要がないようにすることができます。次のPythonコードの助けを借りて、トレーニング済みのNNを保存できます-
nn_classifier = “.\\neuralclassifier.model” #provide the name of the file
model.save(nn_classifier, format=C.ModelFormat.CNTKv2)
以下はの議論です save() 上記で使用した関数−
ファイル名はの最初の引数です save()関数。ファイルのパスと一緒に書き込むこともできます。
別のパラメータは format デフォルト値を持つパラメータ C.ModelFormat.CNTKv2。
トレーニング済みモデルの読み込み
トレーニング済みモデルを保存すると、そのモデルを簡単にロードできます。使用する必要があるのはload ()関数。次の例でこれを確認しましょう-
import numpy as np
import cntk as C
model = C.ops.functions.Function.load(“.\\neuralclassifier.model”)
np.set_printoptions(precision = 1, suppress=True)
unknown = np.array([[7.0, 3.2, 4.7, 1.4]], 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])
保存されたモデルの利点は、保存されたモデルをロードすると、モデルがトレーニングされたばかりの場合とまったく同じように使用できることです。