当前位置: 首页 > news >正文

【深度学习】张量计算:爱因斯坦求和约定|tensor系列03

在这里插入图片描述

  • 博主简介:努力学习的22级计算机科学与技术本科生一枚🌸
  • 博主主页: @Yaoyao2024
  • 往期回顾:【深度学习】详解矩阵乘法、点积,内积,外积、哈达玛积极其应用|tensor系列02
  • 每日一言🌼: “岱宗夫如何?齐鲁青未了。造化钟神秀,阴阳割昏晓。荡胸生曾云,决眦入归鸟。会当凌绝顶,一览众山小。”《望岳》—— 杜甫🌺

0、前言

爱因斯坦求和约定(Einstein Summation,简称 einsum)是一种简洁且功能强大的符号表示法,用于指定复杂的张量运算。在深度学习领域,特别是在 PyTorch 库中,torch.einsum 提供了一种灵活的方式来执行各种张量操作,例如矩阵乘法、点积、批量计算、外积、规约(reduction)、重塑(reshaping)或转置(transposing)等等。

在上篇文章中我们介绍了张量关于”积“的各种操作【深度学习】详解矩阵乘法、点积,内积,外积、哈达玛积极其应用|tensor系列02。也讲了在torch中这些操作的实现方式(各有不同)。

但是实际上,使用torch.einsum 这一个函数,就可以实现上述所有操作。它是对张量计算的一种规定,用简洁的符号来表示各种运算。

下面我们就对爱因斯坦求和约定进行学习吧。

1. 爱因斯坦求和的提出

在线性代数的各种矩阵计算,以及张量的计算中,往往会涉及到很多下标。每个元素的下标标定了一个元素的位置,像工牌号一样,可以唯一确定一个元素。

下面就是一个数学表达式的线性变换,也可以用矩阵来表示。

x 1 = a 11 y 1 + a 12 y 2 + a 13 y 3 x 2 = a 21 y 1 + a 22 y 2 + a 23 y 3 x 3 = a 31 y 1 + a 32 y 2 + a 33 y 3 \mathrm{x^1~=~a_{11}y^1+a_{12}y^2+a_{13}y^3}\\\mathrm{x^2~=~a_{21}y^1+a_{22}y^2+a_{23}y^3}\\\mathrm{x^3~=~a_{31}y^1+a_{32}y^2+a_{33}y^3} x1 = a11y1+a12y2+a13y3x2 = a21y1+a22y2+a23y3x3 = a31y1+a32y2+a33y3

在这里插入图片描述

我我们可以看到,表示线性变换的数学表达式还是相当复杂的。也没有办法能够简化一下呢?

观察表达式的每一行,我们可以发现, x x x的上标核 a a a的下标,是一样的,我们把它记为 i i i,则可以写成:

x i = a i 1 y 1 + a i 2 y 2 + a i 3 y 3 ( i = 1 , 2 , 3 ) \mathrm{x^i~=~a_{i1}y^1+a_{i2}y^2+a_{i3}y^3}_{(i=1,2,3)} xi = ai1y1+ai2y2+ai3y3(i=1,2,3)

我们发现,确实简洁了不少,但是那么多的求和,随着矩阵形状的改变,元素增大,那么得写多少个求和。

可以观察到, a a a的第二个下标核 y y y的上标是一致的。根据这个规律,爱因斯坦就地立法,提出:以下化简方式:
在这里插入图片描述

可以看到,直接把求和项写成了一项。这个约定就是:

同一项里,如果有重复指标,则自动求和。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

上面我们对爱因斯坦求和是什么,大概有了一个了解。它的提出是为了简化张量计算而做出的一个数学表达上的约定。

下面我们来详细讲解一下。

2. 爱因斯坦求和约定(Einstein Summation Convention)

爱因斯坦求和约定是阿尔伯特·爱因斯坦提出的一种简化张量运算的标记法,其核心思想是:

当表达式中出现重复的下标时,默认对这些下标进行求和。这种表示法可以省略显式的求和符号Σ,使表达式更加简洁。

基本规则:

  1. 重复下标表示求和:例如矩阵乘法 C i j = A i k B k j C_{ij}=A_{ik}B_{kj} Cij=AikBkj,k是重复下标,表示对k求和。

  2. 自由下标保留:不重复的下标会保留在结果中。决定新生成矩阵形状元素位置

  3. 哑标:重复的求和下标也称为哑标(dummy index),因为它们不出现在最终结果中

判断是否求和的依据是:

  • 同一项内重复的下标 → 求和(如 kAᵇᵢₖ Bᵇₖⱼ 中)。
  • 跨张量的相同下标 → 广播对齐(如 bAᵇᵢₖBᵇₖⱼ 中)。

    虽然 b 也重复出现,但它出现在 不同张量的相同位置AᵇᵢₖBᵇₖⱼ 的第一个下标都是 b),表示按批次独立计算,而非求和。

优势

  • 简洁表达复杂的张量运算

  • 直观展示张量运算的维度变化

  • 统一表示多种线性代数运算

3. torch.einsum()函数

PyTorch中的torch.einsum()函数实现了爱因斯坦求和约定,可以高效地执行各种张量运算。

3.0 函数介绍

函数签名:

torch.einsum(equation, *operands)
  • equation: 描述运算的字符串,使用逗号分隔输入张量的下标,箭头后是输出下标
  • operands: 输入张量序列

基本语法规则:

  1. 输入张量的下标用逗号分隔
  2. 箭头->后面是输出张量的下标
  3. 重复下标表示求和(收缩)
  4. 省略箭头和输出下标时,按输入下标顺序输出所有不重复的下标

...的作用:

