В вашем коде есть небольшая ошибка. Например, приведенный ниже код работает нормально:
In [107]: import torchvision
# sample input
In [108]: batch_tensor = torch.randn(*(10, 3, 256, 256))
# make grid (2 rows and 5 columns)
In [109]: grid_img = torchvision.utils.make_grid(batch_tensor, nrow=5)
# check shape
In [110]: grid_img.shape
Out[110]: torch.Size([3, 518, 1292])
# reshape and plot
In [111]: plt.imshow(grid_img.permute(1, 2, 0))
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
Out[111]:
, который показывает выход как:
Representable
- это функторы типа контейнеров, которые имеют «особые отношения» с другим типом, который служит индексом в Representable
. В определении Haskell этот тип индекса задается связанным семейством типов type Rep f :: *
Для каждого значения индекса и для каждого значения значения [113 ], мы можем вызвать функцию index :: f a -> Rep f -> a
, чтобы получить соответствующий элемент. И tabulate :: (Rep f -> a) -> f a
создает контейнер, в котором каждый элемент получен из своего собственного индекса.
Теперь, вот пример функтора, который НЕ представим: типичный тип списка Haskell []
. Можно наивно думать, что он может быть проиндексирован чем-то вроде Natural
, но проблема в том, что списки могут быть пустыми или не иметь достаточного количества элементов для достижения заданного индекса.
Всегда бесконечный тип, такой как data Stream a = Stream a (Stream a)
- это Representable
и он индексируется Natural
, потому что всегда будет значение для любого заданного Natural
, которое мы передадим в index
.
Аналогично, однородная пара data Pair a = Pair a a
индексируется по типу Bool
: индекс сообщает нам, какой из компонентов выбрать.
Если мы получим зависимую переменную, векторы фиксированного размера будут Representable
и проиндексированы конечными натуральными числами , ограниченными размером вектора. Они не индексируются неограниченными Natural
сами, потому что тогда у нас может быть доступ за пределы!
Чтение различных экземпляров, определенных для Representable
, поучительно, но, похоже, мы имеем перейти к исходному коду, потому что связанные типы не видны в пикше. Некоторые интересные особенности:
Функтор Identity
индексируется по типу блока ()
, это имеет смысл, потому что Identity
имеет, так сказать, только один «слот», поэтому мы не нужно предоставлять никакой информации.
Тип «функции из некоторого типа» ((->) e)
индексируется самим типом источника. И index
это просто id
. Это то, что подразумевается под «изоморфной монаде читателя», потому что монада Reader e
является просто новым типом над ((->) e)
.
Composition
(вложенность) двух представимых функторов снова Representable
, и они индексируются парой исходных индексов! Это имеет смысл: сначала мы должны знать, как индексировать во внешний функтор, а затем во внутренний.
Product
(спаривание) двух Representable
функторов индексируется суммой (Either
) исходных индексов. Ветвь Either
говорит нам, в какую часть продукта индексировать.
Заметное упущение (потому что это не так в общем случае): нет (Representable f, Representable g) => Representable (Sum f g)
экземпляра.