Tom*_*Tom 8 python numpy dot-product
我正在尝试计算股票投资组合的一阶和二阶矩(即预期回报和标准差)。
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)
Run Code Online (Sandbox Code Playgroud)
所以通常预期回报计算为
(x1,...,xn' * (R1,...,Rn)
x1,...,xn 是具有约束的权重,所有权重必须加起来为 1,' 表示向量已转置。
现在我有点想知道 numpy dot 函数,因为
returns = np.dot(expected_returns_annual, weights)
Run Code Online (Sandbox Code Playgroud)
和
returns = np.dot(expected_returns_annual, weights.T)
Run Code Online (Sandbox Code Playgroud)
给出相同的结果。
我还测试了 weights.T 和 weights 的形状。
weights.shape
Out[58]: (5,)
weights.T.shape
Out[59]: (5,)
Run Code Online (Sandbox Code Playgroud)
weights.T 的形状应该是 (,5) 而不是 (5,),但 numpy 将它们显示为相等(我也尝试过 np.transpose,但结果相同)
有人知道为什么 numpy 会这样吗?在我看来, np.dot 乘积会自动塑造向量正确的原因,以便向量乘积运行良好。那是对的吗?
最好的问候汤姆
tel*_*tel 13
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
Run Code Online (Sandbox Code Playgroud)
您可以向自己证明,这给出了np.dot与此相同的答案assert:
assert expected_returns_annual @ weights == expected_returns_annual.dot(weights)
Run Code Online (Sandbox Code Playgroud)
从概念上讲,@通过将两个1D数组提升为适当的2D数组来处理这种情况(尽管实现不一定这样做)。例如,如果您有xwith shape(N,)和ywith shape (M,),如果您这样做,x @ y则形状将被提升为:
x.shape == (1, N)
y.shape == (M, 1)
Run Code Online (Sandbox Code Playgroud)
matmul/ 的完全行为@
- 如果两个参数都是二维的,它们将像传统矩阵一样相乘。
- 如果任一参数为 ND,N > 2,则将其视为驻留在最后两个索引中的矩阵堆栈并相应地广播。
- 如果第一个参数是 1-D,则通过在其维度前添加 1 将其提升为矩阵。在矩阵乘法之后,前面的 1 被删除。
- 如果第二个参数是 1-D,则通过在其维度上附加 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)但有效(虽然比使用更冗长@)。当您确实需要扩展代码以处理许多矩阵乘法而不是一个矩阵乘法时,NDfor的情况@是概念上简单的小写的泛化/向量化D。