<p>简而言之,你可以使用52个字母中的任何一个(上下)。这是英语中所有的字母。任何更漂亮的坐标轴名称都必须映射到这52个坐标轴上,或是一组等效的数字。实际上,在任何一个<code>einsum</code>调用中,您都希望使用这52个值的一小部分。在</p>
<hr/>
<p><code>@kennytm</code>建议使用替代输入语法。一些样本表明这不是一个解决方案。26仍然是实际限制(尽管有可疑的错误消息)。在</p>
<pre><code>In [258]: np.einsum(np.ones((2,3)),[0,20],np.ones((3,4)),[20,2],[0,2])
Out[258]:
array([[ 3., 3., 3., 3.],
[ 3., 3., 3., 3.]])
In [259]: np.einsum(np.ones((2,3)),[0,27],np.ones((3,4)),[27,2],[0,2])
-
ValueError Traceback (most recent call last)
<ipython-input-259-ea61c9e50d6a> in <module>()
> 1 np.einsum(np.ones((2,3)),[0,27],np.ones((3,4)),[27,2],[0,2])
ValueError: invalid subscript '|' in einstein sum subscripts string, subscripts must be letters
In [260]: np.einsum(np.ones((2,3)),[0,100],np.ones((3,4)),[100,2],[0,2])
-
ValueError Traceback (most recent call last)
<ipython-input-260-ebd9b4889388> in <module>()
> 1 np.einsum(np.ones((2,3)),[0,100],np.ones((3,4)),[100,2],[0,2])
ValueError: subscript is not within the valid range [0, 52]
</code></pre>
<p>我不太清楚为什么你需要超过52个字母(大写和小写),但我确定你需要做一些映射。您不希望一次使用超过52个轴编写<code>einsum</code>字符串。结果迭代器将太大(对于内存或时间)。在</p>
<p>我在描绘一些映射函数,可以用作:</p>
^{pr2}$
<hr/>
<p><a href="https://github.com/hpaulj/numpy-einsum/blob/master/einsum_py.py" rel="nofollow">https://github.com/hpaulj/numpy-einsum/blob/master/einsum_py.py</a></p>
<p>{cda>是Python的版本。粗略地说,<code>einsum</code>解析下标字符串,创建一个可以在<code>np.nditer</code>中使用的<code>op_axes</code>列表来设置所需的积和计算。通过这段代码,我可以了解翻译是如何完成的:</p>
<p>从<code>__name__</code>块中的一个示例:</p>
<pre><code> label_str, op_axes = parse_subscripts('ik,kj->ij', Labels([A.ndim,B.ndim]))
print op_axes
# [[0, -1, 1], [-1, 1, 0], [0, 1, -1]] fine
# map (4,newaxis,3)(newaxis,3,2)->(4,2,newaxis)
print sum_of_prod([A,B],op_axes)
</code></pre>
<p>您的示例,完整的诊断输出是</p>
<pre><code>In [275]: einsum_py.parse_subscripts('ijk,jklm->ijklm',einsum_py.Labels([3,4]))
jklm
{'counts': {105: 1, 106: 2, 107: 2, 108: 1, 109: 1},
'strides': [],
'num_labels': 5,
'min_label': 105,
'nop': 2,
'ndims': [3, 4],
'ndim_broadcast': 0,
'shapes': [],
'max_label': 109}
[('ijk', [105, 106, 107], 'NONE'),
('jklm', [106, 107, 108, 109], 'NONE')]
('ijklm', [105, 106, 107, 108, 109], 'NONE')
iter labels: [105, 106, 107, 108, 109],'ijklm'
op_axes [[0, 1, 2, -1, -1], [-1, 0, 1, 2, 3], [0, 1, 2, 3, 4]]
Out[275]:
(<einsum_py.Labels at 0xb4f80cac>,
[[0, 1, 2, -1, -1], [-1, 0, 1, 2, 3], [0, 1, 2, 3, 4]])
</code></pre>
<p>使用<code>'ajk,jkzZ->ajkzZ'</code>会更改标签,但会导致相同的<code>op_axes</code>。在</p>
<hr/>
<p>这是翻译功能的初稿。它应该适用于任何列表列表(哈希项):</p>
<pre><code>def translate(ll):
mset=set()
for i in ll:
mset.update(i)
dd={k:v for v,k in enumerate(mset)}
x=[''.join([chr(dd[i]+97) for i in l]) for l in ll]
# ['cdb', 'dbea', 'cdbea']
y=','.join(x[:-1])+'->'+x[-1]
# 'cdb,dbea->cdbea'
In [377]: A=np.ones((3,1,2),int)
In [378]: B=np.ones((1,2,4,3),int)
In [380]: ll=[list(i) for i in ['ijk','jklm','ijklm']]
In [381]: y=translate(ll)
In [382]: y
Out[382]: 'cdb,dbea->cdbea'
In [383]: np.einsum(y,A,B).shape
Out[383]: (3, 1, 2, 4, 3)
</code></pre>
<p>使用<code>set</code>映射索引对象意味着最终的索引字符是无序的。只要你指定不应该成为问题的RHS。我也忽略了<code>ellipsis</code>。在</p>
<p>==============</p>
<p><code>einsum</code>输入的列表版本被转换为<code>einsum_list_to_subscripts()</code>(在<code>numpy/core/src/multiarray/multiarraymodule.c</code>)中的下标字符串版本。它将<code>ELLIPSIS</code>替换为“…”。如果<code>( s < 0 || s > 2*26)</code>,其中<code>s</code>是其中一个子列表中的一个数字,则它将引发[0,52]错误消息。并使用</p>
<pre><code> if (s < 26) {
subscripts[subindex++] = 'A' + s;
}
else {
subscripts[subindex++] = 'a' + s;
</code></pre>
<p>但是看起来第二个案子不起作用了,我得到了26个这样的错误。在</p>
<pre><code>ValueError: invalid subscript '{' in einstein sum subscripts string, subscripts must be letters
</code></pre>
<p>如果<code>s>26</code>,则{<cd20>}是错误的:</p>
<pre><code>In [424]: ''.join([chr(ord('A')+i) for i in range(0,26)])
Out[424]: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
In [425]: ''.join([chr(ord('a')+i) for i in range(0,26)])
Out[425]: 'abcdefghijklmnopqrstuvwxyz'
In [435]: ''.join([chr(ord('a')+i) for i in range(26,52)])
Out[435]: '{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94'
</code></pre>
<p>这<code>'a'+s</code>是错误的;应该是:</p>
<pre><code>In [436]: ''.join([chr(ord('a')+i-26) for i in range(26,52)])
Out[436]: 'abcdefghijklmnopqrstuvwxyz'
</code></pre>
<p>我提交了<a href="https://github.com/numpy/numpy/issues/7741" rel="nofollow">https://github.com/numpy/numpy/issues/7741</a></p>
<p>这个错误的存在表明子列表格式并不常见,并且在该列表中使用大数字的频率更低。在</p>