美文网首页
_pack_padded_sequence_backward

_pack_padded_sequence_backward

作者: 潘旭 | 来源:发表于2020-08-10 19:35 被阅读0次
Tensor _pack_padded_sequence_backward(const Tensor& grad, at::IntArrayRef input_size, const Tensor& _batch_sizes, bool batch_first) {
  // 这个函数是在反向传播使用的,计算梯度
  // 是将 pack 后的 [梯度], 恢复成 pack 之前的 [梯度矩阵]
  std::vector<int64_t> input_size_after_t = input_size.vec();  // 输入的 input_size

  if (batch_first) {  // batch_first is True; batch_first is False;
    TORCH_CHECK(input_size.size() >= 2);
    std::swap(input_size_after_t[0], input_size_after_t[1]);
  }

  auto grad_input = at::zeros(input_size_after_t, grad.options());  // 梯度矩阵, 初始化为0

  auto batch_sizes_t = _batch_sizes.contiguous();  // batch_size存放的是每一列非0长度 具体示意图看 我的文章中的 pack 那部分的 batch_size 示意图。

  checkLongTensor(batch_sizes_t);

  int64_t offset = 0;
  int64_t max_seq_len = batch_sizes_t.size(0);  // 获取最大长度
  int64_t * batch_sizes = batch_sizes_t.data_ptr<int64_t>();
  for (int64_t i = 0; i < max_seq_len; ++i) {  // 循环所有sequence 长度
    
    // 填充梯度, grad 是pack 后的梯度, 
    // grad.slice(0, offset, offset + batch_sizes[i]): 就是获取pack 中的所有梯度, 0是第0维, 从 offset 到 offset + batch_sizes[i]
    // 会被提取出来。 batch_sizes[i] 就是 pack 后的 第i个位置上,所有非 0 元素的长度。具体示意图看 我的文章中的 pack 那部分的 batch_size 示意图。
    // 所以 grad_input 的计算结果就是 在非0的地方,用 pack 后的 梯度填充,而原先是 0 的的地方,依然是0, 因为 使用 zeros 初始化的。
    grad_input[i].slice(0, 0, batch_sizes[i]).copy_(grad.slice(0, offset, offset + batch_sizes[i]));
    
    // offset偏移到 下一个 
    offset += batch_sizes[i];
  }

  if (batch_first) {
    grad_input = grad_input.transpose(0, 1);
  }

  return grad_input;
}

网友评论

      本文标题:_pack_padded_sequence_backward

      本文链接:https://www.haomeiwen.com/subject/pcxsdktx.html