我在一组42000张图像上实现了一个名为TF-IDF的加权系统,每张图像由784个像素组成,这基本上是一个42000 × 784的矩阵。
我尝试的第一种方法使用了显式循环,花费了 * 超过2个小时 *。
def tfidf(color,img_pix,img_total):
if img_pix==0:
return 0
else:
return color * np.log(img_total/img_pix)
...
result = np.array([])
for img_vec in data_matrix:
double_vec = zip(img_vec,img_pix_vec)
result_row = np.array([tfidf(x[0],x[1],img_total) for x in double_vec])
try:
result = np.vstack((result,result_row))
# first row will throw a ValueError since vstack accepts rows of same len
except ValueError:
result = result_row
我尝试的第二种方法使用了numpy矩阵,* 花费了不到5分钟 *。注意,data_matrix
,img_pix_mat
都是42000 × 784矩阵,而img_total
是标量。
result = data_matrix * np.log(np.divide(img_total,img_pix_mat))
我希望有人能解释速度的巨大差异。
以下论文的作者题为“NumPy数组:a structure for efficient numerical computation”(http://arxiv.org/pdf/1102.1523.pdf),在第4页的顶部指出,由于矢量化计算,他们观察到速度增加了500倍。我假设我看到的速度增加大部分是由于这一点。然而,我想更进一步,问为什么numpy
矢量化计算比标准python循环快得多?
另外,也许你们知道第一种方法慢的其他原因。try/except结构的开销高吗?或者为每个循环创建一个新的np.array
需要很长时间?
谢谢。
2条答案
按热度按时间j13ufse21#
由于numpy的内部工作原理,(据我所知,numpy内部使用C,所以你下推到numpy的所有东西实际上都要快得多,因为它是用不同的语言编写的)
编辑:
取出
zip
,并将其替换为vstack
也会使其更快,(如果参数非常大,zip
往往会变慢,而vstack
更快;另外,vstack
是numpy(因此是C),而zip是python)。是的,如果我理解正确的话--不确定--你正在做42 k次的尝试/例外块。这肯定会对速度不利。
测试:
结果为(10,)
这意味着是的,如果你的矩阵是42 k乘784的矩阵,你正在尝试42 k次的try-except块。我假设这应该会对计算时间产生影响,以及每次执行
zip
,但不确定这是否是主要原因。(So你运行你的东西的42 k次中的每一次,都需要0.17秒。我很确定try/except块不需要0.17秒,但也许它导致的开销或确实有助于它?)
尝试更改以下内容:
到
这至少摆脱了
zip
语句。不确定zip
语句是占用了你一分钟的时间还是将近两个小时的时间(我知道zip
与numpy.vstack
相比很慢,但不知道这是否会给你带来两个小时的时间增益。)emeijp432#
你所看到的差异并不是因为SSE向量化之类的花哨。主要有两个原因。第一个是NumPy是用C编写的,C实现不必经历Python实现所经历的大量运行时方法调度和异常检查等。
第二个原因是,即使对于Python代码,基于循环的实现也是低效的。您在循环中使用
vstack
,每次调用vstack
时,它都必须完全复制您传递给它的所有数组。这会为您的渐近复杂度增加len(data_matrix)
的额外因素。