Я запутался в методе view()
в следующем фрагменте кода.
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 6, 5)
self.pool = nn.MaxPool2d(2,2)
self.conv2 = nn.Conv2d(6, 16, 5)
self.fc1 = nn.Linear(16*5*5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.pool(F.relu(self.conv1(x)))
x = self.pool(F.relu(self.conv2(x)))
x = x.view(-1, 16*5*5)
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net()
Моя путаница касается следующей строки.
x = x.view(-1, 16*5*5)
Что делает tensor.view()
функция? Я видел его использование во многих местах, но я не могу понять, как он интерпретирует свои параметры.
Что произойдет, если я передам функции отрицательные значения view()
? Например, что произойдет , если я называю tensor_variable.view(1, 1, -1)
?
Кто-нибудь может объяснить основной принцип view()
функционирования на некоторых примерах?
reshape
в PyTorch ?!Давайте сделаем несколько примеров, от простого к сложному.
view
Метод возвращает тензор с теми же данными, что иself
тензор (что означает , что возвращаемый тензор имеет такое же число элементов), но с различной формой. Например:Предполагая, что
-1
это не один из параметров, при умножении их вместе результат должен быть равен количеству элементов в тензоре. Если вы сделаете:,a.view(3, 3)
это вызовет,RuntimeError
потому что форма (3 x 3) недопустима для ввода с 16 элементами. Другими словами: 3 х 3 не равно 16, но 9.Вы можете использовать в
-1
качестве одного из параметров, которые вы передаете в функцию, но только один раз. Все, что происходит, - это то, что метод сделает для вас математику о том, как заполнить это измерение. Напримерa.view(2, -1, 4)
эквивалентноa.view(2, 2, 4)
. [16 / (2 x 4) = 2]Обратите внимание, что возвращенный тензор имеет те же данные . Если вы вносите изменения в «представление», вы изменяете исходные данные тензора:
Теперь для более сложного варианта использования. В документации говорится, что каждое новое измерение представления должно быть либо подпространством исходного измерения, либо охватывать только d, d + 1, ..., d + k, которые удовлетворяют следующему условию смежности, которое для всех i = 0,. .., k - 1, шаг [i] = шаг [i + 1] x размер [i + 1] . В противном случае
contiguous()
необходимо вызвать, прежде чем можно будет просмотреть тензор. Например:Обратите внимание , что для
a_t
, походки [0]! = Шаг [1] х размера [1] , так как 24! = 2 х 3источник
torch.Tensor.view()
Проще говоря,
torch.Tensor.view()
что вдохновленоnumpy.ndarray.reshape()
илиnumpy.reshape()
создает новый взгляд на тензор, если новая форма совместима с формой исходного тензора.Давайте разберемся в этом подробно на конкретном примере.
С этим тензором
t
формы(18,)
новые виды могут быть созданы только для следующих фигур:(1, 18)
или , что эквивалентно(1, -1)
или или , что эквивалентно или или , что эквивалентно или или , что эквивалентно или или , что эквивалентно или или , что эквивалентно или(-1, 18)
(2, 9)
(2, -1)
(-1, 9)
(3, 6)
(3, -1)
(-1, 6)
(6, 3)
(6, -1)
(-1, 3)
(9, 2)
(9, -1)
(-1, 2)
(18, 1)
(18, -1)
(-1, 1)
Как мы уже можем наблюдать из приведенных выше кортежей формы, умножение элементов кортежа формы (например
2*9
,3*6
и т. Д.) Всегда должно быть равно общему количеству элементов в исходном тензоре (18
в нашем примере).Еще одна вещь, которую стоит заметить, это то, что мы использовали
-1
в одном из мест в каждом из кортежей формы. Используя a-1
, мы ленимся в выполнении вычислений сами, и скорее делегируем задачу PyTorch, чтобы выполнить вычисление этого значения для фигуры, когда она создает новое представление . Важно отметить, что мы можем использовать только один-1
кортеж формы. Остальные значения должны быть явно предоставлены нами. Остальное PyTorch будет жаловаться, бросаяRuntimeError
:Таким образом, со всеми вышеупомянутыми формами PyTorch всегда будет возвращать новый вид оригинального тензора
t
. Это в основном означает, что он просто изменяет информацию шага тензора для каждого из новых запрашиваемых представлений.Ниже приведены некоторые примеры, иллюстрирующие, как шаги тензоров изменяются с каждым новым представлением .
Теперь мы увидим шаги для новых взглядов :
Так что это магия
view()
функции. Это просто изменяет шаги (оригинального) тензора для каждого из новых представлений , пока форма нового представления совместима с исходной формой.Другая интересная вещь, которую можно наблюдать из кортежей шагов, состоит в том, что значение элемента в 0- й позиции равно значению элемента в 1- й позиции кортежа формы.
Это потому что:
шаг
(6, 1)
говорит, что для перехода от одного элемента к следующему элементу по 0- му измерению мы должны прыгнуть или сделать 6 шагов. (т.е. чтобы перейти от0
к6
, нужно сделать 6 шагов.) Но чтобы перейти от одного элемента к следующему элементу в 1- м измерении, нам нужен только один шаг (например, чтобы перейти от2
к3
).Таким образом, информация о шагах лежит в основе того, как элементы доступны из памяти для выполнения вычислений.
torch.reshape ()
Эта функция будет возвращать представление и будет точно такой же, как при использовании,
torch.Tensor.view()
если новая форма совместима с формой исходного тензора. В противном случае он вернет копию.Однако заметки
torch.reshape()
предупреждают, что:источник
Я выяснил, что
x.view(-1, 16 * 5 * 5)
это эквивалентно томуx.flatten(1)
, где параметр 1 указывает, что процесс сглаживания начинается с 1-го измерения (не сглаживания «выборочного» измерения). Как вы можете видеть, последнее использование семантически более понятно и проще в использовании, поэтому я предпочитаютflatten()
.источник
Вы можете прочитать
-1
как динамическое количество параметров или «что-нибудь». Из-за этого может быть только один параметр-1
вview()
.Если вы спросите,
x.view(-1,1)
это выведет тензорную форму в[anything, 1]
зависимости от количества элементов вx
. Например:Будет выводить:
источник
weights.reshape(a, b)
вернет новый тензор с теми же данными, что и веса с размером (a, b), так как он копирует данные в другую часть памяти.weights.resize_(a, b)
возвращает тот же тензор с другой формой. Однако, если новая форма приводит к меньшему количеству элементов, чем исходный тензор, некоторые элементы будут удалены из тензора (но не из памяти). Если новая форма дает больше элементов, чем исходный тензор, новые элементы будут неинициализированы в памяти.weights.view(a, b)
вернет новый тензор с теми же данными, что и веса с размером (a, b)источник
Попробуем разобраться в представлении на следующих примерах:
-1 в качестве значения аргумента - это простой способ вычислить значение, скажем, x, при условии, что мы знаем значения y, z или наоборот, в случае 3d, и для 2d снова простой способ вычислить значение, скажем, x при условии, что мы знать значения у или наоборот ..
источник
Мне очень понравились примеры @Jadiel de Armas.
Я хотел бы добавить небольшое понимание того, как элементы упорядочены для .view (...)
источник