Python 如何使用numpy有效地对此类操作进行矢量化? 输入数据

Python 如何使用numpy有效地对此类操作进行矢量化? 输入数据,python,numpy,Python,Numpy,生成给定大小的n个矩阵(此处为3x2)。我也选择了n=25,但我让n来强调这样一个事实,我们得到的是一组矩阵 import numpy as np n = 25 data = np.random.rand(n, 3, 2) 这只是一个格式示例:我无法更改它。或者,如果我这样做了,我们必须考虑到这种变化的计算成本 当前实施 我想在原子上实现的是: output = [] for datum in data: # This outputs on (3x2) matrix after the oth

生成给定大小的n个矩阵(此处为3x2)。我也选择了n=25,但我让n来强调这样一个事实,我们得到的是一组矩阵

import numpy as np
n = 25
data = np.random.rand(n, 3, 2)
这只是一个格式示例:我无法更改它。或者,如果我这样做了,我们必须考虑到这种变化的计算成本

当前实施 我想在原子上实现的是:

output = []
for datum in data: # This outputs on (3x2) matrix after the other
    d0 = datum[0]
    dr = datum[1:]
    output.append(dr-d0)
或者,以更快的方式:

output = [dr-d0 for (dr, d0) in zip(datum[:,0], datum[:,1:])]
问题 这太慢了,而且:

output = datum[:,1:] - datum[:,0]
不起作用,因为在这种情况下,减法运算的行为没有得到很好的定义。另外,这种切片效率不高

Cython/Nuitka/PyPy等都是可能的解决方案,但如果可能的话,我现在想继续使用原始的Numpy。也许某种函数可以非常快速地应用于numpy数组外部循环的元素,而不需要python的开销

np.vectorize
函数不适用于:

def get_diff(mat):
    return mat[1:] - mat[0]
所以我请求你们,努比的大祭司,巨蟒的仆人来开导我可怜的灵魂

编辑:

XY问题 (我不知道它有名字)

我实际上想做的是确定许多简单体(读“四面体”)的内容(读“体积”)。AFAIK最简单、最有效的方法是计算:

np.linalg.det(mat[:1]-mat[0])

然后让我重新表述我的问题:如何使用普通python和numpy有效地计算任何维度为k的简单集合的内容?

我建议
数据[:,1:]-数据[:,0,无]
None
创建了一个新的轴(您应该正式使用
np.newaxis
,这使您的操作非常清楚),然后减法将按照您希望的方式进行

纠正我认为您列表理解中的错误:

def loop(data):
    output = []
    for datum in data: # This outputs on (3x2) matrix after the other
        d0 = datum[0]
        dr = datum[1:]
        output.append(dr-d0)
    return output

def listcomp(data):
    output = [dr-d0 for (d0, dr) in zip(data[:,0], data[:,1:])]
    return output

def sub(data):
    output = data[:,1:] - data[:,0,None]
    return output
我们有

>>> import numpy as np
>>> n = 25
>>> data = np.random.rand(n, 3, 2)
>>> res_loop = loop(data)
>>> res_listcomp = listcomp(data)
>>> res_sub = sub(data)
>>> np.allclose(res_loop, res_listcomp)
True
>>> np.allclose(res_loop, res_sub)
True
>>> 
>>> %timeit loop(data)
10000 loops, best of 3: 184 µs per loop
>>> %timeit listcomp(data)
10000 loops, best of 3: 158 µs per loop
>>> %timeit sub(data)
100000 loops, best of 3: 12.8 µs per loop

我建议
数据[:,1:]-数据[:,0,无]
None
创建了一个新的轴(您应该正式使用
np.newaxis
,这使您的操作非常清楚),然后减法将按照您希望的方式进行

纠正我认为您列表理解中的错误:

def loop(data):
    output = []
    for datum in data: # This outputs on (3x2) matrix after the other
        d0 = datum[0]
        dr = datum[1:]
        output.append(dr-d0)
    return output

def listcomp(data):
    output = [dr-d0 for (d0, dr) in zip(data[:,0], data[:,1:])]
    return output

def sub(data):
    output = data[:,1:] - data[:,0,None]
    return output
我们有

>>> import numpy as np
>>> n = 25
>>> data = np.random.rand(n, 3, 2)
>>> res_loop = loop(data)
>>> res_listcomp = listcomp(data)
>>> res_sub = sub(data)
>>> np.allclose(res_loop, res_listcomp)
True
>>> np.allclose(res_loop, res_sub)
True
>>> 
>>> %timeit loop(data)
10000 loops, best of 3: 184 µs per loop
>>> %timeit listcomp(data)
10000 loops, best of 3: 158 µs per loop
>>> %timeit sub(data)
100000 loops, best of 3: 12.8 µs per loop

我建议
数据[:,1:]-数据[:,0,无]
None
创建了一个新的轴(您应该正式使用
np.newaxis
,这使您的操作非常清楚),然后减法将按照您希望的方式进行

