Phân loại có thể được định nghĩa là quá trình dự đoán nhãn đầu ra theo danh mục hoặc phản hồi cho dữ liệu đầu vào nhất định. Đầu ra được phân loại, dựa trên những gì mô hình đã học được trong giai đoạn huấn luyện, có thể có dạng như “Đen” hoặc “Trắng” hoặc “thư rác” hoặc “không có thư rác”.
Mặt khác, về mặt toán học, nhiệm vụ xấp xỉ một hàm ánh xạ chẳng hạn f từ các biến đầu vào chẳng hạn X đến các biến đầu ra nói Y.
Một ví dụ kinh điển về vấn đề phân loại có thể là việc phát hiện thư rác trong e-mail. Rõ ràng là chỉ có thể có hai loại đầu ra là “thư rác” và “không có thư rác”.
Để thực hiện phân loại như vậy, trước tiên chúng tôi cần đào tạo bộ phân loại trong đó “spam” và “không có thư rác” email sẽ được sử dụng làm dữ liệu đào tạo. Sau khi trình phân loại được đào tạo thành công, nó có thể được sử dụng để phát hiện một email không xác định.
Ở đây, chúng ta sẽ tạo 4-5-3 NN bằng cách sử dụng tập dữ liệu hoa iris có nội dung sau –
- Các nút 4 đầu vào (một nút cho mỗi giá trị dự đoán).
- 5 nút xử lý ẩn.
- Các nút 3 đầu ra (vì có ba loại có thể có trong bộ dữ liệu mống mắt).
Đang tải tập dữ liệu
Chúng tôi sẽ sử dụng tập dữ liệu về hoa diên vĩ, từ đó chúng tôi muốn phân loại các loài hoa diên vĩ dựa trên các đặc tính vật lý về chiều rộng và chiều dài đài hoa cũng như chiều rộng và chiều dài cánh hoa. Bộ dữ liệu mô tả các đặc tính vật lý của các loại hoa iris khác nhau –
- Chiều dài lá đài
- Chiều rộng vách ngăn
- Chiều dài cánh hoa
- Chiều rộng cánh hoa
- Lớp tức là iris setosa hoặc iris versicolor hoặc iris virginica
Chúng tôi có tệp iris.CSV mà chúng tôi cũng đã sử dụng trước đây trong các chương trước. Nó có thể được tải với sự trợ giúp của thư viện Pandas. Tuy nhiên, trước khi sử dụng hoặc tải nó cho bộ phân loại, chúng ta cần chuẩn bị các tệp huấn luyện và kiểm tra để có thể sử dụng dễ dàng với CNTK.
Chuẩn bị đào tạo & tập tin kiểm tra
Bộ dữ liệu Iris là một trong những bộ dữ liệu phổ biến nhất cho các dự án ML. Nó có 150 mục dữ liệu và dữ liệu thô trông như sau:
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
Như đã nói trước đó, bốn giá trị đầu tiên trên mỗi dòng mô tả các đặc tính vật lý của các giống khác nhau, tức là chiều dài lá đài, chiều rộng lá đài, chiều dài cánh hoa, chiều rộng cánh hoa của hoa diên vĩ. Tuy nhiên, chúng ta phải chuyển đổi dữ liệu ở định dạng mà CNTK có thể dễ dàng sử dụng và định dạng đó là tệp .ctf (chúng tôi cũng đã tạo một tệp iris.ctf trong phần trước). Nó sẽ trông giống như sau
|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
Trong dữ liệu trên, thẻ |attribs đánh dấu sự bắt đầu của giá trị đối tượng và |species gắn thẻ các giá trị nhãn lớp. Chúng tôi cũng có thể sử dụng bất kỳ tên thẻ nào khác theo mong muốn của mình, thậm chí chúng tôi cũng có thể thêm ID vật phẩm. Ví dụ: hãy xem dữ liệu sau
|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
Có tổng cộng 150 mục dữ liệu trong tập dữ liệu iris và trong ví dụ này, chúng tôi sẽ sử dụng quy tắc tập dữ liệu giữ lại 80-20, tức là 80% (120 mục) mục dữ liệu cho mục đích đào tạo và 20% (30 mục) mục dữ liệu còn lại để thử nghiệm mục đích.
Xây dựng mô hình phân loại
Trước tiên, chúng ta cần xử lý các tệp dữ liệu ở định dạng CNTK và để làm được điều đó, chúng ta sẽ sử dụng hàm trợ giúp có tên create_reader như sau
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
Bây giờ, chúng ta cần đặt các đối số kiến trúc cho NN của mình và cũng cung cấp vị trí của các tệp dữ liệu. Nó có thể được thực hiện với sự trợ giúp của mã python sau:
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)
Bây giờ, với sự trợ giúp của dòng mã sau, chương trình của chúng ta sẽ tạo NN chưa được huấn luyện
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)
Bây giờ, khi đã tạo mô hình kép chưa được huấn luyện, chúng ta cần thiết lập đối tượng thuật toán Người học và sau đó sử dụng nó để tạo đối tượng đào tạo Người huấn luyện. Chúng ta sẽ sử dụng trình học SGD và cross_entropy_with_softmax hàm mất mát
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])
Viết mã thuật toán học tập như sau
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])
Bây giờ, sau khi hoàn thành với đối tượng Trainer, chúng ta cần tạo hàm reader để đọc dữ liệu huấn luyện−
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 }
Bây giờ là lúc đào tạo mô hình NN của chúng tôi
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))
Khi chúng ta đã hoàn thành việc đào tạo, hãy đánh giá mô hình bằng cách sử dụng các mục dữ liệu thử nghiệm –
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)
Sau khi đánh giá tính chính xác của mô hình NN đã được đào tạo của chúng tôi, chúng tôi sẽ sử dụng nó để đưa ra dự đoán về dữ liệu chưa nhìn thấy
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])
Mô hình phân loại hoàn chỉnh
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()
đầu ra
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]
Lưu mô hình được đào tạo
Bộ dữ liệu Iris này chỉ có 150 mục dữ liệu, do đó sẽ chỉ mất vài giây để huấn luyện mô hình phân loại NN, nhưng việc đào tạo trên một tập dữ liệu lớn có hàng trăm hoặc hàng nghìn mục dữ liệu có thể mất hàng giờ hoặc thậm chí vài ngày.
Chúng ta có thể lưu mô hình của mình để không phải giữ lại mô hình đó từ đầu. Với sự trợ giúp của mã Python sau, chúng ta có thể lưu NN đã đào tạo của mình – nn_classifier = “.\\neuralclassifier.model” #provide the name of the filemodel.save(nn_classifier, format=C.ModelFormat.CNTKv2)
Sau đây là các đối số của hàm save() được sử dụng ở trên −
- Tên tệp là đối số đầu tiên của hàm save(). Nó cũng có thể được ghi cùng với đường dẫn của tệp.
- Một tham số khác là tham số format có giá trị mặc định C.ModelFormat.CNTKv2.
Đang tải mô hình được đào tạo
Sau khi bạn lưu mô hình đã đào tạo, bạn sẽ rất dễ dàng tải mô hình đó. Chúng ta chỉ cần sử dụng hàm load (). Hãy kiểm tra điều này trong ví dụ sau −
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])
Lợi ích của mô hình đã lưu là khi bạn tải mô hình đã lưu, bạn có thể sử dụng mô hình đó chính xác như thể mô hình vừa được đào tạo.
Xem thêm : Phân loại nhị phân mạng thần kinh nhân tạo