CNTK-シーケンス分類
この章では、CNTKのシーケンスとその分類について詳しく学習します。
テンソル
CNTKが機能するコンセプトは tensor です。 基本的に、CNTKの入力、出力、およびパラメーターは*テンソル*として編成されます。これは、一般化された行列と考えられることがよくあります。 すべてのテンソルには*ランク*があります-
- ランク0のテンソルはスカラーです。
- ランク1のテンソルはベクトルです。
- ランク2のテンソルは行列です。
ここでは、これらの異なる寸法を*軸*と呼びます。
静的軸と動的軸
名前が示すように、静的軸はネットワークの寿命を通じて同じ長さです。 一方、動的軸の長さはインスタンスごとに異なります。 実際、各ミニバッチが表示されるまで、それらの長さは通常はわかりません。
動的軸は、テンソルに含まれる数値の意味のあるグループ化も定義するため、静的軸に似ています。
例
より明確にするために、短いビデオクリップのミニバッチがCNTKでどのように表されるかを見てみましょう。 ビデオクリップの解像度がすべて640 * 480であるとします。 また、クリップはカラーで撮影され、通常3つのチャネルでエンコードされます。 それは、私たちのミニバッチが次のことを意味します-
- 長さがそれぞれ640、480、3の3つの静的軸。
- 2つの動的軸。ビデオの長さとミニバッチ軸。
つまり、ミニバッチがそれぞれ240フレームの長さの16ビデオを持っている場合、 _ 16 240 3 640 480_ テンソルとして表されます。
CNTKでのシーケンスの操作
まず、長期記憶ネットワークについて学び、CNTKのシーケンスを理解しましょう。
Long-Short Term Memory Network(LSTM)
Long-Short Term Memory Network
長期短期記憶(LSTM)ネットワークはHochreiter&Schmidhuberによって導入されました。 これは、基本的なリカレントレイヤーに長い間覚えておくという問題を解決しました。 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)
上記のプログラムの詳細な説明は、特にリカレントニューラルネットワークを構築するときに、次のセクションで説明します。