纠正我认为您列表理解中的错误:

def loop(data):
    output = []
    for datum in data: # This outputs on (3x2) matrix after the other
        d0 = datum[0]
        dr = datum[1:]
        output.append(dr-d0)
    return output

def listcomp(data):
    output = [dr-d0 for (d0, dr) in zip(data[:,0], data[:,1:])]
    return output

def sub(data):
    output = data[:,1:] - data[:,0,None]
    return output
我们有

>>> import numpy as np
>>> n = 25
>>> data = np.random.rand(n, 3, 2)
>>> res_loop = loop(data)
>>> res_listcomp = listcomp(data)
>>> res_sub = sub(data)
>>> np.allclose(res_loop, res_listcomp)
True
>>> np.allclose(res_loop, res_sub)
True
>>> 
>>> %timeit loop(data)
10000 loops, best of 3: 184 µs per loop
>>> %timeit listcomp(data)
10000 loops, best of 3: 158 µs per loop
>>> %timeit sub(data)
100000 loops, best of 3: 12.8 µs per loop

我建议
数据[:,1:]-数据[:,0,无]
None
创建了一个新的轴(您应该正式使用
np.newaxis
,这使您的操作非常清楚),然后减法将按照您希望的方式进行

纠正我认为您列表理解中的错误:

def loop(data):
    output = []
    for datum in data: # This outputs on (3x2) matrix after the other
        d0 = datum[0]
        dr = datum[1:]
        output.append(dr-d0)
    return output

def listcomp(data):
    output = [dr-d0 for (d0, dr) in zip(data[:,0], data[:,1:])]
    return output

def sub(data):
    output = data[:,1:] - data[:,0,None]
    return output
我们有

>>> import numpy as np
>>> n = 25
>>> data = np.random.rand(n, 3, 2)
>>> res_loop = loop(data)
>>> res_listcomp = listcomp(data)
>>> res_sub = sub(data)
>>> np.allclose(res_loop, res_listcomp)
True
>>> np.allclose(res_loop, res_sub)
True
>>> 
>>> %timeit loop(data)
10000 loops, best of 3: 184 µs per loop
>>> %timeit listcomp(data)
10000 loops, best of 3: 158 µs per loop
>>> %timeit sub(data)
100000 loops, best of 3: 12.8 µs per loop


我将引用我最喜欢的新概念(谢谢@alKid)。这似乎是一个错误。你到底想做什么?试着理解你的代码,对于每个3x2子矩阵,你想要一个列表/数组,包含从后两列减去的第一列?@E先生:更正了,是的。我将调用我最喜欢的新概念(谢谢@alKid)。这似乎是一个错误。你到底想做什么?试着理解你的代码,对于每个3x2子矩阵,你想要一个列表/数组,包含从后两列减去的第一列?@E先生:更正了,是的。我将调用我最喜欢的新概念(谢谢@alKid)。这似乎是一个错误。你到底想做什么?试着理解你的代码,对于每个3x2子矩阵,你想要一个列表/数组,包含从后两列减去的第一列?@E先生:更正了,是的。我将调用我最喜欢的新概念(谢谢@alKid)。这似乎是一个错误。你到底想做什么?试图理解你的代码,对于每个3x2子矩阵,你想要一个列表/数组,其中包含从后两列减去的第一列?@E先生:更正了,是的。请告诉我:)只是想指出,这里使用的使矢量化工作的关键是调用。广播是一个非常有用的功能。一个数量级,这是伟大的!我不知道我不能用这样的。事实上,当我把n提高到800时,我有了x100的改进。这是我这周学到的最棒的东西。谢谢谢谢你的链接,E先生绝对是一个很好的信息来源@盖尔:当然。E先生的建议很好——值得花时间阅读教程,以了解广播是如何工作的。缺点是它使某些事情变得如此简单,以至于在没有它的情况下很难切换到环境..请告诉我:)我想指出的是,这里使用的使矢量化工作正常的关键东西叫做。广播是一个非常有用的功能。一个数量级,这是伟大的!我不知道我不能用这样的。事实上,当我把n提高到800时,我有了x100的改进。这是我这周学到的最棒的东西。谢谢谢谢你的链接,E先生绝对是一个很好的信息来源@盖尔:当然。E先生的建议很好——值得花时间阅读教程,以了解广播是如何工作的。缺点是它使某些事情变得如此简单,以至于在没有它的情况下很难切换到环境..请告诉我:)我想指出的是,这里使用的使矢量化工作正常的关键东西叫做。广播是一个非常有用的功能。一个数量级,这是伟大的!我不知道我不能用这样的。事实上,当我把n提高到800时,我有了x100的改进。这是我这周学到的最棒的东西。谢谢谢谢你的链接,E先生绝对是一个很好的信息来源@盖尔:当然。E先生的建议很好,值得花时间认真考虑