如何在NumPy中优雅地规范化向量列表?
下面是一个不起作用的例子:
from numpy import *
vectors = array([arange(10), arange(10)]) # All x's, then all y's
norms = apply_along_axis(linalg.norm, 0, vectors)
# Now, what I was expecting would work:
print vectors.T / norms # vectors.T has 10 elements, as does norms, but this does not work
最后一个操作产生“形状不匹配:对象不能广播到单个形状”。
如何使用NumPy优雅地对vectors
中的2D向量进行标准化?
编辑:为什么在向norms
添加维度时上面的操作不起作用(根据我下面的答案)?
发布于 2010-05-18 00:21:10
好吧,除非我漏掉了什么,这是有效的:
vectors / norms
你的建议中的问题是广播规则。
vectors # shape 2, 10
norms # shape 10
形状的长度不一样!因此,规则是首先在left上将小形状扩展一
norms # shape 1,10
您可以通过调用以下命令手动完成此操作:
vectors / norms.reshape(1,-1) # same as vectors/norms
如果要计算vectors.T/norms
,则必须手动进行整形,如下所示:
vectors.T / norms.reshape(-1,1) # this works
发布于 2012-10-04 00:24:12
计算大小
我遇到了这个问题,并对你的规范化方法感到好奇。我使用一种不同的方法来计算大小。注意:我通常也会计算最后一个索引(在本例中是行,而不是列)的规范。
magnitudes = np.sqrt((vectors ** 2).sum(-1))[..., np.newaxis]
然而,通常情况下,我只是这样标准化:
vectors /= np.sqrt((vectors ** 2).sum(-1))[..., np.newaxis]
时间比较
我运行了一个测试来比较时间,发现我的方法快了相当多,但Freddie Witherdon的建议更快。
import numpy as np
vectors = np.random.rand(100, 25)
# OP's
%timeit np.apply_along_axis(np.linalg.norm, 1, vectors)
# Output: 100 loops, best of 3: 2.39 ms per loop
# Mine
%timeit np.sqrt((vectors ** 2).sum(-1))[..., np.newaxis]
# Output: 10000 loops, best of 3: 13.8 us per loop
# Freddie's (from comment below)
%timeit np.sqrt(np.einsum('...i,...i', vectors, vectors))
# Output: 10000 loops, best of 3: 6.45 us per loop
但要注意,正如这篇StackOverflow answer所指出的那样,einsum
没有进行一些安全检查,因此您应该确保vectors
的dtype
足以足够准确地存储幅度的平方。
发布于 2010-05-18 00:17:33
好的:NumPy的数组形状广播将维度添加到数组形状的左侧,而不是右侧。但是,可以指示NumPy在norms
数组的右侧添加一个维度:
print vectors.T / norms[:, newaxis]
确实起作用了!
https://stackoverflow.com/questions/2850743
复制相似问题