【问题标题】:In a python iterator select other iterator based on conditions在 python 迭代器中,根据条件选择其他迭代器
【发布时间】:2020-08-19 22:33:49
【问题描述】:

在 python 中,我有一个迭代器返回固定范围[0, N] 中称为Sampler 的无限索引字符串。实际上我有一个列表,它们所做的只是返回[0, N_0], [N_0, N_1], ..., [N_{n-1}, N_n].范围内的索引

我现在要做的是首先根据它们的范围长度选择其中一个迭代器,所以我有一个 weights 列表 [N_0, N_1 - N_0, ...] 并选择其中一个:

    iterator_idx = random.choices(range(len(weights)), weights=weights/weights.sum())[0]

接下来,我要做的是创建一个迭代器,它随机选择一个迭代器并选择一批M 样本。

class BatchSampler:
    def __init__(self, M):
        self.M = M
        self.weights = [weight_list]

        self.samplers = [list_of_iterators]
        ]
        self._batch_samplers = [
            self.batch_sampler(sampler) for sampler in self.samplers
        ]

    def batch_sampler(self, sampler):
        batch = []
        for batch_idx in sampler:
            batch.append(batch_idx)
            if len(batch) == self.M:
                yield batch

        if len(batch) > 0:
            yield batch

    def __iter__(self):
        # First select one of the datasets.
        iterator_idx = random.choices(
            range(len(self.weights)), weights=self.weights / self.weights.sum()
        )[0]
        return self._batch_samplers[iterator_idx]

这个问题是iter() 似乎只被调用一次,所以只选择了第一次iterator_idx。显然这是错误的......解决这个问题的方法是什么?

当您在 pytorch 中有多个数据集,但您只想从其中一个数据集中抽取批次时,这是一种可能的情况。

【问题讨论】:

    标签: python iterator pytorch


    【解决方案1】:

    在我看来,您想定义自己的容器类型。
    我将尝试提供一些标准方法的示例
    (希望不会遗漏太多细节);
    您应该能够重用这些简单示例之一,
    进入你自己的班级。


    仅使用 __getitem__(支持索引和循环):

    object.__getitem__

    调用以实现 self[key] 的评估。

    
    class MyContainer:
      def __init__(self, sequence):
        self.elements = sequence  # Just something to work with.
      
      def __getitem__(self, key):
        # If we're delegating to sequences like built-in list, 
        # invalid indices are handled automatically by them 
        # (throwing IndexError, as per the documentation).
        return self.elements[key]
    
    t = (1, 2, 'a', 'b')
    c = MyContainer(t)
    elems = [e for e in c]
    assert elems == [1, 2, 'a', 'b']
    assert c[1:-1] == t[1:-1] == (2, 'a')
    
    

    使用迭代器协议:

    object.__iter__

    object.__iter__(self)
    当容器需要迭代器时调用此方法。此方法应返回一个新的迭代器对象,该对象可以迭代容器中的所有对象。对于映射,它应该遍历容器的键。
    迭代器对象也需要实现这个方法;他们必须自己返回。有关迭代器对象的更多信息,请参阅迭代器类型。

    Iterator Types

    容器.__iter__()
    返回一个迭代器对象。该对象需要支持下面描述的迭代器协议。

    迭代器对象本身需要支持以下两种方法,它们共同构成了迭代器协议:

    迭代器.__iter__()
    返回迭代器对象本身。这是允许容器和迭代器与 for 和 in 语句一起使用所必需的。

    迭代器.__next__()
    从容器中返回下一个项目。如果没有其他项目,则引发 StopIteration 异常。

    一旦迭代器的 __next__() 方法引发 StopIteration,它必须在后续调用中继续这样做。

    
    class MyContainer:
      class Iter:
        def __init__(self, container):
          self.cont = container
          self.pos = 0
          self.len = len(container.elements)
        
        def __iter__(self): return self
        def __next__(self):
          if self.pos == self.len: raise StopIteration
          curElem = self.cont.elements[self.pos]
          self.pos += 1
          return curElem
      
      def __init__(self, sequence):
        self.elements = sequence  # Just something to work with.
      
      def __iter__(self):
        return MyContainer.Iter(self)
    
    t = (1, 2, 'a', 'b')
    c = MyContainer(t)
    elems = [e for e in c]
    assert elems == [1, 2, 'a', 'b']
    
    

    使用生成器:

    Generator Types

    Python 的生成器提供了一种方便的方式来实现迭代器协议。如果容器对象的 iter() 方法被实现为生成器,它将自动返回一个迭代器对象(技术上是生成器对象),提供 iter() 和 next() 方法。

    generator

    返回生成器迭代器的函数。它看起来像一个普通函数,只是它包含用于生成一系列可在 for 循环中使用的值的 yield 表达式,或者可以使用 next() 函数一次检索一个值。
    通常指代生成器函数,但在某些情况下可能指代生成器迭代器。

    generator iterator

    由生成器函数创建的对象。

    6.2.9. Yield expressions

    在函数体中使用 yield 表达式会使该函数成为生成器

    
    class MyContainer:
      def __init__(self, sequence):
        self.elements = sequence  # Just something to work with.
      
      def __iter__(self):
        for e in self.elements: yield e
    
    t = (1, 2, 'a', 'b')
    c = MyContainer(t)
    elems = [e for e in c]
    assert elems == [1, 2, 'a', 'b']
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-09
      • 1970-01-01
      • 2011-03-24
      • 2014-02-22
      • 1970-01-01
      • 2015-04-03
      • 2014-07-19
      相关资源
      最近更新 更多