【问题标题】:How to break numpy array into smaller chunks/batches, then iterate through them如何将numpy数组分解成更小的块/批次,然后遍历它们
【发布时间】:2017-01-30 01:31:07
【问题描述】:

假设我有这个 numpy 数组

[[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]]

我想把它分成两批然后迭代:

[[1, 2, 3],      Batch 1
[4, 5, 6]]

[[7, 8, 9],      Batch 2
[10, 11, 12]]

最简单的方法是什么?

编辑:我很抱歉我错过了这样的信息:一旦我打算继续迭代,由于拆分和迭代批次,原始数组将被破坏。批量迭代完成后,我需要从第一批重新开始,因此 我应该保持原始数组不会被破坏。整个想法是与需要批量迭代的随机梯度下降算法保持一致。在一个典型的例子中,我可以有一个 100000 次迭代 For 循环,只需要 1000 个批次,应该一次又一次地重放。

【问题讨论】:

  • 然后迭代?您的意思是您还想将第 1 批和第 2 批拆分成更小的批次吗?
  • @benten 是的,从原始数组中选择第一批,然后迭代到第二批。

标签: python pandas numpy


【解决方案1】:

这样做:

a = [[1, 2, 3],[4, 5, 6],
     [7, 8, 9],[10, 11, 12]]
b = a[0:2]
c = a[2:4]

【讨论】:

    【解决方案2】:

    考虑数组a

    a = np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9],
                  [10, 11, 12]])
    

    选项 1
    使用reshape//

    a.reshape(a.shape[0] // 2, -1, a.shape[1])
    
    array([[[ 1,  2,  3],
            [ 4,  5,  6]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])
    

    选项 2
    如果你想要两组而不是两组

    a.reshape(-1, 2, a.shape[1])
    
    array([[[ 1,  2,  3],
            [ 4,  5,  6]],
    
           [[ 7,  8,  9],
            [10, 11, 12]]])
    

    选项 3
    使用生成器

    def get_every_n(a, n=2):
        for i in range(a.shape[0] // n):
            yield a[n*i:n*(i+1)]
    
    for sa in get_every_n(a, n=2):
        print sa
    
    [[1 2 3]
     [4 5 6]]
    [[ 7  8  9]
     [10 11 12]]
    

    【讨论】:

      【解决方案3】:

      您可以使用numpy.split 沿第一轴拆分n 次,其中n 是所需批次的数量。因此,实现看起来像这样 -

      np.split(arr,n,axis=0) # n is number of batches
      

      因为axis 的默认值是0 本身,所以我们可以跳过设置它。所以,我们只需 -

      np.split(arr,n)
      

      示例运行 -

      In [132]: arr  # Input array of shape (10,3)
      Out[132]: 
      array([[170,  52, 204],
             [114, 235, 191],
             [ 63, 145, 171],
             [ 16,  97, 173],
             [197,  36, 246],
             [218,  75,  68],
             [223, 198,  84],
             [206, 211, 151],
             [187, 132,  18],
             [121, 212, 140]])
      
      In [133]: np.split(arr,2) # Split into 2 batches
      Out[133]: 
      [array([[170,  52, 204],
              [114, 235, 191],
              [ 63, 145, 171],
              [ 16,  97, 173],
              [197,  36, 246]]), array([[218,  75,  68],
              [223, 198,  84],
              [206, 211, 151],
              [187, 132,  18],
              [121, 212, 140]])]
      
      In [134]: np.split(arr,5) # Split into 5 batches
      Out[134]: 
      [array([[170,  52, 204],
              [114, 235, 191]]), array([[ 63, 145, 171],
              [ 16,  97, 173]]), array([[197,  36, 246],
              [218,  75,  68]]), array([[223, 198,  84],
              [206, 211, 151]]), array([[187, 132,  18],
              [121, 212, 140]])]
      

      【讨论】:

      • 非常感谢您的回答。我真的很喜欢拆分的想法,但是我忘了提到我需要保留原始数组以保持完整并且不会被批处理破坏。我用这些细节更新了我的问题。不管怎样,我会着手处理你的建议,并让你知道结果。
      • @Leb_Broth 原来的数组没有被破坏。因此,如果您这样做:out = np.split(arr,n),我们将在列表outarr 中保留一个数组等批次的列表不变。这是否澄清了您的担忧?
      • 啊,是的,对不起,你完全正确。我忘记了。我可以在第一个“while 迭代
      • 有没有为分割数组预先分配内存然后填充它们?而不是两个数组,比如 4。
      • @Merlin 如果内存是一个问题,我建议使用 reshape 方法,然后索引到第一个轴上的每个元素,以获得与这种拆分相同的效果。这是@ piRSquared 的另一个答案所达到的。
      【解决方案4】:

      这是我用来迭代的。我使用b.next() 方法生成索引,然后将输出传递给一个numpy 数组,例如a[b.next()] 其中a 是一个numpy 数组。

      class Batch():    
          def __init__(self, total, batch_size):
              self.total = total
              self.batch_size = batch_size
              self.current = 0
      
          def next(self):
              max_index = self.current + self.batch_size
              indices = [i if i < self.total else i - self.total 
                             for i in range(self.current, max_index)]
              self.current = max_index % self.total
              return indices 
      
      b = Batch(10, 3)
      print(b.next()) # [0, 1, 2]
      print(b.next()) # [3, 4, 5]
      print(b.next()) # [6, 7, 8]
      print(b.next()) # [9, 0, 1]
      print(b.next()) # [2, 3, 4]
      print(b.next()) # [5, 6, 7]
      

      【讨论】:

        【解决方案5】:

        为避免出现“数组拆分不等于除法”的错误,

        np.array_split(arr, n, axis=0)
        

        优于np.split(arr, n, axis=0)

        例如,

        a = np.array([[170,  52, 204],
                      [114, 235, 191],
                      [ 63, 145, 171],
                      [ 16,  97, 173]])
        

        然后

        print(np.array_split(a, 2))
        
        [array([[170,  52, 204],
               [114, 235, 191]]), array([[ 63, 145, 171],
               [ 16,  97, 173]])]
        
        print(np.array_split(a, 3))
        
        [array([[170,  52, 204],
               [114, 235, 191]]), array([[ 63, 145, 171]]), array([[ 16,  97, 173]])]
        

        但是,print(np.split(a, 3)) 会引发错误,因为4/3 不是整数。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-04-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-13
          • 1970-01-01
          相关资源
          最近更新 更多