CNTK-신경망 분류

이 장에서는 CNTK를 사용하여 신경망을 분류하는 방법을 공부합니다.

소개

분류는 주어진 입력 데이터에 대한 범주 형 출력 레이블 또는 응답을 예측하는 프로세스로 정의 될 수 있습니다. 모델이 학습 단계에서 학습 한 내용을 기반으로하는 분류 된 출력은 "검은 색"또는 "흰색"또는 "스팸"또는 "스팸 없음"과 같은 형식을 가질 수 있습니다.

반면에 수학적으로는 매핑 함수를 근사화하는 작업입니다. f 입력 변수는 X를, 출력 변수는 Y를 말합니다.

분류 문제의 전형적인 예는 이메일의 스팸 탐지 일 수 있습니다. "스팸"과 "스팸 없음"이라는 두 가지 범주의 출력 만있을 수 있음이 분명합니다.

이러한 분류를 구현하려면 먼저 "스팸"및 "스팸 없음"이메일이 학습 데이터로 사용되는 분류기의 학습을 수행해야합니다. 분류 기가 성공적으로 학습되면 알 수없는 이메일을 감지하는 데 사용할 수 있습니다.

여기에서는 다음과 같은 홍채 꽃 데이터 세트를 사용하여 4-5-3 NN을 생성합니다.

  • 4 개 입력 노드 (각 예측 변수 값에 대해 하나씩).

  • 5 개의 숨겨진 처리 노드.

  • 3 개의 출력 노드 (홍채 데이터 세트에 세 가지 가능한 종이 있기 때문).

데이터 세트로드

꽃받침 너비와 길이, 꽃잎 너비와 길이의 물리적 특성을 기반으로 붓꽃의 종류를 분류하려는 붓꽃 데이터 세트를 사용할 것입니다. 데이터 세트는 다양한 종류의 붓꽃의 물리적 특성을 설명합니다.

  • 꽃받침 길이

  • 꽃받침 너비

  • 꽃잎 길이

  • 꽃잎 너비

  • 클래스 즉 홍채 세토 사 또는 홍채 versicolor 또는 홍채 virginica

우리는 iris.CSV이전 장에서 사용한 파일도 있습니다. 다음의 도움으로로드 할 수 있습니다.Pandas도서관. 하지만 사용하거나 분류기에로드하기 전에 CNTK에서 쉽게 사용할 수 있도록 교육 및 테스트 파일을 준비해야합니다.

교육 및 테스트 파일 준비

Iris 데이터 세트는 ML 프로젝트에서 가장 인기있는 데이터 세트 중 하나입니다. 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 파일입니다 (이전 섹션에서도 하나의 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에 대한 아키텍처 인수를 설정하고 데이터 파일의 위치도 제공해야합니다. 다음 파이썬 코드의 도움으로 할 수 있습니다-

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]

훈련 된 모델 저장

이 Iris 데이터 세트에는 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])

저장된 모델의 이점은 저장된 모델을로드하면 모델이 방금 학습 된 것처럼 정확히 사용할 수 있다는 것입니다.