场景使用 ...显式写法
基本矩阵乘'...ij,...jk->...ik''bij,bjk->bik'
4D输入同上,自动适配'nbij,nbjk->nbik'
向量点积'...i,...i->...''bi,bi->b'

下面我们将在具体的张量操作中,来认识爱因斯坦求和以及torch.einsum()的使用

3.1 矩阵转置

数学表达式:
B j i = A i j B_{ji}=A_{ij} Bji=Aij

没有重复的下标出现在同一项里面,所以这里的下标表示的就是本身的含义,也就是自由下标(无哑标)。

代码:

import torchA = torch.randn(3, 4)
B = torch.einsum('ij->ji', A)  # 等同于A.T

3.2. 矩阵乘法

数学表达式:

在这里插入图片描述

代码:

import torchA = torch.tensor([[a11, a12, a13],[a21, a22, a23],[a31, a32, a33]])B = torch.tensor([[b11, b12, b13],[b21, b22, b23],[b31, b32, b33]])# 使用einsum实现矩阵乘法
C = torch.einsum('ik,kj->ij', A, B)

3.3 向量内积(点积)

数学表达式:

给定两个向量:

a = [a₁, a₂, a₃]
b = [b₁, b₂, b₃]

内积计算:

c = a₁b₁ + a₂b₂ + a₃b₃

爱因斯坦约定

c = aᵢbᵢ  (i=1,2,3)
  • 重复下标i表示求和
  • 无自由下标→输出为标量

代码:

torch.einsum实现

a = torch.tensor([a1, a2, a3])
b = torch.tensor([b1, b2, b3])
c = torch.einsum('i,i->', a, b)  # 结果为标量

计算过程可视化(从爱因斯坦表达式推出它在干嘛):

展开求和:
torch.einsum('i,i->', a, b)= aᵢbᵢ  (重复下标代表求和)= ∑aᵢbᵢ   (i=1,2,3)= a₁b₁ + a₂b₂ + a₃b₃

3.4 向量外积

数学表达式:

给定两个向量:

a = [a₁, a₂]
b = [b₁, b₂, b₃]

外积结果矩阵:

C = [a₁b₁ a₁b₂ a₁b₃][a₂b₁ a₂b₂ a₂b₃]

爱因斯坦约定

Cᵢⱼ = aᵢbⱼ  (i=1,2; j=1,2,3)
  • 无重复下标→无求和
  • 两个自由下标→输出矩阵

代码:

torch.einsum实现

a = torch.tensor([a1, a2])
b = torch.tensor([b1, b2, b3])
C = torch.einsum('i,j->ij', a, b)  # 2x3矩阵

计算过程可视化

C₁₁ = a₁b₁  C₁₂ = a₁b₂  C₁₃ = a₁b₃
C₂₁ = a₂b₁  C₂₂ = a₂b₂  C₂₃ = a₂b₃

3.5 批量矩阵乘法

数学表达式:

给定两个批量矩阵:

A形状(batch,3,4) = [ [A⁰₁₁...A⁰₁₄], ..., [A⁰₃₁...A⁰₃₄] ][ [A¹₁₁...A¹₁₄], ..., [A¹₃₁...A¹₃₄] ]...
B形状(batch,4,5) = [ [B⁰₁₁...B⁰₁₅], ..., [B⁰₄₁...B⁰₄₅] ][ [B¹₁₁...B¹₁₅], ..., [B¹₄₁...B¹₄₅] ]...

批量矩阵乘法结果:

Cᵇᵢⱼ = Σₖ Aᵇᵢₖ Bᵇₖⱼ

爱因斯坦约定

Cᵇᵢⱼ = Aᵇᵢₖ Bᵇₖⱼ  (b=1...batch; i=1,2,3; j=1...5; k=1...4)
  • 重复下标k表示求和

  • 自由下标b,i,j→输出形状(batch,3,5)

  • k 是求和下标(哑标)
    因为它出现在 同一个<张量乘法项>内 的重复维度(AᵇᵢₖBᵇₖⱼ 中的 k),表示需要沿该维度求和。

  • b 是批处理下标
    虽然 b 也重复出现,但它出现在 不同张量的相同位置AᵇᵢₖBᵇₖⱼ 的第一个下标都是 b),表示按批次独立计算,而非求和。

代码:

torch.einsum实现

A = torch.randn(10, 3, 4)  # 10个3x4矩阵
B = torch.randn(10, 4, 5)  # 10个4x5矩阵
C = torch.einsum('bik,bkj->bij', A, B)  # 输出10个3x5矩阵#也可以用...进行维度自动匹配
C = torch.einsum('...ik,...kj->bij', A, B) 

计算过程可视化:

对于每个批次b:

Cᵇ₁₁ = Aᵇ₁₁Bᵇ₁₁ + Aᵇ₁₂Bᵇ₂₁ + Aᵇ₁₃Bᵇ₃₁ + Aᵇ₁₄Bᵇ₄₁
Cᵇ₁₂ = Aᵇ₁₁Bᵇ₁₂ + Aᵇ₁₂Bᵇ₂₂ + Aᵇ₁₃Bᵇ₃₂ + Aᵇ₁₄Bᵇ₄₂
...
Cᵇ₃₅ = Aᵇ₃₁Bᵇ₁₅ + Aᵇ₃₂Bᵇ₂₅ + Aᵇ₃₃Bᵇ₃₅ + Aᵇ₃₄Bᵇ₄₅

3.6 张量缩并(Tensor Contraction)

数学表达式:

给定两个张量:

A形状(2,3,4): A₁₁₁ A₁₁₂ ... A₁₁₄A₁₂₁ ...     A₁₃₄...A₂₃₁ ...     A₂₃₄B形状(4,5,6):B₁₁₁ ...     B₁₅₆...B₄₅₁ ...     B₄₅₆

