np.dot是否会自动转置向量? [英] Does np.dot automatically transpose vectors?

查看:517
本文介绍了np.dot是否会自动转置向量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试计算股票投资组合的一阶和二阶矩(即预期收益和标准差).

I am trying to calculate the first and second order moments for a portfolio of stocks (i.e. expected return and standard deviation).

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' * (R1,...,Rn)

具有x1,...,xn的权重具有所有权重之和必须等于1的约束,并且'表示向量已转置.

with x1,...,xn are weights with a constraint that all the weights have to sum up to 1 and ' means that the vector is transposed.

现在我对numpy点函数有些疑惑,因为

Now I am wondering a bit about the numpy dot function, because

returns = np.dot(expected_returns_annual, weights)

returns = np.dot(expected_returns_annual, weights.T)

给出相同的结果.

我还测试了重物的形状T和重物.

I tested also the shape of weights.T and weights.

weights.shape
Out[58]: (5,)
weights.T.shape
Out[59]: (5,)

weights.T的形状应该是(,5)而不是(5,),但是numpy将它们显示为相等(我也尝试过np.transpose,但结果相同)

The shape of weights.T should be (,5) and not (5,), but numpy displays them as equal (I also tried np.transpose, but there is the same result)

有人知道为什么numpy会这样吗?在我看来,np.dot乘积会自动调整向量的形状,以使向量乘积很好地工作.正确吗?

Does anybody know why numpy behave this way? In my opinion the np.dot product automatically shape the vector the right why so that the vector product work well. Is that correct?

最诚挚的问候 汤姆

推荐答案

np.dot的语义不是很好

如Dominique Paul所指出的,np.dot具有非常不同的行为,具体取决于输入的形状.正如OP在他的问题中指出的那样,更令人困惑的是,假设weights是一维数组,np.array_equal(weights, weights.T)True(array_equal测试值和形状是否相等).

The semantics of np.dot are not great

As Dominique Paul points out, np.dot has very heterogenous behavior depending on the shapes of the inputs. Adding to the confusion, as the OP points out in his question, given that weights is a 1D array, np.array_equal(weights, weights.T) is True (array_equal tests for equality of both value and shape).

如果您只是刚开始使用Numpy的人,我对您的建议是完全放弃np.dot.根本不要在代码中使用它.而是使用np.matmul或等效的运算符@. @的行为比np.dot的行为更可预测,同时仍易于使用.例如,对于代码中的两个1D数组,您将获得相同的点积,如下所示:

If you are someone just starting out with Numpy, my advice to you would be to ditch np.dot completely. Don't use it in your code at all. Instead, use np.matmul, or the equivalent operator @. The behavior of @ is more predictable than that of np.dot, while still being convenient to use. For example, you would get the same dot product for the two 1D arrays you have in your code like so:

returns = expected_returns_annual @ weights

您可以证明自己,此assert给出的答案与np.dot相同:

You can prove to yourself that this gives the same answer as np.dot with this assert:

assert expected_returns_annual @ weights == expected_returns_annual.dot(weights)

从概念上讲,@通过将两个1D数组提升为适当的2D数组来处理这种情况(尽管实现不一定要这样做).例如,如果您的x形状为(N,),而y的形状为(M,),那么如果您执行x @ y,则这些形状将被提升为:

Conceptually, @ handles this case by promoting the two 1D arrays to appropriate 2D arrays (though the implementation doesn't necessarily do this). For example, if you have x with shape (N,) and y with shape (M,), if you do x @ y the shapes will be promoted such that:

x.shape == (1, N)
y.shape == (M, 1)

matmul/@

的完整行为

以下是文档必须说一下matmul/@以及输入/输出的形状:

Complete behavior of matmul/@

Here's what the docs have to say about matmul/@ and the shapes of inputs/outputs:

  • 如果两个参数都是二维的,它们将像常规矩阵一样相乘.
  • 如果任一自变量为N-D,N> 2,则将其视为位于最后两个索引中并相应广播的一组矩阵.
  • 如果第一个参数是1-D,则通过在其尺寸前面加1来将其提升为矩阵.矩阵相乘后,前面的1被删除.
  • 如果第二个自变量是1-D,则通过在其尺寸后附加1来将其提升为矩阵.矩阵相乘后,附加的1被删除.
  • If both arguments are 2-D they are multiplied like conventional matrices.
  • If either argument is N-D, N > 2, it is treated as a stack of matrices residing in the last two indexes and broadcast accordingly.
  • If the first argument is 1-D, it is promoted to a matrix by prepending a 1 to its dimensions. After matrix multiplication the prepended 1 is removed.
  • If the second argument is 1-D, it is promoted to a matrix by appending a 1 to its dimensions. After matrix multiplication the appended 1 is removed.

注意:在dot

上使用@的参数

正如hpaulj在注释中指出的,对于所有1D2D数组的xynp.array_equal(x.dot(y), x @ y).那么,为什么我(为什么您也应该)更喜欢@?我认为使用@的最佳论据是它有助于以小而有意义的方式改进您的代码:

Notes: the arguments for using @ over dot

As hpaulj points out in the comments, np.array_equal(x.dot(y), x @ y) for all x and y that are 1D or 2D arrays. So why do I (and why should you) prefer @? I think the best argument for using @ is that it helps to improve your code in small but significant ways:

  • @明确是矩阵乘法运算符.如果y是标量,则x @ y将引发错误,而dot将假设您实际上只是想按元素乘法.这可能会导致难以定位的错误,其中dot会默默地返回垃圾结果(我亲自遇到了该错误).因此,@允许您明确说明自己对代码行行为的意图.

  • @ is explicitly a matrix multiplication operator. x @ y will raise an error if y is a scalar, whereas dot will make the assumption that you actually just wanted elementwise multiplication. This can potentially result in a hard-to-localize bug in which dot silently returns a garbage result (I've personally run into that one). Thus, @ allows you to be explicit about your own intent for the behavior of a line of code.

由于@是运算符,它具有一些不错的短语法,用于将各种序列类型强制转换为数组,而不必显式转换它们.例如,[0,1,2] @ np.arange(3)是有效的语法.

Because @ is an operator, it has some nice short syntax for coercing various sequence types into arrays, without having to explicitly cast them. For example, [0,1,2] @ np.arange(3) is valid syntax.

  • 公平地说,虽然[0,1,2].dot(arr)显然无效,但np.dot([0,1,2], arr)是有效的(尽管比使用@更冗长).
  • To be fair, while [0,1,2].dot(arr) is obviously not valid, np.dot([0,1,2], arr) is valid (though more verbose than using @).

当您确实需要扩展代码以处理许多矩阵乘法而不是仅一次时,对于@ND案例在概念上是对D较低案例的简单直观的泛化/矢量化.

When you do need to extend your code to deal with many matrix multiplications instead of just one, the ND cases for @ are a conceptually straightforward generalization/vectorization of the lower-D cases.

这篇关于np.dot是否会自动转置向量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