python - np.dot 会自动转置向量吗?
问题描述
我正在尝试计算股票投资组合的一阶和二阶矩(即预期收益和标准差)。
expected_returns_annual
Out[54]:
ticker
adj_close CNP 0.091859
F -0.007358
GE 0.095399
TSLA 0.204873
WMT -0.000943
dtype: float64
type(expected_returns_annual)
Out[55]: pandas.core.series.Series
weights = np.random.random(num_assets)
weights /= np.sum(weights)
returns = np.dot(expected_returns_annual, weights)
因此,通常预期收益由下式计算
(x1,...,xn' * (R1,...,Rn)
其中 x1,...,xn 是具有所有权重必须总和为 1 的约束的权重,并且 ' 表示向量已转置。
现在我对 numpy dot 函数有点疑惑,因为
returns = np.dot(expected_returns_annual, weights)
和
returns = np.dot(expected_returns_annual, weights.T)
给出相同的结果。
我还测试了 weights.T 和 weights 的形状。
weights.shape
Out[58]: (5,)
weights.T.shape
Out[59]: (5,)
weights.T 的形状应该是 (,5) 而不是 (5,),但是 numpy 将它们显示为相等(我也尝试过 np.transpose,但结果相同)
有人知道为什么 numpy 会这样吗?在我看来, np.dot 产品会自动将矢量塑造正确的原因,以便矢量产品运行良好。那是对的吗?
最好的问候汤姆
解决方案
的语义np.dot
不是很好
正如 Dominique Paul 指出的那样,np.dot
根据输入的形状,它的行为非常不同。更令人困惑的是,正如 OP 在他的问题中指出的那样,鉴于这weights
是一个一维数组,np.array_equal(weights, weights.T)
是True
(array_equal
测试值和形状的相等性)。
建议:改用或np.matmul
等效的@
如果您是刚开始使用 Numpy 的人,我对您的建议是np.dot
完全放弃。根本不要在你的代码中使用它。而是使用np.matmul
,或等效的运算符@
。的行为@
比 的更可预测np.dot
,同时仍然便于使用。例如,对于1D
代码中的两个数组,您会得到相同的点积,如下所示:
returns = expected_returns_annual @ weights
您可以向自己证明,这给出了np.dot
与此相同的答案assert
:
assert expected_returns_annual @ weights == expected_returns_annual.dot(weights)
从概念上讲,@
通过将两个1D
数组提升为适当的数组来处理这种情况2D
(尽管实现不一定这样做)。例如,如果你有x
with shape(N,)
和y
with shape (M,)
,如果你这样做x @ y
,形状将被提升为:
x.shape == (1, N)
y.shape == (M, 1)
matmul
/的完整行为@
以下是文档对matmul
/@
和输入/输出形状的看法:
- 如果两个参数都是二维的,它们会像传统矩阵一样相乘。
- 如果任一参数为 ND,N > 2,则将其视为驻留在最后两个索引中的矩阵堆栈并相应地广播。
- 如果第一个参数是一维的,则通过在其维度前添加 1 将其提升为矩阵。在矩阵乘法之后,前面的 1 被删除。
- 如果第二个参数是一维的,则通过在其维度上附加 1 将其提升为矩阵。在矩阵乘法之后,附加的 1 被删除。
注意:使用@
over的参数dot
正如 hpaulj 在评论中指出的那样,对于np.array_equal(x.dot(y), x @ y)
所有这些都是或数组。那么为什么我(以及你为什么要)更喜欢呢?我认为使用的最佳论据是它有助于以小而重要的方式改进您的代码:x
y
1D
2D
@
@
@
显式地是一个矩阵乘法运算符。如果是标量,x @ y
将引发错误,而假设您实际上只是想要元素乘法。这可能会导致难以本地化的错误,其中默默地返回垃圾结果(我个人遇到过这种错误)。因此,允许您明确说明自己对一行代码行为的意图。y
dot
dot
@
因为
@
是一个操作符,它有一些很好的简短语法可以将各种序列类型强制转换为数组,而不必显式地转换它们。例如,[0,1,2] @ np.arange(3)
是有效的语法。- 公平地说,虽然
[0,1,2].dot(arr)
显然无效,np.dot([0,1,2], arr)
但它是有效的(尽管比 using 更冗长@
)。
- 公平地说,虽然
当你确实需要扩展你的代码来处理许多矩阵乘法而不是一个矩阵乘法时,
ND
例子@
是小写的概念上简单的泛化/向量化D
。
推荐阅读
- arrays - 这个程序如何在 C 中使用 malloc 创建一个二维数组
- java - “无法访问包 java.sql。” 在日食
- python - 从 React Native 调用 AWS Python Lambda 函数
- pine-script - 计算 Ema 交叉距离
- c# - 永远不会分配给,并且将始终具有其默认值 0
- android - Android 如何改进我的应用程序依赖项
- docker - 如何获取 docker 镜像层的大小
- javascript - 仅当 iframe 包含特定文本时才显示 div
- java - 从 HashSet 中提取整数
- mysql - 如何在 SQL 中选择具有 MIN(DateTime 列)、GROUP 由另一列和 DISTINCT 另一列的行?