如何根据样本相对于已经 select 编辑的样本的距离 select 数值样本 (Python)
How to select numeric samples based on their distance relative to samples already selected (Python)
我有一些形状为 (500,2) 的二维数组中的随机测试数据:
xy = np.random.randint(low=0.1, high=1000, size=[500, 2])
从这个数组中,我先select 10个随机样本,到select第11个样本,我想挑离原来的10个最远的样本select 集体编辑样本,我正在使用欧几里德距离来做到这一点。我需要继续这样做,直到选择了一定数量。这是我的尝试。
# Function to get the distance between samples
def get_dist(a, b):
return np.sqrt(np.sum(np.square(a - b)))
# Set up variables and empty lists for the selected sample and starting samples
n_xy_to_select = 120
selected_xy = []
starting = []
# This selects 10 random samples and appends them to selected_xy
for i in range(10):
idx = np.random.randint(len(xy))
starting_10 = xy[idx, :]
selected_xy.append(starting_10)
starting.append(starting_10)
xy = np.delete(xy, idx, axis = 0)
starting = np.asarray(starting)
# This performs the selection based on the distances
for i in range(n_xy_to_select - 1):
# Set up an empty array dists
dists = np.zeros(len(xy))
for selected_xy_ in selected_xy:
# Get the distance between each already selected sample, and every other unselected sample
dists_ = np.array([get_dist(selected_xy_, xy_) for xy_ in xy])
# Apply some kind of penalty function - this is the key
dists_[dists_ < 90] -= 25000
# Sum dists_ onto dists
dists += dists_
# Select the largest one
dist_max_idx = np.argmax(dists)
selected_xy.append(xy[dist_max_idx])
xy = np.delete(xy, dist_max_idx, axis = 0)
关键是这一行——惩罚函数
dists_[dists_ < 90] -= 25000
此惩罚函数的存在是为了防止代码通过人为缩短靠近的值来仅在 space 的边缘选择一圈样本。
然而,这最终会崩溃,并且 selection 开始聚集,如图所示。您可以清楚地看到,在需要任何类型的聚类之前,代码可以生成更好的 selection。我觉得一种衰减指数函数最适合这个,但我不知道如何实现它。
所以我的问题是;我将如何更改当前的惩罚函数以获得我正在寻找的东西?
根据你的问题,我了解到你正在寻找的是周期性边界条件(PBC)。这意味着 space 左边缘的点紧挨着右端。因此,沿着一个轴可以获得的最大距离由框的一半(即边缘和中心之间)给出。
要考虑到 PBC,您需要计算每个轴上的距离并减去方框的一半:
例如,如果您有一个 x1 = 100 的点和第二个 x2 = 900 的点,使用 PBC,它们相隔 200 个单位:|x1 - x2| - 500. 在一般情况下,给定 2 个坐标和半尺寸框,您最终得到:
在你的例子中,这简化为:
delta_x[delta_x > 500] = delta_x[delta_x > 500] - 500
总结一下,我使用新的 distance
函数重写了您的代码(请注意,我删除了一些不必要的 for 循环):
import numpy as np
def distance(p, arr, 500):
delta_x = np.abs(p[0] - arr[:,0])
delta_y = np.abs(p[1] - arr[:,1])
delta_x[delta_x > 500] = delta_x[delta_x > 500] - 500
delta_y[delta_y > 500] = delta_y[delta_y > 500] - 500
return np.sqrt(delta_x**2 + delta_y**2)
xy = np.random.randint(low=0.1, high=1000, size=[500, 2])
idx = np.random.randint(500, size=10)
selected_xy = list(xy[idx])
_initial_selected = xy[idx]
xy = np.delete(xy, idx, axis = 0)
n_xy_to_select = 120
for i in range(n_xy_to_select - 1):
# Set up an empty array dists
dists = np.zeros(len(xy))
for selected_xy_ in selected_xy:
# Compute the distance taking into account the PBC
dists_ = distance(selected_xy_, xy)
dists += dists_
# Select the largest one
dist_max_idx = np.argmax(dists)
selected_xy.append(xy[dist_max_idx])
xy = np.delete(xy, dist_max_idx, axis = 0)
实际上它会创建集群,这是正常现象,因为您倾向于创建彼此之间距离最远的点集群。不仅如此,由于边界条件,我们将沿一个轴的 2 点之间的最大距离设置为 500。因此,两个簇之间的最大距离也是 500!正如您在图片上看到的那样,情况就是如此。
此外,选择更多数字将开始画线以连接不同的集群,从中央的开始,如您在此处看到的那样:
我要找的是 'Furthest Point Sampling'。我对该解决方案进行了更多研究,可在此处找到用于执行此操作的 Python 代码:https://minibatchai.com/ai/2021/08/07/FPS.html
我有一些形状为 (500,2) 的二维数组中的随机测试数据:
xy = np.random.randint(low=0.1, high=1000, size=[500, 2])
从这个数组中,我先select 10个随机样本,到select第11个样本,我想挑离原来的10个最远的样本select 集体编辑样本,我正在使用欧几里德距离来做到这一点。我需要继续这样做,直到选择了一定数量。这是我的尝试。
# Function to get the distance between samples
def get_dist(a, b):
return np.sqrt(np.sum(np.square(a - b)))
# Set up variables and empty lists for the selected sample and starting samples
n_xy_to_select = 120
selected_xy = []
starting = []
# This selects 10 random samples and appends them to selected_xy
for i in range(10):
idx = np.random.randint(len(xy))
starting_10 = xy[idx, :]
selected_xy.append(starting_10)
starting.append(starting_10)
xy = np.delete(xy, idx, axis = 0)
starting = np.asarray(starting)
# This performs the selection based on the distances
for i in range(n_xy_to_select - 1):
# Set up an empty array dists
dists = np.zeros(len(xy))
for selected_xy_ in selected_xy:
# Get the distance between each already selected sample, and every other unselected sample
dists_ = np.array([get_dist(selected_xy_, xy_) for xy_ in xy])
# Apply some kind of penalty function - this is the key
dists_[dists_ < 90] -= 25000
# Sum dists_ onto dists
dists += dists_
# Select the largest one
dist_max_idx = np.argmax(dists)
selected_xy.append(xy[dist_max_idx])
xy = np.delete(xy, dist_max_idx, axis = 0)
关键是这一行——惩罚函数
dists_[dists_ < 90] -= 25000
此惩罚函数的存在是为了防止代码通过人为缩短靠近的值来仅在 space 的边缘选择一圈样本。
然而,这最终会崩溃,并且 selection 开始聚集,如图所示。您可以清楚地看到,在需要任何类型的聚类之前,代码可以生成更好的 selection。我觉得一种衰减指数函数最适合这个,但我不知道如何实现它。
根据你的问题,我了解到你正在寻找的是周期性边界条件(PBC)。这意味着 space 左边缘的点紧挨着右端。因此,沿着一个轴可以获得的最大距离由框的一半(即边缘和中心之间)给出。
要考虑到 PBC,您需要计算每个轴上的距离并减去方框的一半: 例如,如果您有一个 x1 = 100 的点和第二个 x2 = 900 的点,使用 PBC,它们相隔 200 个单位:|x1 - x2| - 500. 在一般情况下,给定 2 个坐标和半尺寸框,您最终得到:
在你的例子中,这简化为:
delta_x[delta_x > 500] = delta_x[delta_x > 500] - 500
总结一下,我使用新的 distance
函数重写了您的代码(请注意,我删除了一些不必要的 for 循环):
import numpy as np
def distance(p, arr, 500):
delta_x = np.abs(p[0] - arr[:,0])
delta_y = np.abs(p[1] - arr[:,1])
delta_x[delta_x > 500] = delta_x[delta_x > 500] - 500
delta_y[delta_y > 500] = delta_y[delta_y > 500] - 500
return np.sqrt(delta_x**2 + delta_y**2)
xy = np.random.randint(low=0.1, high=1000, size=[500, 2])
idx = np.random.randint(500, size=10)
selected_xy = list(xy[idx])
_initial_selected = xy[idx]
xy = np.delete(xy, idx, axis = 0)
n_xy_to_select = 120
for i in range(n_xy_to_select - 1):
# Set up an empty array dists
dists = np.zeros(len(xy))
for selected_xy_ in selected_xy:
# Compute the distance taking into account the PBC
dists_ = distance(selected_xy_, xy)
dists += dists_
# Select the largest one
dist_max_idx = np.argmax(dists)
selected_xy.append(xy[dist_max_idx])
xy = np.delete(xy, dist_max_idx, axis = 0)
实际上它会创建集群,这是正常现象,因为您倾向于创建彼此之间距离最远的点集群。不仅如此,由于边界条件,我们将沿一个轴的 2 点之间的最大距离设置为 500。因此,两个簇之间的最大距离也是 500!正如您在图片上看到的那样,情况就是如此。
此外,选择更多数字将开始画线以连接不同的集群,从中央的开始,如您在此处看到的那样:
我要找的是 'Furthest Point Sampling'。我对该解决方案进行了更多研究,可在此处找到用于执行此操作的 Python 代码:https://minibatchai.com/ai/2021/08/07/FPS.html