我在这个计算机视觉book中经历了一个例子,对代码感到有些惊讶:
descr = []
descr.append(sift.read_features_from_file(featurefiles[0])[1])
descriptors = descr[0] #stack all features for k-means
for i in arange(1,nbr_images):
descr.append(sift.read_features_from_file(featurefiles[i])[1])
descriptors = vstack((descriptors,descr[i]))
对我来说,这似乎是一遍又一遍地复制数组,更有效的实现方式是:
descr = []
descr.append(sift.read_features_from_file(featurefiles[0])[1])
for i in arange(1,nbr_images):
descr.append(sift.read_features_from_file(featurefiles[i])[1])
descriptors = vstack((descr))
或者我在这里遗漏了一些东西,这两个代码并不相同。我做了一个小测试:
print("ATTENTION")
print(descriptors.shape)
print("ATTENTION")
print(descriptors[1:10])
似乎列表不同了?
答案 0 :(得分:1)
你是绝对正确的 - 在循环中反复连接numpy数组极其效率低下。连接始终会生成一个副本,随着您的数组在循环内变得越来越大,这会变得越来越昂贵。
相反,做两件事之一:
正如您所做的那样,将中间值存储在常规Python list
中并将其转换为循环外的numpy数组。附加到list
的是 O(1),而连接np.ndarray
的是 O(n + k)。
如果您知道最终数组的提前量,您可以预先分配它,然后填写for
循环内的行,例如:
descr = np.empty((nbr_images, nbr_features), dtype=my_dtype)
for i in range(nbr_image):
descr[i] = sift.read_features_from_file(featurefiles[i])[1]
另一种变体是使用np.fromiter
从可迭代对象延迟生成数组,例如在this recent question中。