CNTK - การจำแนกเครือข่ายประสาท

ในบทนี้เราจะศึกษาวิธีการจำแนกเครือข่ายประสาทเทียมโดยใช้ CNTK

บทนำ

การจำแนกประเภทอาจถูกกำหนดให้เป็นกระบวนการในการทำนายป้ายกำกับเอาต์พุตตามหมวดหมู่หรือการตอบสนองสำหรับข้อมูลอินพุตที่กำหนด ผลลัพธ์ที่จัดหมวดหมู่ซึ่งจะขึ้นอยู่กับสิ่งที่โมเดลได้เรียนรู้ในขั้นตอนการฝึกอบรมอาจมีรูปแบบเช่น "ดำ" หรือ "ขาว" หรือ "สแปม" หรือ "ไม่มีสแปม"

ในทางกลับกันในทางคณิตศาสตร์มันเป็นหน้าที่ของการประมาณฟังก์ชันการทำแผนที่พูด f จากตัวแปรอินพุตพูดว่า X ถึงตัวแปรเอาต์พุตบอกว่า Y

ตัวอย่างคลาสสิกของปัญหาการจัดประเภทอาจเป็นการตรวจจับสแปมในอีเมล เห็นได้ชัดว่าเอาต์พุตมีได้เพียง 2 ประเภทคือ "สแปม" และ "ไม่มีสแปม"

ในการใช้การจัดประเภทดังกล่าวก่อนอื่นเราต้องทำการฝึกอบรมตัวแยกประเภทซึ่งจะใช้อีเมล "สแปม" และ "ไม่มีสแปม" เป็นข้อมูลการฝึกอบรม เมื่อลักษณนามได้รับการฝึกฝนสำเร็จแล้วก็สามารถใช้ตรวจหาอีเมลที่ไม่รู้จักได้

ที่นี่เราจะสร้าง 4-5-3 NN โดยใช้ชุดข้อมูลดอกไอริสโดยมีดังต่อไปนี้ -

  • โหนดอินพุต 4 โหนด (หนึ่งโหนดสำหรับค่าตัวทำนายแต่ละค่า)

  • โหนดการประมวลผล 5 ซ่อน

  • โหนด 3 เอาต์พุต (เนื่องจากมีสามชนิดที่เป็นไปได้ในชุดข้อมูลไอริส)

กำลังโหลดชุดข้อมูล

เราจะใช้ชุดข้อมูลดอกไอริสซึ่งเราต้องการจำแนกชนิดของดอกไอริสตามคุณสมบัติทางกายภาพของความกว้างและความยาวกลีบเลี้ยงและความกว้างและความยาวของกลีบดอก ชุดข้อมูลอธิบายคุณสมบัติทางกายภาพของดอกไอริสพันธุ์ต่างๆ -

  • ความยาวกลีบเลี้ยง

  • ความกว้างของกลีบเลี้ยง

  • ความยาวกลีบดอก

  • ความกว้างของกลีบดอก

  • ระดับ ได้แก่ iris setosa หรือ iris versicolor หรือ iris 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

อย่างที่บอกไปก่อนหน้านี้ค่าสี่ค่าแรกในแต่ละบรรทัดอธิบายถึงคุณสมบัติทางกายภาพของพันธุ์ต่างๆ ได้แก่ ความยาวกลีบเลี้ยงความกว้างกลีบเลี้ยงความยาวกลีบดอกความกว้างกลีบดอกของดอกไอริส

แต่เราควรจะต้องแปลงข้อมูลในรูปแบบที่ 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 ของเราและระบุตำแหน่งของไฟล์ข้อมูลด้วย สามารถทำได้ด้วยความช่วยเหลือของรหัส 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)

ตอนนี้เมื่อเราสร้างโมเดลที่ไม่ได้รับการฝึกฝนมาแล้วเราจำเป็นต้องตั้งค่าอ็อบเจ็กต์อัลกอริทึมของผู้เรียนจากนั้นจึงใช้เพื่อสร้างอ็อบเจ็กต์การฝึกเทรนเนอร์ เราจะใช้ผู้เรียน 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 object แล้วเราจำเป็นต้องสร้างฟังก์ชัน reader เพื่ออ่านข้อมูลการฝึกอบรม

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])

ข้อดีของโมเดลที่บันทึกไว้คือเมื่อคุณโหลดโมเดลที่บันทึกไว้แล้วจะสามารถใช้งานได้เหมือนกับว่าโมเดลนั้นเพิ่งได้รับการฝึกฝนมา