![](/img/trans.png)
[英]How to Efficiently Find the Indices of Max Values in a Multidimensional Array of Matrices using Pytorch and/or Numpy
[英]How to find the local minima of a smooth multidimensional array in NumPy efficiently?
假設我在 NumPy 中有一個包含連續可微函數求值的數組,我想找到局部最小值。 沒有噪音,因此每個值低於其所有鄰居值的點都符合我的局部最小值標准。
我有以下列表理解,它適用於二維數組,忽略邊界上的潛在最小值:
import numpy as N
def local_minima(array2d):
local_minima = [ index
for index in N.ndindex(array2d.shape)
if index[0] > 0
if index[1] > 0
if index[0] < array2d.shape[0] - 1
if index[1] < array2d.shape[1] - 1
if array2d[index] < array2d[index[0] - 1, index[1] - 1]
if array2d[index] < array2d[index[0] - 1, index[1]]
if array2d[index] < array2d[index[0] - 1, index[1] + 1]
if array2d[index] < array2d[index[0], index[1] - 1]
if array2d[index] < array2d[index[0], index[1] + 1]
if array2d[index] < array2d[index[0] + 1, index[1] - 1]
if array2d[index] < array2d[index[0] + 1, index[1]]
if array2d[index] < array2d[index[0] + 1, index[1] + 1]
]
return local_minima
然而,這是相當緩慢的。 我還想讓它適用於任意數量的維度。 例如,是否有一種簡單的方法可以獲取任意維度數組中某個點的所有鄰居? 還是我完全以錯誤的方式解決了這個問題? 我應該使用numpy.gradient()
嗎?
可以使用Ivan的detect_peaks 函數找到任意維度數組的局部最小值的位置,稍作修改:
import numpy as np
import scipy.ndimage.filters as filters
import scipy.ndimage.morphology as morphology
def detect_local_minima(arr):
# https://stackoverflow.com/questions/3684484/peak-detection-in-a-2d-array/3689710#3689710
"""
Takes an array and detects the troughs using the local maximum filter.
Returns a boolean mask of the troughs (i.e. 1 when
the pixel's value is the neighborhood maximum, 0 otherwise)
"""
# define an connected neighborhood
# http://www.scipy.org/doc/api_docs/SciPy.ndimage.morphology.html#generate_binary_structure
neighborhood = morphology.generate_binary_structure(len(arr.shape),2)
# apply the local minimum filter; all locations of minimum value
# in their neighborhood are set to 1
# http://www.scipy.org/doc/api_docs/SciPy.ndimage.filters.html#minimum_filter
local_min = (filters.minimum_filter(arr, footprint=neighborhood)==arr)
# local_min is a mask that contains the peaks we are
# looking for, but also the background.
# In order to isolate the peaks we must remove the background from the mask.
#
# we create the mask of the background
background = (arr==0)
#
# a little technicality: we must erode the background in order to
# successfully subtract it from local_min, otherwise a line will
# appear along the background border (artifact of the local minimum filter)
# http://www.scipy.org/doc/api_docs/SciPy.ndimage.morphology.html#binary_erosion
eroded_background = morphology.binary_erosion(
background, structure=neighborhood, border_value=1)
#
# we obtain the final mask, containing only peaks,
# by removing the background from the local_min mask
detected_minima = local_min ^ eroded_background
return np.where(detected_minima)
你可以這樣使用:
arr=np.array([[[0,0,0,-1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[-1,0,0,0]],
[[0,0,0,0],[0,-1,0,0],[0,0,0,0],[0,0,0,-1],[0,0,0,0]]])
local_minima_locations = detect_local_minima(arr)
print(arr)
# [[[ 0 0 0 -1]
# [ 0 0 0 0]
# [ 0 0 0 0]
# [ 0 0 0 0]
# [-1 0 0 0]]
# [[ 0 0 0 0]
# [ 0 -1 0 0]
# [ 0 0 0 0]
# [ 0 0 0 -1]
# [ 0 0 0 0]]]
這表示最小值出現在索引 [0,0,3]、[0,4,0]、[1,1,1] 和 [1,3,3] 處:
print(local_minima_locations)
# (array([0, 0, 1, 1]), array([0, 4, 1, 3]), array([3, 0, 1, 3]))
print(arr[local_minima_locations])
# [-1 -1 -1 -1]
試試這個 2D:
import numpy as N
def local_minima(array2d):
return ((array2d <= N.roll(array2d, 1, 0)) &
(array2d <= N.roll(array2d, -1, 0)) &
(array2d <= N.roll(array2d, 1, 1)) &
(array2d <= N.roll(array2d, -1, 1)))
這將返回一個類似 array2d 的數組,其中包含本地最小值(四個鄰居)所在的 True/False。
您可以使用@numba.jit 編譯此函數 - 我的測量速度提高了 488 倍
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.