未验证 提交 a7c38367 编写于 作者: C chentianyu03 提交者: GitHub

Fix backward bug (#34582)

* fix backward bug

* format code style

* add test case for grad tensor accumulator
上级 54b6c390
......@@ -49,11 +49,17 @@ void BasicEngine::Init(
"the size of tensors is %s, but the size of grad_tensors is %s.",
tensors.size(), grad_tensors.size()));
PADDLE_ENFORCE_EQ(accumulators_.empty(), true,
platform::errors::AlreadyExists(
"Accumulators are not empty before preparing it for "
"backward network execution."));
for (size_t i = 0; i < tensors.size(); ++i) {
auto var = tensors[i];
auto grad_tensor = grad_tensors[i];
auto init_node = var->GradVarBase()->GradNode();
PADDLE_ENFORCE_EQ(
var->GradVarBase()->GraphIsFreed(), false,
platform::errors::Unavailable(
......@@ -101,6 +107,16 @@ void BasicEngine::Init(
*dev_ctx, grad_var);
}
VariableWrapper* init_grad_var = var->GradVarBase()->SharedVar().get();
auto& accumulator = accumulators_[init_grad_var];
if (!accumulator) {
if (FLAGS_sort_sum_gradient) {
accumulator.reset(new SortedGradientAccumulator(init_grad_var));
} else {
accumulator.reset(new EagerGradientAccumulator(init_grad_var));
}
}
init_nodes_.push_back(init_node);
}
}
......@@ -237,10 +253,6 @@ void BasicEngine::PrepareDeps() {
node_deps_.empty(), true,
platform::errors::AlreadyExists("Op deps are not empty before preparing "
"it for backward network execution."));
PADDLE_ENFORCE_EQ(accumulators_.empty(), true,
platform::errors::AlreadyExists(
"Accumulators are not empty before preparing it for "
"backward network execution."));
PADDLE_ENFORCE_EQ(accumulators_with_grad_node_.empty(), true,
platform::errors::AlreadyExists(
"Accumulators with grad_node as the key are not empty "
......@@ -311,8 +323,10 @@ void BasicEngine::Execute() {
// Start execute Computation graph
std::queue<std::shared_ptr<GradOpNode>> q;
for (size_t i = 0; i < init_nodes_.size(); ++i) {
if (node_deps_[init_nodes_[i].get()] == 0) {
q.push(std::move(init_nodes_[i]));
}
}
size_t op_num = 0;
......
......@@ -115,6 +115,31 @@ class TestBackwardAPI(unittest.TestCase):
self.assertTrue(np.allclose(x_grad, x_tensor.grad.numpy()))
def test_backward_accumulator_with_init_grad(self):
for dtype in self._dtypes:
x = np.random.random([10, ]).astype(dtype)
y_grad = np.random.random([10, ]).astype(dtype)
z_grad = np.random.random([10, ]).astype(dtype)
self._places = [paddle.CPUPlace()]
for place in self._places:
with dg.guard(place):
x_tensor = paddle.to_tensor(x, stop_gradient=False)
y_tensor = x_tensor**2
z_tensor = y_tensor**3
y_grad_tensor = paddle.to_tensor(y_grad)
z_grad_tensor = paddle.to_tensor(z_grad)
paddle.autograd.backward([y_tensor, z_tensor],
[y_grad_tensor, z_grad_tensor])
y = x**2
z = x**3
x_grad = 2 * x_tensor * (
y_grad_tensor + 3 * y_tensor * y_tensor * z_grad_tensor)
self.assertTrue(
np.allclose(x_grad.numpy(), x_tensor.grad.numpy()))
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册