在第三个维度上缩并:

Cᵢⱼₖₗ = Σₘ Aᵢⱼₘ Bₘₖₗ

爱因斯坦约定

Cᵢⱼₖₗ = Aᵢⱼₘ Bₘₖₗ  (i=1,2; j=1,2,3; k=1...5; l=1...6; m=1...4)
  • 重复下标m表示求和
  • 自由下标i,j,k,l→输出形状(2,3,5,6)

代码:

torch.einsum实现

A = torch.randn(2, 3, 4)
B = torch.randn(4, 5, 6)
C = torch.einsum('ijm,mkl->ijkl', A, B)  # 输出2x3x5x6张量

计算过程可视化:

固定i,j,k,l(自由下标,决定新生成矩阵形状和元素的位置)时(也就是向量的点积了):

例如C₁₂₃₄ = A₁₂₁B₁₃₄ + A₁₂₂B₂₃₄ + A₁₂₃B₃₃₄ + A₁₂₄B₄₃₄

3.6 广播的元素级乘法运算

a = torch.arange(6).reshape(2, 3)
b = torch.arange(3)
result = torch.einsum('ij,j->ij', a, b)  # Broadcast and multiply
print(result)

相当于是给a的第i行第j列,与bj行做了点积,每一行都是这样。所以这个运算的效果相当于是给b做了个广播,广播成3×3然后和a作乘法了。

从这里来看,爱因斯坦求和也是可以实现广播操作的~

3.7 沿指定维度求和(Reduction)

数学表达式:

给定一个三维张量 T ∈ R 2 × 3 × 4 T\in\mathbb{R}^{2\times3\times4} TR2×3×4, 其元素表示为 T i j k T_{ijk} Tijk(其中 i = 1 , 2 , j = 1 , 2 , 3 , k = 1 , 2 , 3 , 4 i=1,2,j=1,2,3,k=1,2,3,4 i=1,2,j=1,2,3,k=1,2,3,4)。我们需要沿着第二个维度( j j j维度)进行求和,对矩阵进行压缩(Reduction),得到一个新的二维张量: S ∈ R 2 × 4 S\in\mathbb{R}^{2\times4} SR2×4,其:

S i k = ∑ j T i j k S_{ik}=\sum_jT_{ijk} Sik=jTijk

根据爱因斯坦求和约定,上述求和操作可以表示为:

S i k = T i j k ( 对  j 求和 ) S_{ik}=T_{ijk}\quad(\text{对 }j\text{ 求和}) Sik=Tijk( j 求和)

  • 输入张量 T i j k T_{ijk} Tijk(三维)
  • 输出张量 S i k S_{ik} Sik(二维)
  • 下标角色
    • i , k i, k i,k自由下标(出现在输入和输出中)
    • j j j求和下标(哑标)(仅出现在输入中)

代码:

因此,einsum 表达式为:

result = torch.einsum('ijk->ik', tensor)

3.8 注意力机制

Transformer和AlphaFold等模型中注意力机制的核心计算步骤。流程分为三个阶段:

  1. 计算原始注意力分数(Query-Key点积 + 缩放)
  2. Softmax归一化(得到注意力权重)
  3. 加权求和Value向量(生成最终输出)

1. 阶段一:计算原始注意力分数

数学表达式:

raw_attn q k = Q q ⋅ K k c = ∑ c Q q c K k c c \text{raw\_attn}_{qk} = \frac{Q_q \cdot K_k}{\sqrt{c}} = \frac{\sum_{c} Q_{qc} K_{kc}}{\sqrt{c}} raw_attnqk=c QqKk=c cQqcKkc

其中:

  • Q ∈ R q × c Q \in \mathbb{R}^{q \times c} QRq×c:查询矩阵(q个查询向量,每个维度c)
  • K ∈ R k × c K \in \mathbb{R}^{k \times c} KRk×c:键矩阵(k个键向量,每个维度c)

代码:

einsum实现

raw_attn = torch.einsum('qc,kc->qk', Q, K) / math.sqrt(Q.shape[-1])
  • 下标解析
    • qc:Q的维度(查询数×特征维度)
    • kc:K的维度(键数×特征维度)
    • ->qk:输出形状(每个查询与每个键的点积)
  • 缩放:除以 c \sqrt{c} c 防止点积值过大(梯度稳定)

计算示例:

假设:

  • Q = [ 1 2 3 4 ] , K = [ 0 1 1 0 ] , c = 2 Q=\begin{bmatrix}1&2\\3&4\end{bmatrix},K=\begin{bmatrix}0&1\\1&0\end{bmatrix},c=2 Q=[1324],K=[0110],c=2
  • 计算:
    raw_attn 00 = 1 × 0 + 2 × 1 2 = 2 2 = 2 raw_attn 01 = 1 × 1 + 2 × 0 2 = 1 2 raw_attn 10 = 3 × 0 + 4 × 1 2 = 4 2 = 2 2 raw_attn 11 = 3 × 1 + 4 × 0 2 = 3 2 \begin{aligned}&\text{raw\_attn}_{00}=\frac{1\times0+2\times1}{\sqrt{2}}=\frac2{\sqrt{2}}=\sqrt{2}\\&\text{raw\_attn}_{01}=\frac{1\times1+2\times0}{\sqrt{2}}=\frac1{\sqrt{2}}\\&\text{raw\_attn}_{10}=\frac{3\times0+4\times1}{\sqrt{2}}=\frac4{\sqrt{2}}=2\sqrt{2}\\&\text{raw\_attn}_{11}=\frac{3\times1+4\times0}{\sqrt{2}}=\frac3{\sqrt{2}}\end{aligned} raw_attn00=2 1×0+2×1=2 2=2 raw_attn01=2 1×1+2×0=2 1raw_attn10=2 3×0+4×1=2 4=22 raw_attn11=2 3×1+4×0=2 3
    最终得到 r a w _ a t t n ∈ R 2 × 2 \mathrm{raw\_attn}\in\mathbb{R}^{2\times2} raw_attnR2×2
    raw_attn = [ 2 1 2 2 2 3 2 ] \text{raw\_attn}=\begin{bmatrix}\sqrt2&\frac1{\sqrt2}\\2\sqrt2&\frac3{\sqrt2}\end{bmatrix} raw_attn=[2 22 2 12 3]

