python - 基于另一个相似矩阵对矩阵进行排序的 Numpyic 方法
问题描述
假设我有一个Y
从 0 到 10 的随机浮点数矩阵,其形状为(10, 3)
:
import numpy as np
np.random.seed(99)
Y = np.random.uniform(0, 10, (10, 3))
print(Y)
输出:
[[6.72278559 4.88078399 8.25495174]
[0.31446388 8.08049963 5.6561742 ]
[2.97622499 0.46695721 9.90627399]
[0.06825733 7.69793028 7.46767101]
[3.77438936 4.94147452 9.28948392]
[3.95454044 9.73956297 5.24414715]
[0.93613093 8.13308413 2.11686786]
[5.54345785 2.92269116 8.1614236 ]
[8.28042566 2.21577372 6.44834702]
[0.95181622 4.11663239 0.96865261]]
我现在得到一个X
具有相同形状的矩阵,可以看作是通过向Y
行添加小噪声然后改组而获得的:
X = np.random.normal(Y, scale=0.1)
np.random.shuffle(X)
print(X)
输出:
[[ 4.04067271 9.90959141 5.19126867]
[ 5.59873104 2.84109306 8.11175891]
[ 0.10743952 7.74620162 7.51100441]
[ 3.60396019 4.91708372 9.07551354]
[ 0.9400948 4.15448712 1.04187208]
[ 2.91884302 0.47222752 10.12700505]
[ 0.30995155 8.09263241 5.74876947]
[ 1.11247872 8.02092335 1.99767444]
[ 6.68543696 4.8345869 8.17330513]
[ 8.38904822 2.11830619 6.42013343]]
现在我想X
根据Y
row对矩阵进行排序。我已经知道每对匹配的行中的每对列值之间的差异不超过 0.5 的容差。我设法编写了以下代码,并且运行良好。
def sort_X_by_Y(X, Y, tol):
idxs = [next(i for i in range(len(X)) if all(abs(X[i] - row) <= tol)) for row in Y]
return X[idxs]
print(sort_X_by_Y(X, Y, tol=0.5))
输出:
[[ 6.68543696 4.8345869 8.17330513]
[ 0.30995155 8.09263241 5.74876947]
[ 2.91884302 0.47222752 10.12700505]
[ 0.10743952 7.74620162 7.51100441]
[ 3.60396019 4.91708372 9.07551354]
[ 4.04067271 9.90959141 5.19126867]
[ 1.11247872 8.02092335 1.99767444]
[ 5.59873104 2.84109306 8.11175891]
[ 8.38904822 2.11830619 6.42013343]
[ 0.9400948 4.15448712 1.04187208]]
但是,实际上我正在对(1000, 3)
矩阵进行排序,而我的代码太慢了。我觉得应该有更多 numpyic 的方式来编码。有什么建议么?
解决方案
这是您的算法的矢量化版本。对于 1000 个样本,它的运行速度比您的实现快约 26.5 倍。但是会创建一个额外的带有形状的布尔数组(1000,1000,3)
。行有可能在容差范围内具有相似的值,并且选择了错误的行。
tol = .5
X[(np.abs(Y[:, np.newaxis] - X) <= tol).all(2).argmax(1)]
输出
array([[ 6.68543696, 4.8345869 , 8.17330513],
[ 0.30995155, 8.09263241, 5.74876947],
[ 2.91884302, 0.47222752, 10.12700505],
[ 0.10743952, 7.74620162, 7.51100441],
[ 3.60396019, 4.91708372, 9.07551354],
[ 4.04067271, 9.90959141, 5.19126867],
[ 1.11247872, 8.02092335, 1.99767444],
[ 5.59873104, 2.84109306, 8.11175891],
[ 8.38904822, 2.11830619, 6.42013343],
[ 0.9400948 , 4.15448712, 1.04187208]])
更强大的 L1 范数解决方案
X[np.abs(Y[:, np.newaxis] - X).sum(2).argmin(1)]
或 L2 范数
X[((Y[:, np.newaxis] - X)**2).sum(2).argmin(1)]
推荐阅读
- azure-sql-database - 使用多个 OrderBy 时应该创建哪个索引
- blockchain - 将 UI 选定字段转换为 Solidity 智能合约
- excel - 如何在将文本格式化为大写时导入文本文件
- javascript - 如何显示两个水平滚动菜单栏
- java - 我可以将用户输入从一个包拉到另一个包吗?
- windows - 在 windows 上安装 ocaml 失败
- calendar - 如何使用 MS Graph API 读取公共日历
- survey - 使用 SurveyMonkey 是否可以为问题提供规范名称?
- mongodb - mongo 索引键限制与索引名称长度
- python - 如何修复 pip:无法导入名称 main?(已安装 pip 并且 pip3 工作正常)