使用特定位置的值初始化数组
Initialize an array with a value in a specific location
我想初始化一个用0填充的数组,在特定位置用1填充。我知道如何用这样的两行代码来做到这一点:
import numpy as np
shape = (2,3)
location = (0,1)
arr = np.zeros(shape)
arr[location] = 1
是否有更快的方法,也许使用 oneliner?
引入稀疏性
即使您可能找不到任何方法来加快这种简单的初始化速度,您可能希望对具有多个数据点的较大矩阵 and/or 使用 sparse matrices。
存在多种类型的稀疏矩阵,它们的目的是使某些计算速度更快(但其他一些计算速度更慢,具体针对每种类型)并且它们的内存使用效率更高,只要您的矩阵由许多零组成。
对于您的具体情况,它会更慢:
import numpy as np
from scipy import sparse
shape = (2, 3)
location = (0, 1)
# With dense matrix
arr = np.zeros(shape)
arr[location] = 1
# timeit > 280 ns ± 4.16 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# With coordinate matrix
sparr = sparse.coo_matrix(([1], ([location[0]], [location[1]])), shape=shape)
# timeit > 20.5 µs ± 156 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
稀疏性:矩阵的典型案例
但是想象一下你有一个非常大的矩阵,在一些地方调度,你可以简单地这样做:
shape = (2000, 3000)
n_points = 500
loc_y = np.random.randint(shape[0], size=(n_points))
loc_x = np.random.randint(shape[1], size=(n_points))
data = np.ones(np_points)
sp_arr = sparse.coo_matrix((data, (loc_y, loc_x)), shape=shape)
# timeit > 17.8 µs ± 90.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
而不是这个:
np_arr = np.zeros(shape)
for d, x, y in zip(data, loc_x, loc_y):
np_arr[y, x] = d
# timeit > 613 µs ± 8.53 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
...或类似这样的东西:
np_loc = [y * shape[1] + x for x, y in zip(loc_x, loc_y)] # not in the timeit
np_arr2 = np.zeros(shape)
np.put(np_arr2, np_loc, data)
# timeit > 497 µs ± 13.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
((sp_arr.toarray() == np_arr) & (np_arr == np_arr2)).all()
# > True
限制
请注意,在许多情况下,您可能必须将稀疏矩阵转换为经典的 numpy(密集)ndarray,这会占用计算时间。在您必须进行多次此类操作而无需在步骤之间将它们转换为密集数组的情况下,使用稀疏矩阵可能是最佳选择;例如,处理具有许多特征的数据集的单热编码表示。
玩得开心
最后一点,检查 how each sparse matrix type stores its data and when a certain type is more memory-efficient than another 很有趣。您甚至可以尝试推断与密集版本相比它们变得有害的数据点的临界数量。
我想初始化一个用0填充的数组,在特定位置用1填充。我知道如何用这样的两行代码来做到这一点:
import numpy as np
shape = (2,3)
location = (0,1)
arr = np.zeros(shape)
arr[location] = 1
是否有更快的方法,也许使用 oneliner?
引入稀疏性
即使您可能找不到任何方法来加快这种简单的初始化速度,您可能希望对具有多个数据点的较大矩阵 and/or 使用 sparse matrices。
存在多种类型的稀疏矩阵,它们的目的是使某些计算速度更快(但其他一些计算速度更慢,具体针对每种类型)并且它们的内存使用效率更高,只要您的矩阵由许多零组成。
对于您的具体情况,它会更慢:
import numpy as np
from scipy import sparse
shape = (2, 3)
location = (0, 1)
# With dense matrix
arr = np.zeros(shape)
arr[location] = 1
# timeit > 280 ns ± 4.16 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# With coordinate matrix
sparr = sparse.coo_matrix(([1], ([location[0]], [location[1]])), shape=shape)
# timeit > 20.5 µs ± 156 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
稀疏性:矩阵的典型案例
但是想象一下你有一个非常大的矩阵,在一些地方调度,你可以简单地这样做:
shape = (2000, 3000)
n_points = 500
loc_y = np.random.randint(shape[0], size=(n_points))
loc_x = np.random.randint(shape[1], size=(n_points))
data = np.ones(np_points)
sp_arr = sparse.coo_matrix((data, (loc_y, loc_x)), shape=shape)
# timeit > 17.8 µs ± 90.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
而不是这个:
np_arr = np.zeros(shape)
for d, x, y in zip(data, loc_x, loc_y):
np_arr[y, x] = d
# timeit > 613 µs ± 8.53 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
...或类似这样的东西:
np_loc = [y * shape[1] + x for x, y in zip(loc_x, loc_y)] # not in the timeit
np_arr2 = np.zeros(shape)
np.put(np_arr2, np_loc, data)
# timeit > 497 µs ± 13.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
((sp_arr.toarray() == np_arr) & (np_arr == np_arr2)).all()
# > True
限制
请注意,在许多情况下,您可能必须将稀疏矩阵转换为经典的 numpy(密集)ndarray,这会占用计算时间。在您必须进行多次此类操作而无需在步骤之间将它们转换为密集数组的情况下,使用稀疏矩阵可能是最佳选择;例如,处理具有许多特征的数据集的单热编码表示。
玩得开心
最后一点,检查 how each sparse matrix type stores its data and when a certain type is more memory-efficient than another 很有趣。您甚至可以尝试推断与密集版本相比它们变得有害的数据点的临界数量。