【问题标题】:Create a matrix of weight which sum to one efficiently创建一个权重矩阵,有效地求和为一
【发布时间】:2021-02-02 00:11:26
【问题描述】:

我正在创建一个线性组合生成器和测试器。目标是测试 N 个输入的所有线性组合,以确定哪个产生最佳分数。

可以通过强制方式创建权重矩阵,如下所示。但是,当应用程序可以有 2 个以上没有上限的模块时,这在应用程序中并不灵活。有没有办法泛化这段代码?

最好以矩阵形式输出这个输出,这样我就可以简单地将输入矩阵乘以一个标量来获得线性组合输出!

编辑:完全明确。我正在寻找一种灵活引用的方法

for i in range...: 
   for j in range...: 
       for k in range...

适用于 2、3、4、+ 模块

def generate_weights(n=4, min_weight=0, max_weight=100):
    weight_dictionary = {}
    combination = 1
    for i in range(0, 101):
        for j in range(0, 101):
            for k in range(0, 101):
                for l in range(0, 101):
                    # For now, ignoring conditions on each individual scalar's min and max weight criteria
                    if i + j + k + l == 100:
                        weight_dictionary[combination] = (i, j, k, l)
                        combination+=1
    return weight_dictionary

test = generate_weights()

【问题讨论】:

    标签: python arrays numpy iteration


    【解决方案1】:

    通常,处理未知深度的堆叠循环的最简单方法是使用递归。函数每次运行时都会运行一个循环,递归深度给出堆栈。

    import numpy as np
    
    def generate_weights0( layers = 4, tgt = 100 ):
        """ Generate list of lists with 'layers' items adding to tgt """
        result = []
    
        def one_layer( layers, tgt, cumul ):
            """  layers: layers still to produce.
                 tgt: the tgt still left to be consumed.
                 cumul: a list of the combinations for the layers already processed.
            """
            if layers == 1: # return results for the last layer
                cumul.append( tgt )
                result.append( cumul )
            else:
                # For each i call one_layer with revised parameters
                for i in range( tgt + 1 ):
                    cumul_ = cumul.copy()
                    cumul_.append( i )
                    # Recursive call with updated parameters
                    one_layer( layers - 1, tgt - i, cumul_ )
    
        one_layer( layers, tgt, [] )  # Execute the initialised function
        return np.array( result )
    

    Above 返回假设 min 为零的结果。为避免复杂性,有第二个函数调用上述函数,已将参数调整为最小值。然后它将最小值添加到所有结果中。

    def generate_weights( layers = 4, min_ = 0, tgt = 100 ):
        tgt = tgt - ( layers * min_ )
        return generate_weights0( layers, tgt ) + min_
    

    我认为这会返回您想要的。

    【讨论】:

    • 谢谢,这正是我想要的。如果您有任何关于递归的建议资源以及何时使用它,我想研究一下!
    • 我在 1980 年代第一次使用递归,所以我不是最好的人选。尝试搜索递归算法。维基百科可能会有所帮助,因为它是一种寻找解决方案的方法,而不是过于特定于语言。祝你好运。
    【解决方案2】:

    由于“i + j + k + l == 100”,你不需要每次都计算范围0~100,你可以限制范围并排除不可能的值,像这样:

        for i in range(0, 101):
            for j in range(0, 101-i):
                for k in range(0, 101-i-j):
                    for l in range(0, 101-i-j-k):
    

    之前的时间复杂度:O(n**4)

    >>> test = generate_weights()
    Time:  12.879271500000016
    

    之后的时间复杂度:O(n*log(n))

    >>> test = generate_weights()
    Time:  0.6409992999999758
    

    【讨论】:

    • 您好,感谢您的优化!我目前正在关注一种将手动“for i in range...for j in range...for k in range...”更改为对数组的动态引用并循环通过该数组或列表来实现的方法结果相同。
    猜你喜欢
    • 2018-04-16
    • 1970-01-01
    • 2019-05-04
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 2011-12-17
    • 1970-01-01
    相关资源
    最近更新 更多