为了将矩阵 X
的行归一化为单位长度,我通常使用以下方法:
X /= np.linalg.norm(X, axis=1, keepdims=True)
尝试为算法优化此操作时,我很惊讶地发现在我的机器上写出规范化大约快了40%。
X /= np.sqrt(X[:,0]**2+X[:,1]**2+X[:,2]**2)[:,np.newaxis]
X /= np.sqrt(sum(X[:,i]**2 for i in range(X.shape[1])))[:,np.newaxis]
为什么会出现这种情况?在 np.linalg.norm()
中性能损失在哪里?
import numpy as np
X = np.random.randn(10000,3)
%timeit X/np.linalg.norm(X,axis=1, keepdims=True)
# 276 µs ± 4.55 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit X/np.sqrt(X[:,0]**2+X[:,1]**2+X[:,2]**2)[:,np.newaxis]
# 169 µs ± 1.38 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit X/np.sqrt(sum(X[:,i]**2 for i in range(X.shape[1])))[:,np.newaxis]
# 185 µs ± 4.17 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
我观察到这个问题在MacbookPro 2015上使用OpenBLAS支持的
(1) python3.6 + numpy v1.17.2
和(2) python3.9 + numpy v1.19.3
中存在。我认为这不是this post的重复,那篇文章涉及矩阵范数,而这篇文章是关于向量的L2范数。