CNTK - Phân loại trình tự
Trong chương này, chúng ta sẽ tìm hiểu chi tiết về các trình tự trong CNTK và cách phân loại của nó.
Hàng căng
Khái niệm mà CNTK hoạt động là tensor. Về cơ bản, đầu vào, đầu ra cũng như các tham số của CNTK được tổ chức nhưtensors, thường được coi là một ma trận tổng quát. Mỗi tensor có mộtrank -
Tensor của hạng 0 là một đại lượng vô hướng.
Độ căng của bậc 1 là một vectơ.
Tensor của hạng 2 là amatrix.
Ở đây, các kích thước khác nhau này được gọi là axes.
Trục tĩnh và trục động
Như tên của nó, các trục tĩnh có cùng độ dài trong suốt vòng đời của mạng. Mặt khác, độ dài của các trục động có thể thay đổi theo từng trường hợp. Trên thực tế, độ dài của chúng thường không được biết trước khi mỗi minibatch được giới thiệu.
Các trục động cũng giống như các trục tĩnh vì chúng cũng xác định một nhóm có ý nghĩa của các số chứa trong tensor.
Thí dụ
Để làm rõ hơn, hãy xem cách thể hiện một loạt video clip ngắn trong CNTK. Giả sử rằng độ phân giải của tất cả các video clip là 640 * 480. Và, các clip cũng được quay bằng màu thường được mã hóa bằng ba kênh. Hơn nữa, điều đó có nghĩa là minibatch của chúng tôi có những điều sau:
3 trục tĩnh có độ dài lần lượt là 640, 480 và 3.
Hai trục động lực học; thời lượng của video và trục minibatch.
Có nghĩa là nếu một minibatch có 16 video, mỗi video dài 240 khung hình, sẽ được biểu thị là 16*240*3*640*480 dây căng.
Làm việc với các chuỗi trong CNTK
Hãy để chúng tôi hiểu các trình tự trong CNTK bằng cách tìm hiểu đầu tiên về Mạng bộ nhớ dài hạn.
Mạng bộ nhớ dài hạn (LSTM)
Mạng bộ nhớ ngắn hạn (LSTM) được giới thiệu bởi Hochreiter & Schmidhuber. Nó giải quyết vấn đề nhận được một lớp lặp lại cơ bản để ghi nhớ mọi thứ trong một thời gian dài. Kiến trúc của LSTM được đưa ra ở trên trong sơ đồ. Như chúng ta có thể thấy, nó có các tế bào thần kinh đầu vào, các tế bào bộ nhớ và các tế bào thần kinh đầu ra. Để chống lại vấn đề độ dốc biến mất, các mạng bộ nhớ ngắn hạn sử dụng một ô nhớ rõ ràng (lưu trữ các giá trị trước đó) và các cổng sau:
Forget gate- Như tên của nó, nó báo cho ô nhớ quên các giá trị trước đó. Ô nhớ lưu trữ các giá trị cho đến khi cổng tức là 'cổng quên' yêu cầu nó quên chúng.
Input gate - Như tên của nó, nó thêm những thứ mới vào ô.
Output gate - Như tên của nó, cổng xuất quyết định thời điểm truyền các vectơ từ ô sang trạng thái ẩn tiếp theo.
Nó rất dễ dàng để làm việc với các trình tự trong CNTK. Hãy xem nó với sự trợ giúp của ví dụ sau:
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
Giải thích chi tiết của chương trình trên sẽ được đề cập trong các phần tiếp theo, đặc biệt là khi chúng ta sẽ xây dựng các mạng Neural tái diễn.