CNTK - การจำแนกตามลำดับ

ในบทนี้เราจะเรียนรู้รายละเอียดเกี่ยวกับลำดับใน CNTK และการจัดหมวดหมู่

เทนเซอร์

แนวคิดที่ CNTK ทำงานคือ tensor. โดยทั่วไปอินพุต CNTK เอาต์พุตและพารามิเตอร์จะถูกจัดเรียงเป็นtensorsซึ่งมักคิดว่าเป็นเมทริกซ์ทั่วไป ทุกเทนเซอร์มีrank -

  • Tensor ของอันดับ 0 เป็นสเกลาร์

  • Tensor ของอันดับ 1 คือเวกเตอร์

  • Tensor ของอันดับ 2 คือ amatrix

ในที่นี้มิติต่างๆเหล่านี้เรียกว่า axes.

แกนคงที่และแกนไดนามิก

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

แกนไดนามิกเปรียบเสมือนแกนคงที่เนื่องจากยังกำหนดการจัดกลุ่มที่มีความหมายของตัวเลขที่มีอยู่ในเทนเซอร์

ตัวอย่าง

เพื่อให้ชัดเจนยิ่งขึ้นเรามาดูวิธีการแสดงคลิปวิดีโอสั้น ๆ ใน CNTK สมมติว่าความละเอียดของคลิปวิดีโอคือ 640 * 480 ทั้งหมดและคลิปจะถูกถ่ายด้วยสีซึ่งโดยทั่วไปจะเข้ารหัสด้วยสามช่องสัญญาณ นอกจากนี้ยังหมายความว่ามินิแบทช์ของเรามีดังต่อไปนี้ -

  • 3 แกนคงที่ยาว 640, 480 และ 3 ตามลำดับ

  • แกนไดนามิกสองแกน ความยาวของวิดีโอและแกนมินิแบทช์

หมายความว่าหากมินิแบทช์มีวิดีโอ 16 รายการซึ่งแต่ละรายการมีความยาว 240 เฟรมจะแสดงเป็น 16*240*3*640*480 เทนเซอร์

การทำงานกับลำดับใน CNTK

ให้เราเข้าใจลำดับใน CNTK โดยการเรียนรู้เกี่ยวกับ Long-Short Term Memory Network ก่อน

เครือข่ายหน่วยความจำระยะยาว (LSTM)

Hochreiter & Schmidhuber เครือข่ายหน่วยความจำระยะยาว (LSTM) มันแก้ปัญหาในการรับเลเยอร์ซ้ำขั้นพื้นฐานเพื่อจดจำสิ่งต่างๆเป็นเวลานาน สถาปัตยกรรมของ LSTM แสดงไว้ด้านบนในแผนภาพ อย่างที่เราเห็นว่ามันมีเซลล์ประสาทอินพุตเซลล์ความจำและเซลล์ประสาทเอาท์พุต เพื่อต่อสู้กับปัญหาการไล่ระดับสีที่หายไปเครือข่ายหน่วยความจำระยะยาวจะใช้เซลล์หน่วยความจำที่ชัดเจน (เก็บค่าก่อนหน้านี้) และประตูต่อไปนี้ -

  • Forget gate- ตามความหมายของชื่อจะบอกให้เซลล์หน่วยความจำลืมค่าก่อนหน้านี้ เซลล์หน่วยความจำจะเก็บค่าไว้จนกว่าเกตคือ 'forget gate' จะบอกให้ลืม

  • Input gate - ตามความหมายของชื่อมันจะเพิ่มสิ่งใหม่ ๆ ให้กับเซลล์

  • Output gate - ตามความหมายของชื่อประตูเอาต์พุตจะตัดสินใจว่าเมื่อใดที่จะส่งต่อเวกเตอร์จากเซลล์ไปยังสถานะที่ซ่อนอยู่ถัดไป

มันง่ายมากที่จะทำงานกับลำดับใน CNTK มาดูกันด้วยความช่วยเหลือของตัวอย่างต่อไปนี้ -

import sys
import os
from cntk import Trainer, Axis
from cntk.io import MinibatchSource, CTFDeserializer, StreamDef, StreamDefs,\
   INFINITELY_REPEAT
from cntk.learners import sgd, learning_parameter_schedule_per_sample
from cntk import input_variable, cross_entropy_with_softmax, \
   classification_error, sequence
from cntk.logging import ProgressPrinter
from cntk.layers import Sequential, Embedding, Recurrence, LSTM, Dense
def create_reader(path, is_training, input_dim, label_dim):
   return MinibatchSource(CTFDeserializer(path, StreamDefs(
      features=StreamDef(field='x', shape=input_dim, is_sparse=True),
      labels=StreamDef(field='y', shape=label_dim, is_sparse=False)
   )), randomize=is_training,
   max_sweeps=INFINITELY_REPEAT if is_training else 1)
def LSTM_sequence_classifier_net(input, num_output_classes, embedding_dim,
LSTM_dim, cell_dim):
   lstm_classifier = Sequential([Embedding(embedding_dim),
      Recurrence(LSTM(LSTM_dim, cell_dim)),
      sequence.last,
      Dense(num_output_classes)])
return lstm_classifier(input)
def train_sequence_classifier():
   input_dim = 2000
   cell_dim = 25
   hidden_dim = 25
   embedding_dim = 50
   num_output_classes = 5
   features = sequence.input_variable(shape=input_dim, is_sparse=True)
   label = input_variable(num_output_classes)
   classifier_output = LSTM_sequence_classifier_net(
   features, num_output_classes, embedding_dim, hidden_dim, cell_dim)
   ce = cross_entropy_with_softmax(classifier_output, label)
   pe =      classification_error(classifier_output, label)
   rel_path = ("../../../Tests/EndToEndTests/Text/" +
      "SequenceClassification/Data/Train.ctf")
   path = os.path.join(os.path.dirname(os.path.abspath(__file__)), rel_path)
   reader = create_reader(path, True, input_dim, num_output_classes)
input_map = {
   features: reader.streams.features,
   label: reader.streams.labels
}
lr_per_sample = learning_parameter_schedule_per_sample(0.0005)
progress_printer = ProgressPrinter(0)
trainer = Trainer(classifier_output, (ce, pe),
sgd(classifier_output.parameters, lr=lr_per_sample),progress_printer)
minibatch_size = 200
for i in range(255):
   mb = reader.next_minibatch(minibatch_size, input_map=input_map)
trainer.train_minibatch(mb)
   evaluation_average = float(trainer.previous_minibatch_evaluation_average)
   loss_average = float(trainer.previous_minibatch_loss_average)
return evaluation_average, loss_average
if __name__ == '__main__':
   error, _ = train_sequence_classifier()
   print(" error: %f" % error)
average  since  average  since  examples
loss     last   metric   last
------------------------------------------------------
1.61    1.61    0.886     0.886     44
1.61     1.6    0.714     0.629    133
 1.6    1.59     0.56     0.448    316
1.57    1.55    0.479      0.41    682
1.53     1.5    0.464     0.449   1379
1.46     1.4    0.453     0.441   2813
1.37    1.28     0.45     0.447   5679
 1.3    1.23    0.448     0.447  11365

error: 0.333333

คำอธิบายโดยละเอียดของโปรแกรมข้างต้นจะกล่าวถึงในส่วนถัดไปโดยเฉพาะอย่างยิ่งเมื่อเราจะสร้าง Recurrent Neural networks