Ошибка подразумевает, что программа пытается распространиться через набор операций во второй раз.При первом обратном распространении набора операций Pytorch удаляет вычислительный граф для освобождения памяти.Поэтому при второй попытке обратного распространения произойдет сбой, поскольку график уже удален.
Вот подробное объяснение того же.
Краткий ответ
Используйте loss.backward(retain_graph=True)
.Это не приведет к удалению вычислительного графа.
Подробный ответ
В первой версии в каждой итерации цикла новый вычислительный граф генерируется каждый раз при запуске out = self(x)
.
Every loop's graph
out = self(x) -> loss = self.lossfn(out, y)
Во второй версии, поскольку out
объявлен вне цикла, у вычислительных графиков в каждом цикле есть родительский узел снаружи.
- out[i] = self(x) -> loss = self.lossfn(out[i], y)
out[i] - | - out[i] = self(x) -> loss = self.lossfn(out[i], y)
- out[i] = self(x) -> loss = self.lossfn(out[i], y)
Следовательно, вот временная шкалао том, что происходит.
- Первая итерация выполняется
- Граф вычислений удален, включая родительский узел
- Вторая итерация пытается выполнить обратное распространение, но не удалась, так как она ненайти родительский узел