矩阵最近邻填充是指对矩阵中指定元素取值用周围最近邻的元素取值进行替换。下面介绍三种实现方法。前两种方法适合较小的输入矩阵,第三种方法速度最快。
采用for循环的方式,逐个计算待替换元素位置与剩余非替换元素位置的距离,选择出其中距离最小位置的元素为替换目标。该方法用于采用for循环的形式,所以显存占用较少。mei函数定义如下所示:
def nearest_fill(x, a, b):
"""
Parameters
----------
x : array,输入矩阵
a : float,待替换元素取值下限
b : float,待替换元素取值上限
Returns
-------
x : array,替换后矩阵
"""
x = x.copy()
index_r = np.array(np.where((x>=a) & (x <=b))).T
index_t = np.array(np.where((x<a) | (x >b))).T
for ir in index_r:
d = (ir - index_t) ** 2
d = d[:, 0] + d[:, 1]
p = index_t[np.argmin(d)]
x[ir[0], ir[1]] = x[p[0], p[1]]
return x
采用矩阵的方式,逐个计算待替换元素位置与剩余非替换元素位置的距离,选择出其中距离最小位置的元素为替换目标。这种方式会存储全部距离矩阵,占用的内存或者显存较大。可以通过设置batch的大小来降低内存或者显存占用。函数定义如下所示:
x : array,输入矩阵
a : float,待替换元素取值下限
b : float,待替换元素取值上限
batch:设置距离矩阵一次操作最多填充的数量,设置较小的值则内存或显存较小
- def nearest_fill_batch(x, a, b, batch=4):
- """
- Parameters
- ----------
- x : array,输入矩阵
- a : float,待替换元素取值下限
- b : float,待替换元素取值上限
- batch:设置距离矩阵一次操作最多填充的数量,设置较小的值则内存或显存较小
- Returns
- -------
- x : array,替换后矩阵
- """
- x = x.copy()
- index_r = np.array(np.where((x>=a) & (x <=b))).T
- index_t = np.array(np.where((x<a) | (x >b))).T
- index_r1 = np.expand_dims(index_r, 1)
- N = index_r.shape[0] // batch
- for i in range(N):
- index_r2 = index_r1[i*batch:(i+1)*batch]
- distances = index_r2 - index_t
- distances = distances ** 2
- distances = np.sum(distances, -1)
- pos = np.argmin(distances, 1)
- x[index_r2[:, 0, 0], index_r2[:, 0, 1]] = x[index_t[pos][:, 0], index_t[pos][:, 1]]
- if index_r.shape[0] % batch > 0:
- index_r2 = index_r1[(index_r.shape[0]- index_r.shape[0] % batch):]
- distances = index_r2 - index_t
- distances = distances ** 2
- distances = np.sum(distances, -1)
- pos = np.argmin(distances, 1)
- x[index_r2[:, 0, 0], index_r2[:, 0, 1]] = x[index_t[pos][:, 0], index_t[pos][:, 1]]
- return x
前两种方法都会计算每个待替换元素与剩余所有非替换元素的位置距离,计算量大,且内存或显存占用大。这种方法适合维度较小的矩阵元素替换。对于较大维度的矩阵,以上两种方法的计算时间也会显著增加。第三种方法,仅仅计算其中位置距离较小的若干个元素的距离矩阵,运行速度大大提升。函数定义如下所示:
x : array,输入矩阵
a : float,待替换元素取值下限
b : float,待替换元素取值上限
- def nearest_fill_fast(x, a, b):
- """
- Parameters
- ----------
- x : array,输入矩阵
- a : float,待替换元素取值下限
- b : float,待替换元素取值上限
- Returns
- -------
- y : array,替换后矩阵
- """
- y = x.copy()
- h, w = x.shape[:2]
- index_r = np.array(np.where((x>=a) & (x <=b))).T
- index_t = np.array(np.where((x<a) | (x >b))).T
- for ir in index_r:
- i, j = ir
- for k in range(3, max(w, h)):
- kernel = [k, k]
- x1 = max(j-kernel[0]//2, 0)
- x2 = min(x1 + kernel[0], w)
- y1 = max(i-kernel[1]//2, 0)
- y2 = min(y1 + kernel[1], h)
- x_tmp = x[y1:y2, x1:x2]
- index_t = np.array(np.where((x_tmp<a) | (x_tmp >b))).T
- if len(index_t) < 1:
- continue
- index_t += [y1, x1]
- d = (ir - index_t) ** 2
- d = d[:, 0] + d[:, 1]
- p = index_t[np.argmin(d)]
- y[ir[0], ir[1]] = x[p[0], p[1]]
- break
- return y

耗时测试结果:

更多三维、二维感知算法和金融量化分析算法请关注“乐乐感知学堂”微信公众号,并将持续进行更新。