我想为 10060 个记录/点创建一个距离接近矩阵,其中每个记录/点都具有 23 属性,并使用欧氏距离作为度量标准。我使用嵌套的for循环编写代码来计算每个点之间的距离(导致(n(n-1))/ 2)计算)。花了很长时间(大约8分钟)。当我使用cdist时,花费的时间要少得多(仅3秒!!! )。当我查看源代码时,cdist还使用嵌套的for循环,而且它进行 n ^ 2 次计算(大于我的逻辑所做的比较次数)。 是什么让cdist更快地执行并提供正确的输出? ,请帮助我理解。预先感谢。
答案 0 :(得分:1)
您在哪里阅读源代码? python code调用(如果在默认的<T>
情况下一直沿用)c代码
metric='euclidean'
static NPY_INLINE int
cdist_seuclidean(const double *XA, const double *XB, const double *var,
double *dm, const npy_intp num_rowsA, const npy_intp num_rowsB,
const npy_intp num_cols)
{
npy_intp i, j;
for (i = 0; i < num_rowsA; ++i) {
const double *u = XA + (num_cols * i);
for (j = 0; j < num_rowsB; ++j, ++dm) {
const double *v = XB + (num_cols * j);
*dm = seuclidean_distance(var, u, v, num_cols);
}
}
return 0;
}
在哪里
seuclidean_distance
因此,它实际上是一个三重循环,但这是高度优化的C代码。 Python static NPY_INLINE double
seuclidean_distance(const double *var, const double *u, const double *v,
const npy_intp n)
{
double s = 0.0;
npy_intp i;
for (i = 0; i < n; ++i) {
const double d = u[i] - v[i];
s += (d * d) / var[i];
}
return sqrt(s);
}
循环很慢,它们会占用大量开销,并且决不能与numpy数组一起使用,因为scipy / numpy可以以python的方式利用for
对象中保存的基础内存数据不能。