【问题标题】:Random Index from a Tensor (Sampling with Replacement from a Tensor)来自张量的随机索引(从张量替换采样)
【发布时间】:2019-09-17 12:23:53
【问题描述】:

我正在尝试操纵不同神经网络的各个权重,以查看它们的性能如何下降。作为这些实验的一部分,我需要从它们的权重张量中随机抽样,我将其理解为带放回抽样(在统计意义上)。然而,由于它是高维的,我一直被如何以公平的方式做到这一点难住了。以下是我考虑这个问题的方法和研究:

  • 这之前是通过选择一个随机层然后在该层中选择一个随机权重来实现的(忽略选择随机权重的实现)。由于层的大小不同,我们发现权重的采样不均匀。

  • 我考虑过如果我们按照张量的numpy.shape进行采样会发生什么;但是,我现在意识到这遇到了与上面相同的问题。

    考虑这样的 2 阶张量会发生什么:

    [[*, *, *],
     [*, *, *, *]]
    

    随机选择一行然后从该行中选择一个值会导致选择不公平。如果您能够断言这种情况永远不会发生,则此方法可能会起作用,但它远非通用解决方案。

    请注意,this possible duplicate 实际上是以这种方式实现的。

  • 我发现有人建议展平张量并使用numpy.random.choice 从一维数组中随机选择。这是一个简单的解决方案,除了我不知道如何将展平的张量反转回其原始形状。此外,扁平化数百万个权重的实现会有些缓慢。

  • 我发现有人在讨论tf.random.multinomialhere,但是我理解的不够多,不知道它是否适用。

  • 我遇到了this paper 关于resevoir sampling,但又一次超出了我的想象。

  • 我找到了专门讨论张量和采样技术的 another paper,但它甚至超出了我的想象。

  • 一位队友找到了this other paper,它谈到了从张量中随机抽样,但它仅适用于 3 级张量。


任何帮助理解如何做到这一点?我正在使用 Keras 在 Python 中工作,但我将采用它存在的任何形式的算法。提前谢谢你。

【问题讨论】:

    标签: python-3.x random keras tensor


    【解决方案1】:

    在我忘记记录我们得出的解决方案之前,我先谈谈我看到的两种不同的实现方法:

    1. 在张量的标量元素上使用total ordering。这有效地枚举了您的元素,即展平它们。但是,您可以在保持原始形状的同时执行此操作。考虑这个伪代码(类似 Python 的语法):

      def sample_tensor(tensor, chosen_index: int) -> Tuple[int]:
          """Maps a chosen random number to its index in the given tensor.
      
          Args:
              tensor: A ragged-array n-tensor.
              chosen_index: An integer in [0, num_scalar_elements_in_tensor).
          Returns:
              The index that accesses this element in the tensor.
      
          NOTE: Entirely untested, expect it to be fundamentally flawed.
          """
          remaining = chosen_index
          for (i, sub_list) in enumerate(tensor):
              if type(sub_list) is an iterable:
                  if |sub_list| > remaining:
                      remaining -= |sub_list|
                  else:
                      return i joined with sample_tensor(sub_list, remaining)
              else: 
                  if len(sub_list) <= remaining:
                      return tuple(remaining)
      

      首先,我知道这不是一个合理的算法。我们的想法是倒计时,直到您到达您的元素,并为索引记账。

      我们需要在这里做出关键假设。 1) 所有列表最终将只包含标量。 2) 直接结果是,如果列表包含列表,则假设它也不包含同一级别的标量。 (停下来说服自己(2)。)

      我们还需要在这里做一个重要的说明:我们无法测量任何给定列表中标量的数量,除非该列表是由标量均匀组成的。为了避免在每个点都测量这个大小,我上面的算法应该被重构为先下降,然后再减去。

      这个算法有一些后果:

      • 它是整个解决问题方式中最快的。如果你想写一个函数f: [0, total_elems) -&gt; Tuple[int],你必须知道张量总排序中前面标量元素的数量。这实际上绑定在Theta(l),其中l 是张量中列表的数量(因为我们可以在标量列表上调用len)。
      • 很慢。与对具有定义形状的更好张量进行采样相比,它太慢了

      这引出了一个问题:我们能做得更好吗?请参阅下一个解决方案。

    2. probability distributionnumpy.random.choice 结合使用。这里的想法是,如果我们提前知道标量的分布已经是什么样子,我们就可以在递减张量的每个级别上公平地采样。这里的难题是构建这个发行版。

      我不会为此编写伪代码,但会列出一些目标:

      • 只能调用一次来构建数据结构。
      • 该算法需要结合迭代和递归技术来分别 a) 为兄弟列表构建分布和 b) 为后代构建分布。
      • 算法需要将索引映射到对应于兄弟列表的概率分布(注意上面讨论的假设)。这确实需要知道任意子张量中的元素数量。
      • 在列表仅包含标量的较低级别,我们可以通过仅存储所述列表中元素的数量来简化(而不是存储从一维数组中随机选择标量的概率)。
      • 您可能需要 2-3 个函数:一个利用概率分布返回索引的函数,一个构建分布对象的函数,还可能一个仅计算元素以帮助构建分布的函数。

      这在O(n) 也更快,其中n 是张量的等级。我确信这是最快的算法,但我没有时间尝试证明它。

      您可以选择将分布存储为有序字典,将概率映射到另一个字典或一维数组中的元素数量。我认为这可能是最明智的结构。


    请注意,(2) 确实与 (1) 相同,但我们预先计算了有关张量密度的知识。

    我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2019-01-06
      • 1970-01-01
      • 1970-01-01
      • 2018-08-05
      • 1970-01-01
      • 2020-01-03
      • 1970-01-01
      • 1970-01-01
      • 2018-07-31
      相关资源
      最近更新 更多