Hen*_*ton 7 python for-loop numpy
我正在寻找Python和/或Numpy矢量化的方法,以消除以下的for循环使用:
for i in list_range_values:
v[list_list_values[i]] += list_comp_values[i]
Run Code Online (Sandbox Code Playgroud)
哪里:
list_range_values是一个整数值的Python列表,例如.[1,3,5],从范围(0,R-1,1)中抽取
list_comp_values是数值的Python列表,例如.[0.7,9.8,1.25,5,10,11.7,6,0.2]这样len(list_comp_values)= R
v是长度为V的numpy向量,使得R可以是<,=,>而不是V.
list_list_values是一个列表的Python列表(每个列表包含不同数量的整数值,例如[[3,6,7],[5,7,11,25,99],[8,45],[4,7] ,8],[0,1],[21,31,41],[9,11,22,33,44],[17,19]])从范围(0,V-1,1)中绘制并使用len(list_list_values)= R.
例如.
for i in list_range_values (= [1, 3, 5]):
i=1: v[[5, 7, 11, 25, 99]] += list_comp_values[1] (= 9.8)
i=3: v[[4, 7, 8]] += list_comp_values[3] (= 5)
i=5: v[[21, 31, 41]] += list_comp_values[5] (= 11.7)
Run Code Online (Sandbox Code Playgroud)
有没有可用的方法可以消除for循环?
Cython,Scipy/Weave/Blitz和C模块是替代解决方案,但是要确保首先是否存在Numpy矢量化答案.
虽然它通常会导致大量加速以消除for循环并利用numpy内置插件/矢量化.我只想指出情况并非总是如此.定时简单的for循环与更多涉及的矢量化,不会给你一个大的加速,而且更冗长.需要考虑的事情:
from timeit import Timer
setstr="""import numpy as np
import itertools
import random
Nlists = 1000
total_lists = 5000
outsz = 100
maxsublistsz = 100
# create random list of lists
list_range_values = random.sample(xrange(total_lists),Nlists)
list_list_values = [random.sample(xrange(outsz),np.random.randint(1,maxsublistsz)) for k in xrange(total_lists)]
list_comp_values = 10*np.random.uniform(size=(total_lists,))
v = np.zeros((outsz,))
def indices(start, end):
lens = end - start
np.cumsum(lens, out=lens)
i = np.ones(lens[-1], dtype=int)
i[0] = start[0]
i[lens[:-1]] += start[1:]
i[lens[:-1]] -= end[:-1]
np.cumsum(i, out=i)
return i
def sum_by_group(values, groups):
order = np.argsort(groups)
groups = groups[order]
values = values[order]
values.cumsum(out=values)
index = np.ones(len(groups), 'bool')
index[:-1] = groups[1:] != groups[:-1]
values = values[index]
groups = groups[index]
values[1:] = np.diff(values)
return values, groups
"""
method1="""
list_list_lens = np.array(map(len, list_list_values))
comp_vals_expanded = np.repeat(list_comp_values, list_list_lens)
list_vals_flat = np.fromiter(itertools.chain.from_iterable(list_list_values),dtype=int)
list_list_starts = np.concatenate(([0], np.cumsum(list_list_lens)[:-1]))
toadd = indices(list_list_starts[list_range_values],(list_list_starts + list_list_lens)[list_range_values])
v[list_vals_flat[toadd]] += comp_vals_expanded[toadd]
"""
method2="""
for k in list_range_values:
v[list_list_values[k]] += list_comp_values[k]
"""
method3="""
llv = [list_list_values[i] for i in list_range_values]
lcv = [list_comp_values[i] for i in list_range_values]
counts = map(len, llv)
indices = np.concatenate(llv)
values = np.repeat(lcv, counts)
totals, indices_unique = sum_by_group(values, indices)
v[indices_unique] += totals
"""
t1 = Timer(method1,setup=setstr).timeit(100)
print t1
t2 = Timer(method2,setup=setstr).timeit(100)
print t2
t3 = Timer(method3,setup=setstr).timeit(100)
print t3
Run Code Online (Sandbox Code Playgroud)
对于列表中的大量元素:
方法1 :(不用于循环-jterrace)1.43秒
方法2 :( for循环)4.62秒
方法3 :(不用于循环 - bago)2.99秒
对于少量列表(更改Nlists为10),for循环明显快于jterrace的解决方案:
方法1 :(不用于循环-jterrace)1.05秒
方法2 :( for循环)0.045秒
方法3 :(不用于循环 - bago)0.041秒
这不是敲@jterrace或@ bago的解决方案,这是非常优雅的.相反,它要指出的是,通常简单的for循环不会表现不佳.
| 归档时间: |
|
| 查看次数: |
1453 次 |
| 最近记录: |