Plate as iterator in minipyro?

I’ve been reading through minipyro since it seemed recommended as a gentler introduction to the inner workings of pyro than actually reading pyro’s source.

plate is defined like this:

class PlateMessenger(Messenger):
    def __init__(self, fn, size, dim):
        assert dim < 0
        self.size = size
        self.dim = dim
        super(PlateMessenger, self).__init__(fn)

    def process_message(self, msg):
        if msg["type"] == "sample":
            batch_shape = msg["fn"].batch_shape
            if len(batch_shape) < -self.dim or batch_shape[self.dim] != self.size:
                batch_shape = [1] * (-self.dim - len(batch_shape)) + list(batch_shape)
                batch_shape[self.dim] = self.size
                msg["fn"] = msg["fn"].expand(torch.Size(batch_shape))

    def __iter__(self):
        return range(self.size)

...
# boilerplate to match the syntax of actual pyro.plate:
def plate(name, size, dim=None):
    if dim is None:
        raise NotImplementedError("minipyro.plate requires a dim arg")
    return PlateMessenger(fn=None, size=size, dim=dim)

When I try to use it as an iterator like this:

for i in plate('hi', 5, dim=-1):
    print(i)

I get this:

TypeError: iter() returned non-iterator of type 'range'

Am I confused about something? Is this just an oversight? Is plate not meant to work as an iterator in minipyro?

Maybe it should have been this?:

    def __iter__(self):
        yield from range(self.size)
1 Like

Is this just an oversight? Is plate not meant to work as an iterator in minipyro?

Yes, this is an oversight, thanks for catching it. plate isn’t meant to work as an iterator in minipyro, hence the NotImplementedError in the definition def plate(...) in your snippet. PlateMessenger.__iter__ should probably raise a ValueError if self.dim != None.

Note that the implementation of plate in minipyro only affects distribution shapes and hence should have no effect when used as an iterator, whereas in the full version of Pyro plate also conveys information about conditional independence and subsampling.

Thanks!

PlateMessenger.__iter__ should probably raise a ValueError if self.dim != None .

(Non-mini) pyro already appropriately raises that exception.

Since minipyro’s plate requires a dim, probably minipyro’s PlateMessenger.__iter__ should raise NotImplemented? Either that or allow dim=None and implement __iter__ as yield from range(self.size) (and maybe issue a warning about having no effect).

If that sounds right I’d be happy to post a PR for one of those options.

Note that the implementation of plate in minipyro only affects distribution shapes and hence should have no effect when used as an iterator, whereas in the full version of Pyro plate also conveys information about conditional independence and subsampling.

Thanks – I hadn’t quite picked up on that difference.