Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 加速二维阵列上的NumPy循环-删除相似的行_Python_Performance_Numpy_Vectorization - Fatal编程技术网

Python 加速二维阵列上的NumPy循环-删除相似的行

Python 加速二维阵列上的NumPy循环-删除相似的行,python,performance,numpy,vectorization,Python,Performance,Numpy,Vectorization,我试图显著加快以下代码的速度,但没有效果。该代码接收二维数组并删除与数组中其他行相比过于相似的数组行。请参阅下面的代码和注释 as0 = a.shape[0] for i in range(as0): a2s0 = a.shape[0] # shape may change after each iteration if i > (a2s0 - 1): break # takes the difference between all rows in

我试图显著加快以下代码的速度,但没有效果。该代码接收二维数组并删除与数组中其他行相比过于相似的数组行。请参阅下面的代码和注释

as0 = a.shape[0]
for i in range(as0):
    a2s0 = a.shape[0] # shape may change after each iteration
    if i > (a2s0 - 1):
        break
    # takes the difference between all rows in array by iterating over each
    # row. Then sums the absolutes. The condition finally gives a boolean
    # array output - similarity condition of 0.01
    t = np.sum(np.absolute(a[i,:] - a), axis=1)<0.01
    # Retains the indices that are too similar and then deletes the
    # necessary row
    inddel = np.where(t)[0]
    inddel = [k for k in inddel if k != i]
    a = np.delete(a, inddel, 0)
第一行:

t = np.sum(np.absolute(a[i,:] - a), axis=1)<0.01
t=np.sum(np.absolute(a[i,:]-a,axis=1)

这里有一种矢量化方法,它利用了将
a
扩展到
3D
然后以矢量化的方式在所有迭代中执行这些计算-

mask = (np.absolute(a[:,None] - a)).sum(2) < 0.01
a_out = a[~np.triu(mask,1).any(0)]
标杆管理 接近-

# Approach#2 from this post
def remove_similar_rows(a, thresh=0.01):
    n = a.shape[0]
    dists = pdist(a, 'cityblock')
    idx = np.flatnonzero(dists < thresh)
    sep_idx = np.arange(n-1,0,-1).cumsum()
    rm_idx = np.unique(np.searchsorted(sep_idx,idx,'right'))
    return np.delete(a,rm_idx,axis=0)

# @John Zwinck's soln
def pairwise_manhattan_distances(a, thresh=0.01):
    d = manhattan_distances(a)
    return a[~np.any(np.tril(d < thresh), axis=0)]

让我们创建一些假数据:

np.random.seed(0)
a = np.random.random((4,3))
现在我们有:

array([[ 0.5488135 ,  0.71518937,  0.60276338],
       [ 0.54488318,  0.4236548 ,  0.64589411],
       [ 0.43758721,  0.891773  ,  0.96366276],
       [ 0.38344152,  0.79172504,  0.52889492]])
接下来,我们需要所有行对的元素差异之和。我们可以使用:

其中:

array([[ 0.        ,  0.33859562,  0.64870931,  0.31577611],
       [ 0.33859562,  0.        ,  0.89318282,  0.6465111 ],
       [ 0.64870931,  0.89318282,  0.        ,  0.5889615 ],
       [ 0.31577611,  0.6465111 ,  0.5889615 ,  0.        ]])
现在可以应用阈值,只保留一个三角形:

m = np.tril(d < 0.4, -1) # large threshold just for this example
这表明第0行与第1行和第3行“太相似”。现在,您可以从原始矩阵中删除掩码的任何元素为真的行:

a[~np.any(m, axis=0)] # axis can be either 0 or 1 - design choice
这给了你:

array([[ 0.54488318,  0.4236548 ,  0.64589411],
       [ 0.43758721,  0.891773  ,  0.96366276],
       [ 0.38344152,  0.79172504,  0.52889492]])
总而言之:

d = sklearn.metrics.pairwise.manhattan_distances(a)
a = a[~np.any(np.tril(d < 0.4, -1), axis=0)]
d=sklearn.metrics.pairwise.manhattan\u距离(a)
a=a[~np.any(np.tril(d<0.4,-1),轴=0)]

谢谢你,史蒂夫。到目前为止,我已经添加了一个edit,它删除了delete,现在我已经包含了只对未看到的行进行计算的代码。再次感谢您的
(np.absolute(a[:,None]-a))。sum(2)
在数学上是优雅的,但是如果输入的数据足够大,它就会爆炸。我试着输入一个(4000,30)的形状,花了很多秒,很多内存,然后我把它杀死了。我的答案中的
曼哈顿距离(a)
在150毫秒内做同样的事情。如果输入很小,你的速度会更快。@JohnZwinck你能在你的帖子中分享你的基准测试设置吗?很简单:
a=np.random.random((4000,30))
然后
%timeit(np.absolute(a[,None]-a)).sum(2)
在IPython中。@JohnZwinck添加了另一种有效的方法,以及计时测试。@Jean-michelaurencenairac:只需在几个块中重复运行它。例如,在前10k行上运行该算法,然后在接下来的10k行上运行该算法,同时删除。希望您删除很多行,最后您可以将剩余的行组装成最后一行。假设我们有行号:
6,10,12
“相似”。那么,是否可以删除前两行并保留最后一行,即
12
?是的。删除哪些索引并不重要。只要唯一的行仍然存在。要复制您的行,我必须做一个小的更改:
m=np.tril(d<0.4,k=-1)
@Jean-michelaurencenairac:你说得对,我在发布的代码中忽略了设置
k=-1
。现在修好了。
m = np.tril(d < 0.4, -1) # large threshold just for this example
array([[False, False, False, False],
       [ True, False, False, False],
       [False, False, False, False],
       [ True, False, False, False]], dtype=bool)
a[~np.any(m, axis=0)] # axis can be either 0 or 1 - design choice
array([[ 0.54488318,  0.4236548 ,  0.64589411],
       [ 0.43758721,  0.891773  ,  0.96366276],
       [ 0.38344152,  0.79172504,  0.52889492]])
d = sklearn.metrics.pairwise.manhattan_distances(a)
a = a[~np.any(np.tril(d < 0.4, -1), axis=0)]