【发布时间】:2017-12-07 06:20:11
【问题描述】:
我正在尝试将工作图像字幕 CNN-LSTM 网络从 TensorFlow 转换为 CNTK,并拥有我认为是经过正确训练的模型,但在弄清楚如何从最终训练的 CNTK 模型中提取预测时遇到了麻烦。
def create_lstm_model(image_features, text_features):
embedding_dim = 512
hidden_dim = 512
cell_dim = 512
vocab_dim = 77
image_embedding = Embedding(embedding_dim)
text_embedding = Embedding(embedding_dim)
lstm_classifier = Sequential([Stabilizer(),
Recurrence(LSTM(hidden_dim)),
Recurrence(LSTM(hidden_dim)),
Stabilizer(),
Dense(vocab_dim)])
embedded_images = BatchNormalization()(image_embedding(image_features))
embedded_text = text_embedding(text_features)
lstm_input = C.plus(embedded_images, embedded_text)
lstm_input = C.dropout(lstm_input, 0.5)
output = lstm_classifier(lstm_input)
return output
我以 CTF 格式提供我的数据,固定字幕序列大小为 40,使用以下结构:
def create_reader(path, is_training):
return MinibatchSource(CTFDeserializer(path, StreamDefs(
target_tokens = StreamDef(field='target_tokens', shape=vocab_len, is_sparse=True),
input_tokens = StreamDef(field='input_tokens', shape=vocab_len, is_sparse=True),
image_features = StreamDef(field='image_features', shape=image_features_dim, is_sparse=False)
)), randomize = is_training, max_sweeps = INFINITELY_REPEAT if is_training else 1)
除此之外:三个数据流的原因 - 我有一个输入图像特征向量(预训练的 ResNet 的最后一个 2048-dim 层)、一个输入文本标记序列和一个输出文本标记序列。所以基本上我的 CTF 文件,就序列而言,看起来像:
0 | target_token_0 | input_token_0 | input_image_feature_vector (2048-dim)
0 | target_token_1 | input_token_1 | empty array of 2048 zeros
0 | target_token_2 | input_token_2 | empty array of 2048 zeros
...
0 | target_token_40 | input_token_40 | empty array of 2048 zeros
1 | target_token_0 | input_token_0 | input_image_feature_vector (2048-dim)
1 | target_token_1 | input_token_1 | empty array of 2048 zeros
1 | target_token_2 | input_token_2 | empty array of 2048 zeros
...
1 | target_token_40 | input_token_40 | empty array of 2048 zeros
基本上,我不知道如何在 CNTK 中将两个序列切片和拼接在一起(即使您可以轻松拼接两个张量),所以我通过仅提供序列中的第一个元素来绕过它输入 2048-dim 图像特征向量,以及序列中的剩余元素,其中包含一个空的 2048-dim 零向量 - 设置用于:
C.plus(embedded_images, embedded_text)
在上面的模型中 - 目标本质上是采用 40 个[2048]->[512] 图像嵌入序列的第一个元素,并在最后 39 个元素之前 hack-splice(TM) 40 个[vocab_dim]->[512] 词嵌入的序列。我指望为空图像向量(2048 个零)学习相当空的[2048]->[512] 图像嵌入,所以我将我的嵌入图像序列和元素方式添加到我的嵌入文本序列中,然后再进入 LSTM .基本上是这样的:
image embedding sequence: [-1, 40, 512] (e.g., [-1, 0, 512])
text embedding sequence: [-1, 40, 512] (e.g., [-1, 1:40, 512)
+
---------------------------------------
lstm input sequence: [-1, 40, 512]
这让我想到了我的实际问题。现在我有一个训练得很好的模型,我想从模型中提取字幕预测,基本上是做这样的事情(来自PyTorch image captioning tutorial):
def sample(self, features, states=None):
"""Samples captions for given image features (Greedy search)."""
sampled_ids = []
inputs = features.unsqueeze(1)
for i in range(20): # maximum sampling length
hiddens, states = self.lstm(inputs, states) # (batch_size, 1, hidden_size),
outputs = self.linear(hiddens.squeeze(1)) # (batch_size, vocab_size)
predicted = outputs.max(1)[1]
sampled_ids.append(predicted)
inputs = self.embed(predicted)
inputs = inputs.unsqueeze(1) # (batch_size, 1, embed_size)
sampled_ids = torch.cat(sampled_ids, 1) # (batch_size, 20)
return sampled_ids.squeeze()
问题是,我无法找出 CNTK 等效项,用于从 LSTM 中获取隐藏状态并在下一个时间步将其抽回:
hiddens, states = self.lstm(inputs, states)
这在 CNTK 中是如何工作的?
【问题讨论】:
标签: cntk