要求:
这是我的代码:
def __init__(self):
self.data = []
def update(self, row):
self.data.append(row)
def finalize(self):
dx = np.array(self.data)
我尝试过的其他事情包括以下代码......但这种情况比较慢。
def class A:
def __init__(self):
self.data = np.array([])
def update(self, row):
np.append(self.data, row)
def finalize(self):
dx = np.reshape(self.data, size=(self.data.shape[0]/5, 5))
以下是如何调用它的示意图:
for i in range(500000):
ax = A()
for j in range(200):
ax.update([1,2,3,4,5])
ax.finalize()
# some processing on ax
答案 0 :(得分:72)
我尝试了一些不同的东西,时间。
import numpy as np
你提到的方法很慢:(32.094秒)
class A:
def __init__(self):
self.data = np.array([])
def update(self, row):
self.data = np.append(self.data, row)
def finalize(self):
return np.reshape(self.data, newshape=(self.data.shape[0]/5, 5))
常规ol Python列表:(0.308秒)
class B:
def __init__(self):
self.data = []
def update(self, row):
for r in row:
self.data.append(r)
def finalize(self):
return np.reshape(self.data, newshape=(len(self.data)/5, 5))
尝试在numpy中实现一个arraylist:(0.362秒)
class C:
def __init__(self):
self.data = np.zeros((100,))
self.capacity = 100
self.size = 0
def update(self, row):
for r in row:
self.add(r)
def add(self, x):
if self.size == self.capacity:
self.capacity *= 4
newdata = np.zeros((self.capacity,))
newdata[:self.size] = self.data
self.data = newdata
self.data[self.size] = x
self.size += 1
def finalize(self):
data = self.data[:self.size]
return np.reshape(data, newshape=(len(data)/5, 5))
这就是我计时的方式:
x = C()
for i in xrange(100000):
x.update([i])
所以看起来普通的旧Python列表非常好;)
答案 1 :(得分:16)
np.append()每次都复制数组中的所有数据,但是list会将容量增加一个因子(1.125)。 list很快,但内存使用量大于数组。如果你关心内存,你可以使用python标准库的数组模块。
以下是关于此主题的讨论:
答案 2 :(得分:10)
在Owen的帖子中使用类声明,这是一个修订的时间,但最终确定了一些效果。
简而言之,我发现C类提供的实现速度比原帖中的方法快60多倍。 (为文本墙道歉)
我使用的文件:
#!/usr/bin/python
import cProfile
import numpy as np
# ... class declarations here ...
def test_class(f):
x = f()
for i in xrange(100000):
x.update([i])
for i in xrange(1000):
x.finalize()
for x in 'ABC':
cProfile.run('test_class(%s)' % x)
现在,结果时间:
903005 function calls in 16.049 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 16.049 16.049 <string>:1(<module>)
100000 0.139 0.000 1.888 0.000 fromnumeric.py:1043(ravel)
1000 0.001 0.000 0.003 0.000 fromnumeric.py:107(reshape)
100000 0.322 0.000 14.424 0.000 function_base.py:3466(append)
100000 0.102 0.000 1.623 0.000 numeric.py:216(asarray)
100000 0.121 0.000 0.298 0.000 numeric.py:286(asanyarray)
1000 0.002 0.000 0.004 0.000 test.py:12(finalize)
1 0.146 0.146 16.049 16.049 test.py:50(test_class)
1 0.000 0.000 0.000 0.000 test.py:6(__init__)
100000 1.475 0.000 15.899 0.000 test.py:9(update)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
100000 0.126 0.000 0.126 0.000 {method 'ravel' of 'numpy.ndarray' objects}
1000 0.002 0.000 0.002 0.000 {method 'reshape' of 'numpy.ndarray' objects}
200001 1.698 0.000 1.698 0.000 {numpy.core.multiarray.array}
100000 11.915 0.000 11.915 0.000 {numpy.core.multiarray.concatenate}
208004 function calls in 16.885 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.001 0.001 16.885 16.885 <string>:1(<module>)
1000 0.025 0.000 16.508 0.017 fromnumeric.py:107(reshape)
1000 0.013 0.000 16.483 0.016 fromnumeric.py:32(_wrapit)
1000 0.007 0.000 16.445 0.016 numeric.py:216(asarray)
1 0.000 0.000 0.000 0.000 test.py:16(__init__)
100000 0.068 0.000 0.080 0.000 test.py:19(update)
1000 0.012 0.000 16.520 0.017 test.py:23(finalize)
1 0.284 0.284 16.883 16.883 test.py:50(test_class)
1000 0.005 0.000 0.005 0.000 {getattr}
1000 0.001 0.000 0.001 0.000 {len}
100000 0.012 0.000 0.012 0.000 {method 'append' of 'list' objects}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1000 0.020 0.000 0.020 0.000 {method 'reshape' of 'numpy.ndarray' objects}
1000 16.438 0.016 16.438 0.016 {numpy.core.multiarray.array}
204010 function calls in 0.244 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.244 0.244 <string>:1(<module>)
1000 0.001 0.000 0.003 0.000 fromnumeric.py:107(reshape)
1 0.000 0.000 0.000 0.000 test.py:27(__init__)
100000 0.082 0.000 0.170 0.000 test.py:32(update)
100000 0.087 0.000 0.088 0.000 test.py:36(add)
1000 0.002 0.000 0.005 0.000 test.py:46(finalize)
1 0.068 0.068 0.243 0.243 test.py:50(test_class)
1000 0.000 0.000 0.000 0.000 {len}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1000 0.002 0.000 0.002 0.000 {method 'reshape' of 'numpy.ndarray' objects}
6 0.001 0.000 0.001 0.000 {numpy.core.multiarray.zeros}
A类被更新破坏,B类被最终化破坏。 C类在两者面前都很强大。
答案 3 :(得分:2)
用于完成的函数存在很大的性能差异。请考虑以下代码:
N=100000
nruns=5
a=[]
for i in range(N):
a.append(np.zeros(1000))
print "start"
b=[]
for i in range(nruns):
s=time()
c=np.vstack(a)
b.append((time()-s))
print "Timing version vstack ",np.mean(b)
b=[]
for i in range(nruns):
s=time()
c1=np.reshape(a,(N,1000))
b.append((time()-s))
print "Timing version reshape ",np.mean(b)
b=[]
for i in range(nruns):
s=time()
c2=np.concatenate(a,axis=0).reshape(-1,1000)
b.append((time()-s))
print "Timing version concatenate ",np.mean(b)
print c.shape,c2.shape
assert (c==c2).all()
assert (c==c1).all()
使用连接似乎是第一个版本的两倍,比第二个版本快10倍。
Timing version vstack 1.5774928093
Timing version reshape 9.67419199944
Timing version concatenate 0.669512557983
答案 4 :(得分:1)
如果您希望通过列表操作提高性能,请查看blist库。它是python列表和其他结构的优化实现。
我没有对它进行基准测试,但是他们页面中的结果似乎很有希望。
答案 5 :(得分:1)
添加到 Owen 和 Prashant Kumar 发布了一个使用多维 numpy 数组(又名形状)的版本,加快了 numpy 解决方案的代码。特别是如果您需要经常访问 (finalize()) 数据。
版本 | Prashant Kumar | row_length=1 | row_length=5 |
---|---|---|---|
A 类 - np.append | 2.873 秒 | 2.776 秒 | 0.682 秒 |
B 类-python 列表 | 6.693 秒 | 80.868 秒 | 22.012 秒 |
C 类 - 数组列表 | 0.095 秒 | 0.180 秒 | 0.043 秒 |
Prashant Kumar
列是他在我的机器上执行的示例以进行比较。 row_length=5
是初始问题的示例。 python list
的急剧增加来自 {built-in method numpy.array}
,这意味着 numpy 需要更多的时间将列表的多维列表转换为相对于一维列表的数组,并在两者都具有的情况下对其进行整形相同数量的条目,例如np.array([[1,2,3]*5])
与 np.array([1]*15).reshape((-1,3))
。
这是代码:
import cProfile
import numpy as np
class A:
def __init__(self,shape=(0,), dtype=float):
"""First item of shape is ingnored, the rest defines the shape"""
self.data = np.array([], dtype=dtype).reshape((0,*shape[1:]))
def update(self, row):
self.data = np.append(self.data, row)
def finalize(self):
return self.data
class B:
def __init__(self, shape=(0,), dtype=float):
"""First item of shape is ingnored, the rest defines the shape"""
self.shape = shape
self.dtype = dtype
self.data = []
def update(self, row):
self.data.append(row)
def finalize(self):
return np.array(self.data, dtype=self.dtype).reshape((-1, *self.shape[1:]))
class C:
def __init__(self, shape=(0,), dtype=float):
"""First item of shape is ingnored, the rest defines the shape"""
self.shape = shape
self.data = np.zeros((100,*shape[1:]),dtype=dtype)
self.capacity = 100
self.size = 0
def update(self, x):
if self.size == self.capacity:
self.capacity *= 4
newdata = np.zeros((self.capacity,*self.data.shape[1:]))
newdata[:self.size] = self.data
self.data = newdata
self.data[self.size] = x
self.size += 1
def finalize(self):
return self.data[:self.size]
def test_class(f):
row_length = 5
x = f(shape=(0,row_length))
for i in range(int(100000/row_length)):
x.update([i]*row_length)
for i in range(1000):
x.finalize()
for x in 'ABC':
cProfile.run('test_class(%s)' % x)
还有另一个添加到 post above from Luca Fiaschi 的选项。
b=[]
for i in range(nruns):
s=time.time()
c1=np.array(a, dtype=int).reshape((N,1000))
b.append((time.time()-s))
print("Timing version array.reshape ",np.mean(b))
给我:
Timing version vstack 0.6863266944885253
Timing version reshape 0.505419111251831
Timing version array.reshape 0.5052066326141358
Timing version concatenate 0.5339600563049316