如何解决向量化包含迭代器的for循环numpy数组
我试图通过利用Numpy中的矢量化功能来使python函数更快地运行。
该函数的目的是在for循环的每次迭代结束时,位置arr [i,0](即每行的第一项)将包含2D数组(数据)中的行数,如果位置0处的值小于或等于该值或数组i
ans += map.getorDefault((int) (sq/v),0);
我当前正在使用for循环。运行时非常慢,因为它正在机器学习算法中使用。有人告诉我可以通过向量化for循环来进一步改善这一点。
在尝试使用列表理解功能时,我已经尝试过:
# Data is a 2D array
def function(data)
n = len(data)
arr = np.zeros(shape=(n,9))
for i,sample in enumerate(data):
arr[i][0] = np.count_nonzero(data[:,0] <= data[i][0])
arr[:,0] = ( np.count_nonzero(data[:,x] > data[i][x]) for i in gini_arr[:,0] )
如何将其向量化为for循环?
解决方法
在对我的初始解决方案的评论中,您写道:在第0列中,否 元素小于0 。因此,我得出一个结论,即 您的职能应该是 ,而不是 。
另一个奇怪的地方是您使用控件之一创建了一个循环 名为 sample 的变量,但您永远不要使用此变量。 一个更自然的解决方案是遍历 range(n)(您计算出 n 之前,作为 data 中的行数)。
要在代码中更正的最后一个细节是您的函数 什么都不会退回。
一项改进:在计算满足以下条件的元素的数量时 在某些情况下,根据定义,结果是一个 integers 数组, 不是 float 。
因此,您的函数的更正内容(使用旧方法) 应该是:
def function(data):
n = len(data)
arr = np.zeros((n,9),dtype=int)
for i in range(n):
arr[i,0] = np.count_nonzero(data[:,0] < data[i,0])
return arr
如何以矢量化方式计算结果
将函数定义为:
def fn(data):
dd = data[:,0] # The first column
res = np.less(dd[np.newaxis,:],dd[:,np.newaxis]).sum(axis=1)
return np.hstack([res[:,np.newaxis],np.zeros((dd.size,8),dtype=int)])
请注意, res ( 1-D 数组)包含以下内容的比较结果: dd 中的每个元素以及 dd 中的所有元素。
最终结果产生于:
- 将 res 转换为具有单列的数组
- 由8列填充为零的“加法”。
要测试此功能,我创建了一个测试数组:
data = np.arange(25).reshape(5,-1)
data[3,0] = 1
包含以下内容:
array([[ 0,1,2,3,4],[ 5,6,7,8,9],[10,11,12,13,14],[ 1,16,17,18,19],[20,21,22,23,24]])
然后我跑fn(data)
得到了
array([[0,0],[2,[3,[1,[4,0]])
对于上述测试数据(5行),我的函数仅计算了5%的速度 (您的107 µs和我的101 µs)。
但是对于更多行,例如60,您的功能完成 在1.24毫秒内,而我的功能在165微秒内,所以快了7倍。
对于更大的行数,我的代码的优点应该是 更明显。
按照截至2020-09-07的评论进行编辑
np.newaxis 工作原理的说明:
-
dd
(在 fn 函数中)包含array([ 0,5,10,20])
- data 的第一列,但这是一个 1-D 数组。 -
dd[np.newaxis,:]
是一个 2-D 数组,包含相同的数组 单个行中的数字:array([[ 0,20]])
。 -
dd[:,np.newaxis]
也是 2-D 数组,但这一次 相同的数字是单个列的内容:array([[ 0],[ 5],[10],[ 1],[20]])
-
现在运行
np.less(dd[np.newaxis,np.newaxis]).astype(int)
(为便于评估已计算的内容,我补充说 转换为 int ):array([[0,0]])
上面的结果是一个 2-D 数组,比较的结果 ( left_argument
),其中: - 行号是“行参数”中元素的数量,
- 列号是元素“列参数”的数目。
所以整个数组是“每个”比较的结果。
示例:行( 0 )中的第一个元素不少于 列的元素,因此结果的第一行包含 全零。
-
最后一步是 sum(axis = 1),即计算上述总和 沿着每一行排列。
这样,最终结果是:array([0,4])
,它将是
fn 函数的整个结果的第一列。
如果您仍然需要更多说明,请在网上搜索 np.newaxis 。 即使在SO上,您也可以找到很多关于此问题的解释。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。