类似 einsum 的 gufunc 签名中问号的确切含义是什么?

What is the precise meaning of question marks in an einsum-like gufunc signature?

例如:

np.arange(3)@np.arange(2)
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
# ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 3)

请注意:我知道出了什么问题以及错误消息的含义。我只对精确的语法感兴趣。问号表示什么?

这些表示允许缺失的维度。如果缺少这样一个维度,它将被视为长度为 1,但相应的维度将从输出中删除。

在matmul签名(n?,k),(k,m?)->(n?,m?)中,第一个参数的第一个维度和第二个参数的第二个维度都允许缺失。如果是,第一个参数将被视为行向量,第二个参数将被视为列向量。

引用 NEP 20 — Expansion of Generalized Universal Function Signatures,

  1. Possibly missing dimensions. This part is almost entirely driven by the wish to wrap matmul in a gufunc. matmul stands for matrix multiplication, and if it did only that, it could be covered with the signature (m,n),(n,p)->(m,p). However, it has special cases for when a dimension is missing, allowing either argument to be treated as a single vector, with the function thus becoming, effectively, vector-matrix, matrix-vector, or vector-vector multiplication (but with no broadcasting). To support this, it is suggested to allow postfixing a dimension name with a question mark to indicate that the dimension does not necessarily have to be present.

    With this addition, the signature for matmul can be expressed as (m?,n),(n,p?)->(m?,p?). This indicates that if, e.g., the second operand has only one dimension, for the purposes of the elementary function it will be treated as if that input has core shape (n, 1), and the output has the corresponding core shape of (m, 1). The actual output array, however, has the flexible dimension removed, i.e., it will have shape (..., m). Similarly, if both arguments have only a single dimension, the inputs will be presented as having shapes (1, n) and (n, 1) to the elementary function, and the output as (1, 1), while the actual output array returned will have shape (). In this way, the signature allows one to use a single elementary function for four related but different signatures, (m,n),(n,p)->(m,p), (n),(n,p)->(p), (m,n),(n)->(m) and (n),(n)->().