来自张量的随机索引(使用张量进行替换抽样)

时间:2019-04-28 19:28:47

标签: python-3.x random keras tensor

我正在尝试操纵不同神经网络的权重,以查看其性能如何下降。作为这些实验的一部分,我需要从它们的重量张量中随机抽样,我已经理解为替换抽样(从统计意义上讲)。但是,由于它是高维度的,因此我对如何以公平的方式执行此操作感到困惑。这是我考虑此问题的方法和研究:

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

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

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

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

    随机选择一行,然后从该行中选择一个值将导致选择不公。如果您能够断言这种情况永远不会发生,但与一般解决方案相去甚远,则可以使用此方法。

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

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

  • 我发现有人在讨论tf.random.multinomial here,但是我对它的理解还不够,无法知道它是否适用。

  • 我遇到this paperresevoir sampling,但又一次超过了我。

  • 我发现another paper专门讨论了张量和采样技术,但它甚至超出了我的头脑。

  • 一个队友发现this other paper谈论从张量进行随机采样,但这仅适用于3级张量。


任何帮助您了解如何执行此操作的人吗?我正在与Keras一起使用Python进行工作,但是我将采用一种存在的任何形式的算法。预先谢谢你。

1 个答案:

答案 0 :(得分:0)

在我忘了记录我们得出的解决方案之前,我将讨论实现这一目标的两种不同途径:

  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) -> Tuple[int],则必须知道沿张量的总顺序的前标量元素的数量。这有效地绑定在Theta(l)上,其中l是张量中列表的数量(因为我们可以在标量列表上调用len)。
    • 这是。与采样具有确定形状的更好的张量相比,它太慢

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

  2. probability distributionnumpy.random.choice结合使用。这里的想法是,如果我们提前知道标量的分布已经是什么样,那么我们可以在降低张量的每个级别上公平地采样。这里的难题是建立这种分布。

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

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

    这在O(n)处也更快,其中n是张量的秩。我坚信这是最快的算法,但是我没有时间去证明它。

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


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

我希望这会有所帮助。