Я загрузил набор букв EMNIST и преобразовал каждое изображение в объект torch.tensor
с формой torch.size([28, 28])
. Однако я хотел бы разделить изображение 28*28 на блоки 7*7, каждый из которых имеет размер 16.
И.Е. если пиксель изображения помечен слева направо, сверху вниз с помощью 1, 2, ..., 784
[
[1, 2, 3, ..., 28],
...
[ ..., 784]
]
Я ожидаю, что результатом будет объект torch.tensor
размера torch.size([7, 7, 16])
[
[
[1, 2, 3, 4, 29, 30, 31, 32, 57, 58, 59, 60, 85, 86, 87, 88],
...
[25, 26, 27, 28, 53, 54, 55, 56, 81, 82, 83, 84, 109, 110, 111, 112]
],
...
[
...
[697, 698, 699, 700, 725, 726, 727, 728, 753, 754, 755, 756, 781, 782, 783, 784]
]
]
Я пробовал использовать torch.view(7, 7, 16)
, но это не дало ожидаемого результата.
Спасибо большое ^_^
Родной Пайторх:
Используйте torch.nn.functional.unfold
. Это намного быстрее, при необходимости можно дифференцировать, и вы даже можете использовать перекрывающиеся участки. Вот пример:
x = torch.arange(1,28*28+1).view(28,28).float() # unfold only works with float tensor
x = x.unsqueeze(0).unsqueeze(0) # 2 unsqueeze to make `x` have dim 4 (BxCxHxW)
out = torch.nn.functional.unfold(x, kernel_size= 4, dilation= 1, padding= 0, stride= 4)
out.permute(0,2,1).shape # torch.Size([1, 49, 16])
Альтернатива:
Другой способ — использовать einops
, который более гибок, но потребует установки дополнительного пакета. И да, используйте einops
, если вы хотите работать с несколькими фреймворками: pytorch, numpy, tensorflow,...
from einops import rearrange
x = torch.arange(1,28*28+1).view(28,28)
out = rearrange(x, "(h t1) (w t2) -> h w (t1 t2)", t1 = 4, t2 = 4)
out.shape # torch.Size([7, 7, 16])
Альтернатива 2: Чтобы внести ясность, вы можете сделать это с помощью чистого тензорного оператора (нет необходимости в функциональном операторе) по любой причине:
x = torch.arange(1,28*28+1).view(28,28)
out = torch.stack(torch.split(torch.stack(torch.split(x,4, 0), -1), 4, 1), -2).view(16,49).permute(1,0)
# or
out = torch.stack(torch.split(torch.stack(torch.split(x,4, 1), -1), 4, 0), -1).view(16,49).permute(1,0)
out.shape # torch.Size([49, 16])
Да, «родной Pytorch» - это именно то, что я ищу, наконец out.transpose(1, 2).view(1, 7, 7, 16)
даст желаемый результат. Большое спасибо.
a = torch.tensor([[x + 1 for x in range(28 * y, 28 * (y + 1))] for y in range(28)])
c = a.split(4, dim=0)
torch.stack([torch.stack(d.split(4, dim=1)).view(7, 16) for d in c])
покажет желаемый результат, но есть ли способ быстрее?