2. 阶段二:Softmax归一化

数学表达式:

attn q k = softmax ( raw_attn q ) k = exp ⁡ ( raw_attn q k ) ∑ j = 1 k exp ⁡ ( raw_attn q j ) \text{attn}_{qk} = \text{softmax}(\text{raw\_attn}_{q})_k = \frac{\exp(\text{raw\_attn}_{qk})}{\sum_{j=1}^k \exp(\text{raw\_attn}_{qj})} attnqk=softmax(raw_attnq)k=j=1kexp(raw_attnqj)exp(raw_attnqk)

给定一个查询 q q q对应的原始注意力分数向量 r a w _ a t t n q ∈ R k \mathrm{raw\_attn}_q\in\mathbb{R}^k raw_attnqRk,Softmax计算步骤如下:

数学步骤:

  1. 指数化:对每个分数取指数
    e x p _ a t t n q k = exp ⁡ ( r a w _ a t t n q k ) exp\_attn_{qk} = \exp(\mathrm{raw\_attn}_{qk}) exp_attnqk=exp(raw_attnqk)

  2. 求和:计算每一个查询q对应的所有指数分数的和

    s u m q = ∑ j = 1 k exp ⁡ ( raw_attn q j ) sum_q = \sum_{j=1}^k \exp(\text{raw\_attn}_{qj}) sumq=j=1kexp(raw_attnqj)

  3. 归一化:每个指数值除以总和
    a t t n q k = exp ⁡ ( r a w _ a t t n q k ) s u m \mathrm{attn}_{qk}=\frac{\exp(\mathrm{raw}\_\mathrm{attn}_{qk})}{\mathrm{sum}} attnqk=sumexp(raw_attnqk)

代码:

沿键维度(dim=1)归一化:每个查询对应的所有键的分数转换为概率分布

