Pythonic计算A x A'的方法(没有numpy)

时间:2016-02-06 11:13:32

标签: python numpy matrix multidimensional-array matrix-multiplication

所以A是一个只包含0和1的列表。在不使用nympy或scipy的情况下计算A * A'的最pythonic(也是相当快)的方法是什么。

上面的numpy等价物是:

def foo(a):
    return a * a.T

2 个答案:

答案 0 :(得分:2)

由于你的数据是0和1,可能最好的非numpy解决方案是使用bitarrays:

def dot_self(matrix):
    """ Multiply a 0-1 matrix by its transpose.
    Use bitarrays to possibly speed up calculations.
    """
    from bitarray import bitarray
    rows = tuple(bitarray(row) for row in matrix)
    return [[(r & c).count() for c in rows] for r in rows]

答案 1 :(得分:1)

如果无法安装bitarrayDot Product in Python without NumPy中的1d解决方案可以使用相同的嵌套式解析(https://stackoverflow.com/a/35241087/901925)。这没有利用数据的0/1性质。所以基本上它是嵌套迭代的练习。

def dot1d(a,b):
    return sum(x*y for x,y in zip(a,b))

def dot_2cmp(a):
    return [[dot1d(r,c) for c in a] for r in a]

itertools.product可用于迭代行和列组合,但结果是1d列表,然后需要进行分组(但这一步很快):

def dot2d(a):
    aa=[dot1d(x,y) for x,y in itertools.product(a,a)]
    return [aa[i::len(a)] for i in range(len(a))]

测试:

a=[[1,0,1,0],[0,1,0,1],[0,0,1,1],[1,1,0,0]]

In [246]: dot2d(a)
Out[246]: [[2, 0, 1, 1], [0, 2, 1, 1], [1, 1, 2, 0], [1, 1, 0, 2]]
In [247]: dot_2cmp(a)
Out[247]: [[2, 0, 1, 1], [0, 2, 1, 1], [1, 1, 2, 0], [1, 1, 0, 2]]
In [248]: np.dot(np.array(a),np.array(a).T).tolist()
Out[248]: [[2, 0, 1, 1], [0, 2, 1, 1], [1, 1, 2, 0], [1, 1, 0, 2]]

在较大列表的时间中,2个列表操作需要相同的时间。即使使用输入/输出数组转换,阵列版本也要快得多。

In [254]: b=np.random.randint(0,2,(100,100)).tolist()
In [255]: timeit np.dot(np.array(b),np.array(b).T).tolist()
100 loops, best of 3: 5.46 ms per loop
In [256]: timeit dot2d(b)
10 loops, best of 3: 177 ms per loop
In [257]: timeit dot_2cmp(b)
10 loops, best of 3: 177 ms per loop

结果是对称的,因此跳过重复计算可能是值得的。将它们重新映射到嵌套列表将比numpy更多地工作。

In [265]: timeit [[dot1d(r,c) for c in b[i:]] for i,r in enumerate(b)]
10 loops, best of 3: 90.1 ms per loop

对于它的价值,我不认为这些解决方案比其他解决方案更“Pythonic”。只要它是用清晰的,运行的Python编写的,它就是Pythonic。