以更pythonic的方式找到最近的邻居
Find nearest neighbour in a more pythonic way
A是一个点,P是点的列表。
我想找到哪个点 P[i] 最接近 A,即我想找到 P[i_0]
与:
i_0 = argmin_i || A - P[i]||^2
我是这样做的:
import numpy as np
# P is a list of 4 points
P = [np.array([-1, 0, 7, 3]), np.array([5, -2, 8, 1]), np.array([0, 2, -3, 4]), np.array([-9, 11, 3, 4])]
A = np.array([1, 2, 3, 4])
distance = 1000000000 # better would be : +infinity
closest = None
for p in P:
delta = sum((p - A)**2)
if delta < distance:
distance = delta
closest = p
print closest # the closest point to A among all the points in P
它可以工作,但是如何以 shorter/more Pythonic 方式做到这一点?
在 Python 中更普遍(甚至不使用 Numpy),如何找到 k_0 使得 D[k_0] = min D[k]
? 即 k_0 = argmin_k D[k]
实现您正在使用的相同算法的更 Pythonic 方法是用 key
函数调用 min
来替换循环:
closest = min(P, key=lambda p: sum((p - A)**2))
请注意,我使用 **
求幂(^
是 Python 中的二元异或运算符)。
使用内置 min
是这样的:
import math
p1 = [1,2]
plst = [[1,3], [10,10], [5,5]]
res = min(plst, key=lambda x: math.sqrt(pow(p1[0]-x[0], 2) + pow(p1[1]-x[1], 2)))
print res
[1, 3]
请注意,我只是使用普通 python 列表。
单行的 NumPy 版本:
clostest = P[np.argmin(np.apply_along_axis(lambda p: np.sum((p - A) **2), 1, P))]
numpy 中的完全矢量化方法。类似于@MikeMüller 之一,但使用 numpy's broadcasting 来避免 lambda 函数。
使用示例数据:
>>> P = [np.array([-1, 0, 7, 3]), np.array([5, -2, 8, 1]), np.array([0, 2, -3, 4]), np.array([-9, 11, 3, 4])]
>>> A = np.array([1, 2, 3, 4])
并制作 P
二维 numpy 数组:
>>> P = np.asarray(P)
>>> P
array([[-1, 0, 7, 3],
[ 5, -2, 8, 1],
[ 0, 2, -3, 4],
[-9, 11, 3, 4]])
可以用numpy一行计算:
>>> P[np.argmin(np.sum((P - A)**2, axis=1))]
请注意 P - A
,P.shape = (N, 4)
和 A.shape = (4,)
会将减法广播到 P
的所有行(Pi = Pi - A
)。
对于小 N
(P
中的行数),pythonic 方法可能更快。对于 N
的大值,这应该明显更快。
A是一个点,P是点的列表。
我想找到哪个点 P[i] 最接近 A,即我想找到 P[i_0]
与:
i_0 = argmin_i || A - P[i]||^2
我是这样做的:
import numpy as np
# P is a list of 4 points
P = [np.array([-1, 0, 7, 3]), np.array([5, -2, 8, 1]), np.array([0, 2, -3, 4]), np.array([-9, 11, 3, 4])]
A = np.array([1, 2, 3, 4])
distance = 1000000000 # better would be : +infinity
closest = None
for p in P:
delta = sum((p - A)**2)
if delta < distance:
distance = delta
closest = p
print closest # the closest point to A among all the points in P
它可以工作,但是如何以 shorter/more Pythonic 方式做到这一点?
在 Python 中更普遍(甚至不使用 Numpy),如何找到 k_0 使得 D[k_0] = min D[k]
? 即 k_0 = argmin_k D[k]
实现您正在使用的相同算法的更 Pythonic 方法是用 key
函数调用 min
来替换循环:
closest = min(P, key=lambda p: sum((p - A)**2))
请注意,我使用 **
求幂(^
是 Python 中的二元异或运算符)。
使用内置 min
是这样的:
import math
p1 = [1,2]
plst = [[1,3], [10,10], [5,5]]
res = min(plst, key=lambda x: math.sqrt(pow(p1[0]-x[0], 2) + pow(p1[1]-x[1], 2)))
print res
[1, 3]
请注意,我只是使用普通 python 列表。
单行的 NumPy 版本:
clostest = P[np.argmin(np.apply_along_axis(lambda p: np.sum((p - A) **2), 1, P))]
numpy 中的完全矢量化方法。类似于@MikeMüller 之一,但使用 numpy's broadcasting 来避免 lambda 函数。
使用示例数据:
>>> P = [np.array([-1, 0, 7, 3]), np.array([5, -2, 8, 1]), np.array([0, 2, -3, 4]), np.array([-9, 11, 3, 4])]
>>> A = np.array([1, 2, 3, 4])
并制作 P
二维 numpy 数组:
>>> P = np.asarray(P)
>>> P
array([[-1, 0, 7, 3],
[ 5, -2, 8, 1],
[ 0, 2, -3, 4],
[-9, 11, 3, 4]])
可以用numpy一行计算:
>>> P[np.argmin(np.sum((P - A)**2, axis=1))]
请注意 P - A
,P.shape = (N, 4)
和 A.shape = (4,)
会将减法广播到 P
的所有行(Pi = Pi - A
)。
对于小 N
(P
中的行数),pythonic 方法可能更快。对于 N
的大值,这应该明显更快。