1. Описание
Ниже я упомянул 5 наиболее часто используемых функций PyTorch с их небольшими примерами и возможным случаем, когда они не работают должным образом. Так что держись там. Давайте начнем!
二、torch.Tensor.numpy()
Интуитивно понятно, что эта функция используется для преобразования тензоров в многомерные массивы. [ Ссылка здесь ]
При определении Tensor с параметром require_grad, установленным в значение True, а затем при попытке преобразования в массив numpy PyTorch выдаст ошибку времени выполнения, как показано на рисунке 1 ниже.
Рисунок 1. Ошибка преобразования листового тензора в массив Numpy.
Это связано с тем, что PyTorch может конвертировать только тензоры в массивы Numpy, и это не будет частью каких-либо динамических вычислений в PyTorch. Тензор необходимо отделить от динамического графа с помощью detach , а затем преобразовать в массив numpy.
三、torch.Tensor.new_tensor()
Этот метод возвращает новый тензор в виде data
данных тензора. [ Ссылка здесь ]
При копировании нового тензора из существующего тензора с помощью метода .new_tensor() установка для require_grad значения «True» копирует только данные тензора, а не градиенты, связанные с исходным тензором.
Пожалуйста, обратитесь к следующему примеру:
# Create tensors.
x = torch.tensor(1., requires_grad=True )
w = torch.tensor(2., requires_grad=True)
b = torch.tensor(3., requires_grad=True)
print("x:",x)
print("w:",w)
print("b:",b)
y = w*x + b
print(y)
y.backward() #calculates the gradient of output w.r.t inputs
#gradients of outputs w.r.t inputs
print('dy/dx :',x.grad)
print('dy/dw :',w.grad)
print('dy/db :',b.grad)
a = x.new_tensor(x,requires_grad=True) #creating a copy of a tensor x
print(a.grad) #no grad of tensor x is copied to tensor a
Рисунок 2. Формирование новых тензоров без копирования градиентов.
При печати значения градиента, связанного с тензором a, None не печатается. Это связано с тем, что PyTorch связывает только градиенты тензоров Leaf, участвующих в графе динамических вычислений (например, тензоры x, w и b, используемые при вычислении тензора y на рисунке 2). Метод new_tensor только копирует данные тензора в новый тензор (например, тензор a).
四、torch.Tensor.view()
Этот метод возвращает новый тензор с теми же данными, но другой формы. [ Ссылка здесь ]
t1 = torch.randn(2,3)
print(t1)
print("is t1 contiguous??",t1.is_contiguous())
t1_ = t1.transpose(0,1)
print(t1_)
print("is t1_ contiguous??",t1_.is_contiguous())
print(t1_.view(-1))
tensor([[-1.5140, 0.7263, -0.7764],
[ 0.6795, 0.7041, 1.1364]])
is t1 contiguous?? True
tensor([[-1.5140, 0.6795],
[ 0.7263, 0.7041],
[-0.7764, 1.1364]])
is t1_ contiguous?? False
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-45-ac8f2ddf9c04> in <module>
5 print(t1_)
6 print("is t1_ contiguous??",t1_.is_contiguous())
----> 7 print(t1_.view(-1))
RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.
Этот метод не работает с несплошными тензорами. Дополнительную информацию о непрерывности тензора можно найти здесь.
Рисунок 3. Ошибка .view() на прерывистых тензорах
Из рисунка 3 очевидно, что .view() не может изменить форму прерывистого тензора t1_, поэтому можно использовать .view(). Переоборудован здесь для той же цели.
五、torch.Tensor.is_leaf
Согласно документации PyTorch версии 1.5.0, все тензоры с атрибутом require_grad, установленным в значение False , считаются листовыми тензорами. [ глянь сюда ]
t2 = torch.randn(2,2,requires_grad=True)+2
print(t2)
#As shown above, the tensor t2 is a random tensor with requires_grad set to True
#but is a result of an operation of adding 2 also.
#So, in this case it will not be a Leaf Tensor. Let's check!!
print(t2.is_leaf) #t2 is not a leaf Tensor as it is created by an operation with requires_grad = True
Тензор с атрибутом require_grad, установленным в значение True, считается листовым тензором, только если он создан пользователем и не является результатом операции.
Рисунок 4. Ошибка при создании листового тензора.
Как видно на рисунке 4, тензор t2 не является листовым тензором, поскольку он создается путем добавления двух к вновь определенному тензору, что нарушает рекомендации по определению листовых тензоров.
六、torch.Tensor.backward()
Эта функция отвечает за расчет градиента текущего тензора относительно листьев графа (leafensors) [см. здесь]
Этот метод требует только одномерного тензора или скаляра для вычисления листового вектора/градиента листа графа.
t1 = torch.randn(2,2,requires_grad=True)
t2 = torch.randn(2,2,requires_grad=True)
print(t1,t2)
#Above are 2 randomly defined tensors of dimensions 2x2 with requires_grad = True.
#Let's involve these variables in a linear computation and calculate the gradient
#of output y w.r.t these variables.
y = t1*t2
print(y)
print(y.shape)
y.backward()
tensor([[ 1.0389, -1.0465], [-1.0421, 0.7246]], require_grad=True) tensor([[0.1542, 1.4928], [0.0989, 0.2785]], require_grad=True) tensor([[ 0.1602, -1.5622 ], [-0.1031, 0.2018]], grad_fn=<MulBackward0>) torch.Size([2, 2])
Рисунок 5: Ошибка расчета градиента для неодномерных тензоров
RuntimeError Traceback (most recent call last)
<ipython-input-58-3a823b03f50a> in <module>
12 print(y.shape)
13
---> 14 y.backward()
~/anaconda3/envs/snowflakes/lib/python3.7/site-packages/torch/tensor.py in backward(self, gradient, retain_graph, create_graph)
193 products. Defaults to ``False``.
194 """
--> 195 torch.autograd.backward(self, gradient, retain_graph, create_graph)
196
197 def register_hook(self, hook):
~/anaconda3/envs/snowflakes/lib/python3.7/site-packages/torch/autograd/__init__.py in backward(tensors, grad_tensors, retain_graph, create_graph, grad_variables)
91 grad_tensors = list(grad_tensors)
92
---> 93 grad_tensors = _make_grads(tensors, grad_tensors)
94 if retain_graph is None:
95 retain_graph = create_graph
~/anaconda3/envs/snowflakes/lib/python3.7/site-packages/torch/autograd/__init__.py in _make_grads(outputs, grads)
32 if out.requires_grad:
33 if out.numel() != 1:
---> 34 raise RuntimeError("grad can be implicitly created only for scalar outputs")
35 new_grads.append(torch.ones_like(out, memory_format=torch.preserve_format))
36 else:
RuntimeError: grad can be implicitly created only for scalar outputs
На рисунке 5 мы можем видеть, что форма тензора y равна 2x2, поэтому градиент y относительно t1,t2 не может быть вычислен и приводит к ошибке времени выполнения. Итак, чтобы вычислить градиент, мы можем суммировать все элементы в тензоре y, а затем вычислить сумму градиентов относительно или обновить градиент каждого элемента в тензоре y, в зависимости от контекста и требований. Более подробное обсуждение на форуме PyTorch смотрите здесь .
Полный код смотрите здесь :
Тензорные функции Pytorch — Блокнот от Souptik (souptikmajumder) | Юпитер
Официальную документацию PyTorch для Torch.tensor можно найти здесь .
Эта статья является частью курса PyTorch Zero to GAN, организованного Jovian.ML и freecodecamp . Ссылка на регистрацию на курс здесь .
Спасибо за прочтение! Надеюсь, эта статья развеет некоторые сомнения относительно этих основных функций PyTorch.