CNTK - 序列分类

  • 简述

    在本章中,我们将详细了解 CNTK 中的序列及其分类。
  • 张量

    CNTK 工作的概念是张量。基本上,CNTK 的输入、输出和参数被组织为张量,这通常被认为是一个广义矩阵。每个张量都有一个等级-
    • 秩为 0 的张量是一个标量。
    • 秩为 1 的张量是一个向量。
    • 秩为 2 的张量是矩阵。
    在这里,这些不同的维度被称为轴。
  • 静态轴和动态轴

    顾名思义,静态轴在网络的整个生命周期中具有相同的长度。另一方面,动态轴的长度可能因实例而异。事实上,在每个 minibatch 出现之前,它们的长度通常是未知的。
    动态轴类似于静态轴,因为它们还定义了张量中包含的有意义的数字分组。

    例子

    为了更清楚,让我们看看如何在 CNTK 中表示小批量的短视频剪辑。假设视频剪辑的分辨率都是 640 * 480。而且,剪辑也是彩色拍摄的,通常用三个通道编码。这进一步意味着我们的小批量具有以下内容 -
    • 长度分别为 640、480 和 3 的 3 个静态轴。
    • 两个动态轴;视频的长度和小批量轴。
    这意味着如果一个 minibatch 有 16 个视频,每个视频长 240 帧,则将表示为16*240*3*640*480张量。
  • 在 CNTK 中处理序列

    让我们通过首先了解长短期记忆网络来了解 CNTK 中的序列。

    长短期记忆网络 (LSTM)

    长短期记忆网络
    Hochreiter & Schmidhuber 介绍了长短期记忆 (LSTM) 网络。它解决了获得一个基本的循环层来长时间记住事物的问题。LSTM 的架构如上图所示。正如我们所看到的,它具有输入神经元、记忆细胞和输出神经元。为了解决梯度消失问题,长期短期记忆网络使用显式记忆单元(存储先前的值)和以下门 -
    • 忘记门- 顾名思义,它告诉记忆单元忘记以前的值。存储单元存储值直到门,即“忘记门”告诉它忘记它们。
    • 输入门- 顾名思义,它向单元格添加了新内容。
    • 输出门- 顾名思义,输出门决定何时将向量从单元传递到下一个隐藏状态。
    在 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
    
    
    上述程序的详细解释将在下一节中介绍,尤其是在我们构建递归神经网络时。