Torch detach что это
Я пытаюсь лучше понять, почему.
В принятом ответе на только что связанный вопрос Блупон заявляет, что:
Вам необходимо преобразовать ваш тензор в другой тензор, который не требует градиента в дополнение к его фактическому определению значения.
В первом обсуждении, на которое он ссылается, albanD утверждает:
Это ожидаемое поведение, потому что переход к numpy сломает график, и поэтому градиент не будет вычисляться.
Во втором обсуждении, на которое он ссылается, апашке пишет:
Я изучил внутреннюю работу библиотеки автодифференциации PyTorch, и эти ответы меня все еще смущают. Почему он ломает график, чтобы перейти к numpy? Это потому, что любые операции с массивом numpy не будут отслеживаться в графе autodiff?
Что такое переменная? Как это связано с тензором?
Я считаю, что здесь требуется подробный и качественный ответ на Stack-Overflow, который объясняет причину этого для новых пользователей PyTorch, которые еще не понимают автодифференциацию.
В частности, я думаю, что было бы полезно проиллюстрировать график с помощью рисунка и показать, как происходит отключение в этом примере:
3 ответа
Я думаю, что наиболее важным моментом для понимания здесь является разница между torch.tensor и np.ndarray :
Хотя оба объекта используются для хранения n-мерных матриц (также известных как «тензоры»), <
Итак, если вас интересует только эффективный и простой способ выполнения математических операций с матрицами, np.ndarray или torch.tensor могут использоваться как взаимозаменяемые.
Однако torch.tensor предназначены для использования в контексте оптимизации градиентного спуска, и поэтому они содержат не только тензор с числовыми значениями, но (и, что более важно) вычислительный граф, приводящий к этим значениям. Затем этот вычислительный граф используется (с использованием цепного правила производных) для вычисления производной убытка. функция по каждой из независимых переменных, используемых для вычисления потерь.
Вычислительный график
Из вашего комментарии кажется, что это понятие немного расплывчатое. Попробую проиллюстрировать это простым примером.
Рассмотрим простую функцию двух (векторных) переменных, x и w :
Теперь мы можем проверить градиент z w.r.t w :
Обратите внимание, что это в точности равно
Каждый тензор на пути сохраняет свой «вклад» в вычисления:
Точно так же работает и другое направление:
Обратите внимание: если вы по какой-то причине хотите использовать pytorch только для математических операций без обратного распространения, вы можете использовать with torch.no_grad() диспетчер контекста, в этом случае вычислительные графы не создаются, а torch.tensor и np.ndarray могут использоваться взаимозаменяемо.
Значение первого элемента разделяется тензором и массивом numpy. Изменение его на 10 в тензоре изменило его и в массиве numpy.
Я спросил: Почему он ломает график, чтобы перейти к numpy? Это потому, что какие-либо операции с массивом numpy не будут отслеживаться в графе autodiff?
Написание my_tensor.detach().numpy() означает просто: «Я собираюсь выполнить несколько вычислений без отслеживания на основе значения этого тензора в массиве numpy».
Учебник «Погружение в глубокое обучение» (d2l) имеет хороший раздел, описывающий метод detach (), хотя здесь не говорится о том, почему отсоединение имеет смысл перед преобразованием в массив numpy.
Спасибо jodag за помощь в ответе на этот вопрос. По его словам, переменные устарели, поэтому мы можем проигнорировать этот комментарий.
Я думаю, что лучший ответ, который я могу найти до сих пор, находится в ссылке на документацию jodag:
И в замечаниях Албана, которые я цитировал в вопросе:
Другими словами, метод detach означает «Мне не нужны градиенты», и невозможно отслеживать градиенты с помощью операций numpy (в конце концов, для этого и нужны тензоры PyTorch!)
Разница между «detach()» и «с torch.nograd()» в PyTorch?
Я знаю о двух способах исключения элементов вычисления из вычисления градиента backward
Метод 1: Использование with torch.no_grad()
Есть ли разница между этими двумя? Есть ли преимущества/недостатки у того и другого?
2 ответа
tensor.detach() создает тензор, который совместно использует хранилище с тензором, не требующим градации. Он отсоединяет выходные данные от вычислительного графика. Таким образом, никакой градиент не будет распространяться обратно вдоль этой переменной.
Оболочка with torch.no_grad() временно установила для всех флагов requires_grad значение false. torch.no_grad говорит, что ни одна операция не должна строить график.
Однако torch.detach() просто отсоединяет переменную от графика вычисления градиента, как следует из названия. Но это используется, когда эта спецификация должна быть предоставлена для ограниченного числа переменных или функций, например. как правило, при отображении результатов потерь и точности после окончания эпохи обучения нейронной сети, потому что в этот момент она только потребляет ресурсы, так как ее градиент не будет иметь значения во время отображения результатов.
Похожие вопросы:
В чем функциональная разница между этими тремя методами jQuery : detach() hide() remove()
Я строю нейронные сети в Pytorch, я вижу, что view и view_as используются взаимозаменяемо в различных реализациях, в чем разница между ними?
Чтобы получить доступ к параметрам модели в pytorch, я видел два метода: использование state_dict и использование parameters() Интересно, в чем разница, или если одно-хорошая практика, а.
I’m trying to get a better understanding of why.
In the accepted answer to the question just linked, Blupon states that:
You need to convert your tensor to another tensor that isn’t requiring a gradient in addition to its actual value definition.
In the first discussion he links to, albanD states:
This is expected behavior because moving to numpy will break the graph and so no gradient will be computed.
In the second discussion he links to, apaszke writes:
I have studied the internal workings of PyTorch’s autodifferentiation library, and I’m still confused by these answers. Why does it break the graph to to move to numpy? Is it because any operations on the numpy array will not be tracked in the autodiff graph?
What is a Variable? How does it relate to a tensor?
I feel that a thorough high-quality Stack-Overflow answer that explains the reason for this to new users of PyTorch who don’t yet understand autodifferentiation is called for here.
In particular, I think it would be helpful to illustrate the graph through a figure and show how the disconnection occurs in this example:
3 Answers 3
So, if you are only interested in efficient and easy way to perform mathematical operations on matrices np.ndarray or torch.tensor can be used interchangeably.
However, torch.tensor s are designed to be used in the context of gradient descent optimization, and therefore they hold not only a tensor with numeric values, but (and more importantly) the computational graph leading to these values. This computational graph is then used (using the chain rule of derivatives) to compute the derivative of the loss function w.r.t each of the independent variables used to compute the loss.
As mentioned before, np.ndarray object does not have this extra «computational graph» layer and therefore, when converting a torch.tensor to np.ndarray you must explicitly remove the computational graph of the tensor using the detach() command.
Computational Graph
From your comments it seems like this concept is a bit vague. I’ll try and illustrate it with a simple example.
Consider a simple function of two (vector) variables, x and w :
We can now inspect the gradient of z w.r.t w :
Note that this is exactly equals to
Each tensor along the path stores its «contribution» to the computation:
These grad_fn are essential components to torch.tensors and without them one cannot compute derivatives of complicated functions. However, np.ndarray s do not have this capability at all and they do not have this information.
please see this answer for more information on tracing back the derivative using backwrd() function.
Since both np.ndarray and torch.tensor has a common «layer» storing an n-d array of numbers, pytorch uses the same storage to save memory:
numpy() → numpy.ndarray
Returns self tensor as a NumPy ndarray. This tensor and the returned ndarray share the same underlying storage. Changes to self tensor will be reflected in the ndarray and vice versa.
The other direction works in the same way as well:
Difference between «detach()» and «with torch.nograd()» in PyTorch?
I know about two ways to exclude elements of a computation from the gradient calculation backward
Method 1: using with torch.no_grad()
Is there a difference between these two? Are there benefits/downsides to either?
3 Answers 3
tensor.detach() creates a tensor that shares storage with tensor that does not require grad. It detaches the output from the computational graph. So no gradient will be backpropagated along this variable.
The wrapper with torch.no_grad() temporarily set all the requires_grad flag to false. torch.no_grad says that no operation should build the graph.
The difference is that one refers to only a given variable on which it is called. The other affects all operations taking place within the with statement. Also, torch.no_grad will use less memory because it knows from the beginning that no gradients are needed so it doesn’t need to keep intermediary results.
Learn more about the differences between these along with examples from here.
detach()
One example without detach() :
The end result in green r is a root of the AD computational graph and in blue is the leaf tensor.