attn = torch.softmax(raw_attn, dim=1)
  • 输出性质
    • 每行和为1(概率分布)
    • 突出最大值(如输入[3,1] → 输出[0.88, 0.12]

3. 阶段三:加权求和Value向量

数学表达式:

r e s u l t q d = ∑ k = 1 K a t t n q k V k d \mathrm{result}_{qd}=\sum_{k=1}^K\mathrm{attn}_{qk}V_{kd} resultqd=k=1KattnqkVkd

  • V ∈ R k × d V\in\mathbb{R}^{k\times d} VRk×d:值矩阵(k个值向量,每个维度d)
  • 物理意义:用注意力权重对值向量加权平均

代码:

result = torch.einsum('qk,kd->qd', attn, V)
  • 下标解析
    • qk:注意力权重矩阵(查询数×键数)
    • kd:值矩阵(键数×值维度)
    • ->qd:输出形状(查询数×值维度)

计算示例:

假设:

  • a t t n = [ 0.8 0.2 0.5 0.5 ] , V = [ 1 3 2 4 ] \mathrm{attn}=\begin{bmatrix}0.8&0.2\\0.5&0.5\end{bmatrix},V=\begin{bmatrix}1&3\\2&4\end{bmatrix} attn=[0.80.50.20.5],V=[1234]
  • 计算: r e s u l t 00 = 0.8 × 1 + 0.2 × 2 = 1.2 r e s u l t 01 = 0.8 × 3 + 0.2 × 4 = 3.2 \mathrm{result}_{00}=0.8\times1+0.2\times2=1.2\\\mathrm{result}_{01}=0.8\times3+0.2\times4=3.2 result00=0.8×1+0.2×2=1.2result01=0.8×3+0.2×4=3.2

最终得到 r e s u l t ∈ R 2 × 2 \mathrm{result}\in\mathbb{R}^{2\times2} resultR2×2

4. 易错点:重复下标一定求和?

终极答案:位置决定命运(下标角色的黄金法则)

在表达式 Cᵇᵢⱼ = Aᵇᵢₖ Bᵇₖⱼ 中,下标的命运由它的出现位置决定:

1. 求和下标(哑标)的特征

  1. 必须同时出现在两个相乘的张量中
  2. 必须出现在每个张量的不同维度位置
  3. 不会出现在输出下标中

如何判断爱因斯坦表达式中的下标是否是哑标?

对于任意爱因斯坦求和表达式(单张量或多张量),求和下标必须满足

  • 必要条件:输入中出现但输出中不出现(否则是自由下标)
  • 充分条件(多张量时追加)
    • 在所有输入张量中都出现
    • 在不同张量的不同维度位置

具体来说:

  1. 单张量操作(如矩阵求和、迹运算):

    • 唯一判定标准:输入有但输出无的下标即为哑标(必须求和)。
    • 其他两个特征不适用。
  2. 多张量操作(如矩阵乘法 A i k B k j A_{ik}B_{kj} AikBkj):

    • 需同时满足:
      • 出现在所有输入张量中(特征1)
      • 在不同张量的不同维度位置(特征2)
      • 不在输出中(特征3)

k 为例:

Aᵇᵢₖ Bᵇₖⱼ↑   ↑不同位置(A的第3维,B的第2维)

k 在A中是第3个下标,在B中是第2个下标 → 满足"不同位置"条件 → 需要求和

总结表格:🌟

场景求和下标判定依据
单张量操作输入有、输出无的下标(必须求和)
多张量操作输入有(所有张量)、输出无 + 在不同张量的不同维度位置
非法情况下标在输入张量的相同位置出现,或出现在输出中却试图求和

2. 批处理下标(非求和)的特征

  • 出现在两个张量的相同维度位置
  • 必须出现在输出下标中

b 为例:

Aᵇᵢₖ Bᵇₖⱼ↑    ↑相同位置(都是第1维)

b 在A和B中都是第1个下标 → 满足"相同位置"条件 → 保持独立不求和

三维动画演示(想象这个场景)

假设我们有两个立方体:

  • 立方体A:轴为 b(批次)× i(行)× k(列)
  • 立方体B:轴为 b(批次)× k(行)× j(列)

计算时:

  1. 沿着k方向(两个立方体的不同轴)进行纤维(fiber)的点积 → 需要求和
  2. 沿着b方向保持各层独立 → 不求和

数学证明(为什么这样设计?)

爱因斯坦约定本质上是以下运算的简写:

for b in range(batch):for i in range(3):for j in range(5):C[b,i,j] = sum(A[b,i,k] * B[b,k,j] for k in range(4))
  • k 对应最内层的 sum() → 必须求和
  • b 对应最外层的循环 → 保持独立

常见误区纠正

❌ 误区:“重复出现就要求和”
✅ 正解:“跨张量且不同位置的重复才求和”

实战测试

判断下面哪些下标会被求和:

  1. einsum('abc,cde->abe', X, Y)

    • 求和下标:c(X的第3维,Y的第1维)
    • 批处理下标:无(因为没有跨张量重复的其他下标)
  2. einsum('bik,bkj->bikj', A, B)

    • 求和下标:无(虽然k重复,但出现在输出中)
    • 批处理下标:b(相同位置)

为什么这样设计?(设计哲学)

  1. 位置差异暗示运算意图

    • 不同位置:暗示矩阵乘法类的收缩操作
    • 相同位置:暗示并行/广播操作
  2. 与张量积的自然对应

A ⊗ B 的下标排列总是保持输入张量的原始顺序

如果您还是觉得反直觉…

可以记住这个万能判断法则

  1. 写下所有输入张量的维度标记
  2. 用箭头连接相同的字母
    • 横向连接(跨张量):求和
    • 纵向连接(同张量):保留

示例:

A: b--i--k\   \
B: b--k--j

横向的 k 需要求和,纵向的 b 保持独立。

5. 总结理解模式

对于任何张量运算,都可以按照以下模式理解:

  1. 写出完整数学表达式:明确每个元素的求和关系
  2. 识别下标类型
    • 重复下标(哑标):将被求和的维度
    • 自由下标:决定输出形状的维度
  3. 转换为einsum表示法
    • 输入张量的下标用逗号分隔
    • 箭头后是输出下标
  4. 实现计算可视化:固定自由下标,展开哑标的求和过程

这种思维方法可以推广到任何维度的张量运算,是理解和实现复杂神经网络操作的有力工具。

参考

  • 【【从0开始学广义相对论02】嫌矩阵运算难写?看看爱因斯坦怎么做的:Einstein求和约定】 (这篇文章中的黑底图片和部分内容参考与本视频,感谢博主
  • 感谢DeepSeek,豆包

相关文章:

【深度学习】张量计算:爱因斯坦求和约定|tensor系列03

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; Yaoyao2024往期回顾&#xff1a;【深度学习】详解矩阵乘法、点积&#xff0c;内积&#xff0c;外积、哈达玛积极其应用|tensor系列02每日一言&#x1f33c;: “岱宗夫如何&…...

OpenHarmony-Risc-V上运行openBLAS中的benchmark

OpenHarmony-Risc-V上运行openBLAS中的benchmark 文章目录 OpenHarmony-Risc-V上运行openBLAS中的benchmark前言一、编译openBLAS1.源码下载2.工具链下载3.编译并安装openBLAS 二、编译open BLAS中的benchmark三、上设备运行总结 前言 参考https://zhuanlan.zhihu.com/p/18825…...

CCF CSP 第36次(2024.12)(2_梦境巡查_C++)

CCF CSP 第36次&#xff08;2024.12&#xff09;&#xff08;2_梦境巡查_C&#xff09; 解题思路&#xff1a;思路一&#xff1a; 代码实现代码实现&#xff08;思路一&#xff09;&#xff1a; 时间限制&#xff1a; 1.0 秒 空间限制&#xff1a; 512 MiB 原题链接 解题思路…...

windows下安装mcp servers

以sequential-thinking为例 macos下安装就像github readme中那样安装即可&#xff1a; {"mcpServers": {"sequential-thinking": {"command": "npx","args": ["-y","modelcontextprotocol/server-sequenti…...

OpenGauss 数据库介绍

OpenGauss 数据库介绍 OpenGauss 是华为基于 PostgreSQL 开发的企业级开源关系型数据库&#xff0c;现已成为开放原子开源基金会的项目。以下是 OpenGauss 的详细介绍&#xff1a; 一 核心特性 1.1 架构设计亮点 特性说明优势多核并行NUMA感知架构充分利用现代CPU多核性能行…...

Web3区块链网络中数据隐私安全性探讨

在这个信息爆炸的时代&#xff0c;Web3 的概念如同一股清流&#xff0c;以其去中心化、透明性和安全性的特点&#xff0c;为数据隐私保护提供了新的解决方案。本文将探讨 Web3 区块链网络中数据隐私的安全性问题&#xff0c;并探索如何通过技术手段提高数据隐私的保护。 Web3 …...

linux驱动之poll

驱动中 poll 实现 在用户空间实现事件操作的一个主要实现是调用 select/poll/epoll 函数。那么在驱动中怎么来实现 poll 的底层呢&#xff1f; 其实在内核的 struct file_operations 结构体中有一个 poll 成员&#xff0c;其就是底层实现的接口函数。 驱动中 poll 函数实现原…...

【最后203篇系列】028 FastAPI的后台任务处理

说明 今天偶然在别的文章里看到这个功能&#xff0c;突然觉得正好。 CeleryWorker已经搭好了&#xff0c;但是我一直想在用户请求时进行额外的处理会比较影响处理时间&#xff0c;用这个正好可以搭配上。 我设想的一个场景&#xff1a; 1 用户发起请求2 接口中进行关键信息…...

微信小程序中,将搜索组件获取的值传递给父页面(如 index 页面)可以通过 自定义事件 或 页面引用 实现

将搜索组件获取的值传递给父页面&#xff08;如 index 页面&#xff09;可以通过 自定义事件 或 页面引用 实现 方法 1&#xff1a;自定义事件&#xff08;推荐&#xff09; 步骤 1&#xff1a;搜索组件内触发事件 在搜索组件的 JS 中&#xff0c;当获取到搜索值时&#xff0c…...

深入理解分布式缓存 以及Redis 实现缓存更新通知方案

一、分布式缓存简介 1. 什么是分布式缓存 分布式缓存&#xff1a;指将应用系统和缓存组件进行分离的缓存机制&#xff0c;这样多个应用系统就可以共享一套缓存数据了&#xff0c;它的特点是共享缓存服务和可集群部署&#xff0c;为缓存系统提供了高可用的运行环境&#xff0c…...

C#核心笔记——(六)框架基础

我们在编程时所需的许多核心功能并不是由C#语言提供的,而是由.NET Framework中的类型提供的。本节我们将介绍Framework在基础编程任务(例如虚的等值比较、顺序比较以及类型转换)中的作用。我们还会介绍Framework中的基本类型,例如String、DateTime和Enum. 本章中的绝大部分…...

C# 点击导入,将需要的参数传递到弹窗的页面

点击导入按钮&#xff0c;获取本页面的datagridview标题的结构&#xff0c;并传递到导入界面。 新增一个datatable用于存储datagridview的caption和name&#xff0c;这里用的是devexpress组件中的gridview。 DataTable dt new DataTable(); DataColumn CAPTION …...

java面向对象编程【基础篇】之基础概念

目录 &#x1f680;前言&#x1f914;面向过程VS面向对象&#x1f4af;面向过程编程&#xff08;POP&#xff09;&#x1f4af;面向对象编程&#xff08;OOP&#xff09;&#x1f4af;两者对比 &#x1f31f;三大特性&#x1f4af;封装性&#x1f4af;继承性&#x1f4af;多态性…...

Oceanbase单机版上手示例

本月初Oceanbase单机版发布&#xff0c;作为一个以分布式起家的数据库&#xff0c;原来一个集群动辄小十台机器&#xff0c;多着十几台几十台甚至更多&#xff0c;Oceanbase单机版的发布确实大大降低了硬件部署的门槛。 1.下载安装介质 https://www.oceanbase.com/softwarece…...

深度学习基础--CNN经典网络之InceptionV3详解与复现(pytorch)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 InceptionV3是InceptionV1的升级版&#xff0c;虽然加大了计算量&#xff0c;但是当时效果是比VGG效果要好的。本次任务是探究InceptionV3结构并进行复…...

VOIP通信中的错误码

cancle报文 Reason: SIP;cause200;text"Call completed elsewhere" Reason: Q.850;cause26表示取消的原因是呼叫在其他地方已经完成表示Q.850标准中的原因码26&#xff0c;通常对应于“呼叫被取消”&#xff08;Call Cancelled&#xff09;487 Request Terminated Re…...

C++ STL编程-vector概念、对象创建

vector 概念&#xff1a;是常见的一种容器&#xff0c;被称为“柔性数组”。 在vector中&#xff0c;front()是数组中的第一个元素&#xff0c;back()是数组的最后一个元素。begin()是是指向第一个元素&#xff0c;end()是指向back()的后一个元素 vector的对象创建&#xff0…...

easyexcel使用模板填充excel坑点总结

1.单层map设置值是{属性}&#xff0c;那使用两层map进行设置值&#xff0c;是不是可以使用{属性.属性}&#xff0c;以为取出map里字段只用{属性}就可以设置值&#xff0c;那再加个.就可以从里边map取出对应属性&#xff0c;没有两层map写法 填充得到的文件打开报错 was empty (…...

C#学习第16天:聊聊反射

什么是反射&#xff1f; 定义&#xff1a;反射是一种机制&#xff0c;允许程序在运行时获取关于自身的信息&#xff0c;并且可以动态调用方法、访问属性或创建实例。用途&#xff1a;常用于框架设计、工具开发、序列化、代码分析和测试等场景 反射的核心概念 1. 获取类型信息…...

【Unity】使用Cinemachine+CharacterController实现第三人称视角下的角色视角、移动和跳跃控制

1.初始配置 安装Cinemachine插件给角色添加CharacterConroller创建Cinemachine-->Free Look Camera在Free Look Camera中调整参数&#xff0c;Y Axis勾选Inver&#xff0c;X Axis取消勾选InverFree Look Camera要看向角色 跟随角色&#xff08;自行设置&#xff0c;我就不…...

如何通俗的理解transformer架构编码器和解码器干的活

我们可以用生活中的比喻来理解Transformer的编码器和解码器&#xff0c;以及解码器中两种注意力的作用&#xff1a; 一、编码器&#xff08;Encoder&#xff09;&#xff1a;理解信息的「分析师团队」 想象你要翻译一句话&#xff0c;比如把中文“今天天气很好”翻译成英文。编…...

React 受控表单绑定基础

React 中最常见的几个需求是&#xff1a; 渲染一组列表绑定点击事件表单数据与组件状态之间的绑定 受控表单绑定是理解表单交互的关键之一。 &#x1f4cd;什么是受控组件&#xff1f; 在 React 中&#xff0c;所谓“受控组件”&#xff0c;指的是表单元素&#xff08;如 &l…...

UMG:ListView

1.创建WEB_ListView,添加Border和ListView。 2.创建Object,命名为Item(数据载体&#xff0c;可以是其他类型)。新增变量name。 3.创建User Widget&#xff0c;命名为Entry(循环使用的UI载体).添加Border和Text。 4.设置Entry继承UserObjectListEntry接口。 5.Entry中对象生成时…...

实验五 内存管理实验

实验五 内存管理实验 一、实验目的 1、了解操作系统动态分区存储管理过程和方法。 2、掌握动态分区存储管理的主要数据结构--空闲表区。 3、加深理解动态分区存储管理中内存的分配和回收。 4、掌握空闲区表中空闲区3种不同放置策略的基本思想和实现过程。 5、通过模拟程…...

初识 Firebase 与 FPM

Firebase 是什么 ? Firebase 是 Google 旗下面向 iOS、Android、Web 与多端框架&#xff08;Flutter、Unity 等&#xff09;的应用开发平台&#xff0c;提供从「构建 → 发布与运维 → 增长」全生命周期的一站式后端即服务&#xff08;BaaS&#xff09;。它把实时数据库、托管…...

探索C++中的数据结构:栈(Stack)的奥秘

引言 栈是计算机科学中最基础且重要的数据结构之一&#xff0c;它像一摞盘子一样遵循"后进先出"&#xff08;LIFO&#xff09;的原则。无论是函数调用、表达式求值&#xff0c;还是浏览器前进后退功能&#xff0c;栈都扮演着关键角色。本文将深入解析栈的C实现及其应…...

vue3 nprogress 使用

nprogress 介绍与作用 1.nprogress 是一个轻量级的进度条组件&#xff0c;主要用于在页面加载或路由切换时显示一个进度条&#xff0c;提升用户体验。它的原理是通过在页面顶部创建一个 div&#xff0c;并使用 fixed 定位来实现进度条的效果 2.在 Vite Vue 3 项目中&#xf…...

MCP(Model Context Protocol 模型上下文协议)科普

MCP&#xff08;Model Context Protocol&#xff0c;模型上下文协议&#xff09;是由人工智能公司 Anthropic 于 2024年11月 推出的开放标准协议&#xff0c;旨在为大型语言模型&#xff08;LLM&#xff09;与外部数据源、工具及服务提供标准化连接&#xff0c;从而提升AI在实际…...

韩媒专访CertiK创始人顾荣辉:黑客攻击激增300%,安全优先的破局之路

4月17日&#xff0c;韩国知名科技媒体《韩国IT时报》(Korea IT Times)发布了对CertiK联合创始人兼CEO顾荣辉教授的专访。双方围绕CertiK一季度《HACK3D》安全报告&#xff0c;就黑客攻击手法的迭代和安全防御技术的创新路径等&#xff0c;展开深度对话。 顾荣辉认为&#xff0…...

华为openEuler操作系统全解析:起源、特性与生态对比

华为openEuler操作系统全解析&#xff1a;起源、特性与生态对比 一、起源与发展历程 openEuler&#xff08;欧拉操作系统&#xff09;是华为于2019年开源的Linux发行版&#xff0c;其前身为华为内部研发的服务器操作系统EulerOS。EulerOS自2010年起逐步发展&#xff0c;支持华…...

从零实现Git安装、使用

一、git安装 Git官方下载 1.下载exe程序 2.双击安装&#xff0c;一直点击next&#xff0c;默认安装 安装完成后&#xff0c;在任意文件夹右键&#xff0c;出现下图所示&#xff0c;即为安装成功。 3.【Git Bash Here】调出命令窗口&#xff0c;设置用户名和 email 地址。 gi…...

leetcode刷题日记——单词规律

[ 题目描述 ]&#xff1a; [ 思路 ]&#xff1a; 题目要求判断字符串 s 中的单词是否按照 pattern 这种模式排列具体思路和 205. 同构字符串基本一致&#xff0c;可以通过 hash 存储来实现思路二&#xff0c;通过字符串反推 pattern&#xff0c;如果一致&#xff0c;则遵循相…...

Ubuntu 修改语言报错Failed to download repository information

1.进入文件(ps:vim可能出现无法修改sources.list文件的问题&#xff09; sudo gedit /etc/apt/sources.list2.修改(我是直接增添以下内容在其原始源前面&#xff0c;没有删原始内容)文件并保存&#xff0c;这里会替换原文件 deb http://mirrors.aliyun.com/ubuntu/ focal mai…...

烹饪与餐饮管理实训室数字课程开发方案

烹饪与餐饮管理专业需要具有餐饮产品设计、研发的能力&#xff1b; 具有饮食美学、科学配餐与高端宴席设计的能力&#xff1b; 具有餐饮企业、中央厨房运营管理的能力&#xff1b; 具有餐饮信息化系统应用、数字化运营的能力&#xff0c;这些能力的培养&#xff0c;需要烹饪与餐…...

关于模拟噪声分析的11个误区

目录 1. 降低电路中的电阻值总是能改善噪声性能 2. 所有噪声源的噪声频谱密度可以相加&#xff0c;带宽可以在最后计算时加以考虑 3. 手工计算时必须包括每一个噪声源 4. 应挑选噪声为ADC 1/10的ADC驱动器 5. 直流耦合电路中必须始终考虑1/f噪声 6. 因为1/f噪声随着频率降…...

基于 S2SH 架构的企业车辆管理系统:设计、实现与应用

在企业运营中&#xff0c;车辆管理是一项重要工作。随着企业规模的扩大&#xff0c;车辆数量增多&#xff0c;传统管理方式效率低下&#xff0c;难以满足企业需求。本文介绍的基于 S2SH 的企业车辆管理系统&#xff0c;借助现代化计算机技术&#xff0c;实现车辆、驾驶员和出车…...

51单片机实验七:EEPROM AT24C02 与单片机的通信实例

目录 一、实验环境与实验器材 二、实验内容及实验步骤 三、proteus复位电路 1.改电阻的阻值&#xff08;方法一&#xff09; 2.改电阻的属性&#xff08;方法2&#xff09; 一、实验环境与实验器材 环境&#xff1a;Keli&#xff0c;STC-ISP烧写软件,Proteus. …...

【TeamFlow】 1 TeamFlow 去中心化生产协同系统架构

总体架构设计 采用四层混合架构&#xff0c;结合分层设计与去中心化网络&#xff1a; #mermaid-svg-qBgw9wMd8Gi0gOci {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-qBgw9wMd8Gi0gOci .error-icon{fill:#552222;}…...

第 8 期:条件生成 DDPM:让模型“听话”地画图!

本期关键词&#xff1a;Conditional DDPM、Class Embedding、Label Control、CIFAR-10 条件生成 什么是条件生成&#xff08;Conditional Generation&#xff09;&#xff1f; 在标准的 DDPM 中&#xff0c;我们只是“随机生成”图像。 如果我想让模型生成「小狗」怎么办&…...

树莓派超全系列教程文档--(32)config.txt常用音频配置

config.txt常用音频配置 板载模拟音频&#xff08;3.5mm耳机插孔&#xff09;audio_pwm_modedisable_audio_ditherenable_audio_ditherpwm_sample_bits HDMI音频 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 板载模拟音频&#xff08;3.5mm耳机…...

Perf学习

重要的能解决的问题是这些&#xff1a; perf_events is an event-oriented observability tool, which can help you solve advanced performance and troubleshooting functions. Questions that can be answered include: Why is the kernel on-CPU so much? What code-pa…...

量子神经网络编译器开发指南:从理论突破到产业落地全景解析

本文深度剖析IBM Qiskit 5.0量子经典混合编译器的技术架构&#xff0c;详解如何基于含噪量子处理器实现MNIST手写数字分类任务&#xff08;准确率达89%&#xff09;。结合本源量子云、百度量子等国内平台免费配额政策&#xff0c;系统性阐述量子神经网络开发的技术路线与资源获…...

守护者进程小练习

守护者进程含义 定义&#xff1a;守护进程&#xff08;Daemon&#xff09;是运行在后台的特殊进程&#xff0c;独立于控制终端&#xff0c;周期性执行任务或等待事件触发。它通常以 root 权限运行&#xff0c;名称常以 d 结尾&#xff08;如 sshd, crond&#xff09;。 特性&a…...

研究生面试常见问题

研究生面试是考研复试的重要环节&#xff0c;面试表现直接关系到录取结果。以下从面试流程、常见问题分类及回答技巧等方面为您整理了相关内容&#xff0c;帮助您更好地准备面试。 一、研究生面试的基本流程 自我介绍&#xff1a;通常需要准备1分钟左右的中文或英文自我介绍&a…...

极狐GitLab 登录限制如何设置?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 登录限制 (BASIC SELF) 您可以使用登录限制自定义 Web 界面以及基于 HTTP(S) 的 Git 的身份验证限制。 设置 要访问登录限…...

AI驱动商业变革:零售行业的智能化跃迁

引言&#xff1a;AI技术迈入黄金时代 2024年成为生成式AI&#xff08;Gen AI&#xff09;全面落地的关键年。据麦肯锡《技术趋势展望》报告&#xff0c;生成式AI相关投资同比增长​7倍​​&#xff0c;其经济价值预计达​​2.6-4.4万亿美元​​[1]。在零售领域&#xff0c;该技…...

初始图像学(6)

Camera类 我们之前学了很多的图形学知识和相关的程序&#xff0c;现在我们停下脚步&#xff0c;来好好整理一下我们学习的内容&#xff0c;我们将之前的视口代码和渲染代码合并到一个新的单类camera.h&#xff0c;这个类主要负责两项任务&#xff1a; 构建并发射光线到世界中 …...

【React】通过 fetch 发起请求,设置 proxy 处理跨域

fetch 基本使用跨域处理 fetch 基本使用 在node使用原生ajax发请求&#xff1a;XMLHttpRequest()1.获取xhr对象 2.注册回调函数 3.设置参数&#xff0c;请求头 4.发起连接原生ajax没有带异步处理 promise&#xff1b;原生ajax封装一下&#xff0c;以便重复调用jQuery&#…...

好数对的数目

题目描述 给你一个整数数组 nums。 如果一组数字 (i, j) 满足 nums[i] nums[j] 且 i < j&#xff0c;就可以认为这是一组 好数对。 返回 好数对 的数目。 示例 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3,1,1,3] 输出&#xff1a;4 解释&#xff1a; 有 4 组好…...

Animated Raindrop Ripples In HLSL

这节课是利用材质做雨滴i效果 首先是创建一个圆环&#xff0c;实际上他就是为了创建一个圆&#xff0c;但是是空心的&#xff0c;可以看之前我的做法&#xff0c;这里以他的为准 创建圆环 就是当uv的点在max_radius和min_radius之间的时候绘制。 他这里写了ringThickness&a…...