【问题标题】:Multiplication of (0,1)-matrix with a (0,1)-vector(0,1) 矩阵与 (0,1) 向量的乘法
【发布时间】:2014-07-17 14:08:19
【问题描述】:

在 Python 中,我想将二进制矩阵(每个元素为 0 或 1)与二进制向量相乘。矩阵的大小类似于 100000 x 100,向量有 100 个元素。如果 V 和 x 分别是矩阵和向量(初始化为 bool),这个简单的代码就可以完成这项工作:

V.astype(np.int8).dot(x.astype(np.int8))

我的问题是:有没有办法通过利用 2 个操作数的二进制特性来更快地做到这一点?毕竟,这 100000 次操作中的每一个都是 V 的一行与向量 x 之间的逻辑与之和。

感谢您的帮助。 帕特里克

编辑:刚刚尝试了您的解决方案 unutbu。奇怪的是,这两种方法(int8 et einsum)的性能在我的机器上似乎相似。

【问题讨论】:

    标签: python matrix binary


    【解决方案1】:

    你可以使用np.einsum:

    In [12]: V = np.random.randint(2, size=(100000,100))
    In [14]: x = np.random.randint(2, size=100)
    In [15]: expected = V.astype(np.int8).dot(x.astype(np.int8))
    In [28]: result = np.einsum('ij,j->i', V, x)
    

    结果是一样的:

    In [29]: np.allclose(expected, result)
    Out[29]: True
    

    np.einsum 大约快 3 倍:

    In [30]: %timeit np.einsum('ij,j->i', V, x)
    100 loops, best of 3: 6.92 ms per loop
    In [25]: %timeit V.astype(np.int8).dot(x.astype(np.int8))
    10 loops, best of 3: 22.4 ms per loop
    

    注意:与您的原始代码不同,np.einsum 在这种情况下返回一个 dtype 为 int32 的数组。


    您可以尝试使用np.logical_andnp.sum,但这样做会慢很多:

    In [45]: result2 = np.logical_and(V, x).sum(axis=1)
    
    In [46]: np.allclose(expected, result2)
    Out[46]: True
    
    In [47]: %timeit np.logical_and(V, x).sum(axis=1)
    10 loops, best of 3: 78 ms per loop
    

    这可能会更慢,因为分两步进行计算 需要形成一个形状为 (100000, 100) 的中间数组np.logical_and(V, x)。调用 np.einsum 让底层 C++ 函数直接计算结果。

    【讨论】:

    • 刚刚尝试了您的解决方案 unutbu。奇怪的是,两种方法(int8 et einsum)的性能在我的机器上似乎相似。
    • 这是可能的。各种方法的性能(甚至是相对性能)可能取决于 NumPy 的版本、编译 NumPy 时使用的库(参见np.show_config())、操作系统、硬件等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-06
    • 2018-11-06
    • 2020-03-16
    • 2020-10-29
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    相关资源
    最近更新 更多