The Clock and the Pizza [NeurIPS 2023 oral]

本篇文章发表于NeurIPS 2023 (oral),作者来自于MIT。

文章链接:https://arxiv.org/abs/2306.17844


一、概述

目前,多模态大语言模型的出现为人工智能带来新一轮发展,相关理论也逐渐从纸面走向现实,影响着人们日常生活的方方面面。在享受着技术提供给我们福利的同时,人们也在不断尝试去探索这些模型/算法背后的原理究竟是什么,不禁思考这样几个问题:

  • 神经网络解决问题的具体机制是什么?
  • 这种机制是否和我们现实生活中解决问题的方式是一致的(是否是人类可理解的)?
  • 影响神经网络解决问题方式的因素是什么? 

这些问题并不新鲜,理解神经网络背后原理/机制的研究在最近几年更是层出不穷。这些研究大概可以分为两类:第一类,对训练好之后的模型进行事后的解释(post-hoc explanation),探索这些模型解决问题的方式,并验证这些方式是否是人类可以理解的。显然,上述几个问题的答案可以通过这种方式获得。与之对应,第二类则是根据人类可理解的机制去设计模型,即,使模型具备所谓的内在可解释性(instrinct interpretabiltiy),比较具有代表性的例子如concept bottleneck models (CBMs)等。本篇博客将讨论重点放在第一类。

为了回答最初的几个问题,本篇文章以模加法(modular addition) —— 如,8+6=2 (mod 12) ——为例,对训练好的网络所学习到的算法进行逆向工程(reverse-engineering),尝试寻找神经网络进行模加法运算的原理。

研究发现,即使是执行像模加法这样简单的任务,神经网络的机制也十分复杂,并且也不仅仅局限于单一的解决方案。在不同条件下(如不同的模型超参数、模型大小、数据集规模等),模型的运算机制之间具有巨大差异。这些不同的机制构成了所谓的算法相空间 (algorithm phase space),从其中一种机制跳转为另一种机制的现象被称为“相变(phase transition)”。而在模加法的算法相空间中存在这样两种算法:clock算法和pizza算法。接下来就让我们具体看一下这两种算法。


二、模运算与Clock Algorithm

实验设置:

训练神经网络执行模加法运算a+b=c\pmod{p},其中a,b,c=0,1,\cdots,p-1。作者在整篇论文中使用p = 59。在网络中,每一个整数 t 都有一个对应的embedding vector \mathbf{E}_t\in\mathbb{R}^d。对于两个整数 a,b,它们的embedding [\mathbf{E}_a,\mathbf{E}_b]\in\mathbb{R}^{2d}将作为网络的输入,并预测得到categorical output c。经过训练,embedding以及网络参数都将被学习得到。

在实验中,作者在模加法运算任务上训练了两种不同的网络架构:模型A和模型B。

  • model A: a one-layer ReLU transformer with constant attention
  • model B: a standard one-layer ReLU transformer

由于model A并不包含attention,因此可以将其简单视为以ReLU作为activation function的MLP。

2.1 Review of the Clock Algorithm

作者发现,在模型A和模型B完成训练之后,embedding (\mathbf{E}_a,\mathbf{E}_b) 通常在由它们的嵌入矩阵 (embedding matrix) 的前两个主成分所构成的平面上呈现出圆形分布。这与以前的工作的发现是一致的。

Formally, \mathbb{E}_a\approx[\cos(w_ka),\sin(w_ka)] where w_k=2\pi k/pk is an integer in [1,p-1].

Nanda et al.[1] discovered a circuit that uses these circular embeddings to implement an interpretable algorithm for modular arithmetic, which we call the Clock algorithm.

我们可以想象一个时钟,假设现在是上午9点,再过4个小时是下午1点,这个过程实际上就是模加法运算 9+4=1\pmod{12}.时钟(Clock)的运动可以简单地描述一个用来执行模加法运算的算法,将1到12共十二个数字排列在圆形表盘上,每两个连续数字之间的角度是360^\circ/12=30^\circ.对于上述例子而言,计算 9\times30^\circ以及 4\times30^\circ 并将二者相加,最后的角度对应于 1\times30^\circ.

Nanda et al.[1]发现model B (standard one-layer ReLU transformer)执行的就是上述的clock algorithm。具体而言,clock algorithm会执行三个步骤:

1. Tokens a and b are embedded as 

\mathbf{E}_a=[\cos(w_ka),\sin(w_ka)] 

\mathbf{E}_b=[\cos(w_kb),\sin(w_kb)]

2. 两个embedding \mathbf{E}_a,\mathbf{E}_b 的polar angles相加并通过三角恒等式得到相加结果

\mathbf{E}_{ab,x}=\cos\left(w_k(a+b)\right)=\cos\left(w_ka\right)\cos\left(w_kb\right)-\sin\left(w_ka\right)\sin\left(w_kb\right)\\ \mathbf{E}_{ab,y}=\sin\left(w_k(a+b)\right)=\sin(w_ka)\cos\left(w_kb\right)+\cos\left(w_ka\right)\sin\left(w_kb\right)

3. 对于每一个candidate output c,对应的logit为 Q_{abc}

总结如下:

\mathbf{E}_{ab}\equiv\begin{pmatrix}\mathbf{E}_{ab,x}\\\mathbf{E}_{ab,y}\end{pmatrix}=\begin{pmatrix}\mathbf{E}_{a,x}\mathbf{E}_{b,x}-\mathbf{E}_{a,y}\mathbf{E}_{b,y}\\\mathbf{E}_{a,x}\mathbf{E}_{b,y}+\mathbf{E}_{a,y}\mathbf{E}_{b,x}\end{pmatrix}=\begin{pmatrix}\cos(w_k(a+b))\\\sin(w_k(a+b))\end{pmatrix}

Q_{abc}=\mathbf{U}_{c}\cdot\mathbf{E}_{ab},\mathbf{U}_{c}\equiv(\mathbf{E}_{c,x},\mathbf{E}_{c,y})=(\cos(w_{k}c),\sin(w_{k}c))

Q_{abc}(\mathrm{Clock})=\cos(w_k(a+b-c))

最终,预测输出为 c^{*}=\operatorname{argmax}_{c}Q_{abc}.

(以上三个步骤的具体执行方式请参考文献[1],本篇博客谨作为结论使用。)

Clock algorithm的关键在于,注意力机制可以用来执行乘法运算。然而我们可能会问,当注意力机制缺失时(如model A)会发生什么?

对此,作者研究发现了一些model A违反clock algorithm的证据。实际上,这个情况下model A将不再使用clock algorithm来完成模加法运算,而是使用另一种机制(pizza)。

2.2 Evidence I: Gradient Symmetry

回顾 Q_{abc} 的表达式:

Q_{abc}^{\mathrm{Clock}}=(\mathbf{E}_{a,x}\mathbf{E}_{b,x}-\mathbf{E}_{a,y}\mathbf{E}_{b,y})\mathbf{E}_{c,x}+(\mathbf{E}_{a,x}\mathbf{E}_{b,y}+\mathbf{E}_{a,y}\mathbf{E}_{b,x})\mathbf{E}_{c,y}

我们不难发现 Q_{abc} 的梯度在参数顺序上缺乏permutation symmetry,即

\nabla_{\mathbf{E}_a}{Q_{abc}}\neq\nabla_{\mathbf{E}_b}{Q_{abc}}

因此,如果我们观察到相反的情况,即,某个算法符合permutation symmetry(上式等号成立),那么这个算法一定不是clock algorithm。

因此,作者计算了输入嵌入向量(input embedding vectors)最大的6个主成分,并计算output logits相对于输入嵌入向量的梯度,最后将计算得到的梯度投影到6个主成分方向上。model A与model B的结果如下图所示。

可以发现由于model B采取的是clock algorithm,因此logits对于不同embedding的梯度是不对称的(对应于图中红色圆点);相反,model A是对称的(图中黄色圆点),这就说明model A采取的一定不是clock algorithm。

2.3 Evidence II: Logit Patterns

除了检查模型的输入,检查模型的输出也揭示了model A与model B的差异。对于每个input pair (a, b),作者可视化了分配给正确标签 a + b 的输出logit。

图中的行以a - b作为索引,列以a + b作为索引。从图中可以看出,model A的correct logits对a - b有较为明显的依赖性。具体而言,model A每一行的correct logits大致是相同的,但在model B中并没有观察到这种pattern。这再一次表明model A和model B分别对应于不同的算法。

以上两点(2.2, 2.3)都印证了model A与model B之间算法/机制的不同。我们知道model B遵循的是clock算法,那model A遵循的是什么样的算法呢?但不管怎样,model A所遵循的算法一定拥有gradient symmetry以及如Fig.3所示的logit pattern。

在下一节中,作者描述了一种新的解决模加法运算的算法(pizza),并在后续证明model A实施的就是pizza算法。


三、另一种解决方案: the Pizza Algorithm

3.1 The Pizza Algorithm

与Clock算法不同,Pizza算法在embedding形成的圆内而不是在圆周上运行。(作者将这个过程形象地比喻成香肠铺满披萨,也是pizza algorithm名称的由来。)

Pizza算法的基本思想如下图右侧所示。

给定一个固定的标签 c,对于所有 (a,b) 且 a+b=c\pmod{p},点 \mathbf{E}_{ab}=(\mathbf{E}_a+\mathbf{E}_b)/2 位于经过二维平面原点的一条直线上。不同的 (a,b) 可以形成若干条这样的直线,这些直线就将整个披萨切割成一个个小块。具体来说,每两条直线会将披萨切成镜像的两个“披萨片”。接下来,为了执行模运算,网络可以判断两个嵌入向量的平均值 \mathbf{E}_{ab} 位于哪个切片对中。

Pizza算法也包括三个步骤:

步骤1与Clock算法相同,将token a和b分别嵌入为:

\mathbf{E}_a=(\cos(w_ka),\sin(w_ka)) 

\mathbf{E}_b=(\cos(w_kb),\sin(w_kb))

步骤2和步骤3则与Clock算法不同:

步骤2.1,取 \mathbf{E}_a 和 \mathbf{E}_b 的平均值,得到 \mathbf{E}_{ab}

在步骤2.2和步骤3中,计算任何可能的输出 c 的logit Q_{abc} 来(隐式地)计算 \mathbf{E}_{ab} 的极角。为了达到这个目的,一种(较为直观的)方式是取 \mathbf{E}_{ab} 与 (\cos(w_kc/2),\sin(w_kc/2)) 的点积的绝对值,但这个做法在神经网络中并不常见,并且会导致不同的logit pattern,而与我们上面对logit可视化后的结果不一致。

实际上,步骤2.2会将 \mathbf{E}_{ab} 转换为向量

 \mathbf{H}_{ab}=|\cos(w_k(a-b)/2)|(\cos(w_k(a+b)),\sin(w_k(a+b)))

Note: 实际上就是clock algorithm种 \mathbf{E}_{ab} 乘以一个因子。

然后步骤3将转换后的向量与output embedding U_{c}=(\cos(w_{k}c),\sin(w_{k}c)) 进行点乘,得到

Q_{abc}(\mathrm{Pizza})=\left|\cos(w_k(a-b)/2)\right|\cos(w_k(a+b-c))

最后的预测结果依然是c^{*}=\operatorname{argmax}_{c}Q_{abc}.

两种算法之间的关键区别在于二者所需要的非线性操作不同:Clock algorithm需要在步骤2中对输入进行乘法运算;而Pizza只需要绝对值运算,而绝对值运算很容易通过ReLU层实现。因此,如果神经网络在执行乘法时缺乏inductive bias,则模型更有可能实施的是Pizza algorithm而不是Clock algorithm,在后面会具体验证这一点。

3.2 Evidence I: Logit Patterns

由上可见,Clock和Pizza算法在步骤3中都计算了logits Q_{abc},但是二者有不同的形式。具体来说,与 Q_{abc}(\mathrm{Clock}) 相比,Q_{abc}(\mathrm{Pizza}) 有一个额外的乘法因子 |\cos(w_k(a-b)/2)|。因此,给定 c = a + b, Q_{abc}(\mathrm{Pizza}) 依赖于 a - b,但 Q_{abc}(\mathrm{Clock}) 对a - b则没有这种依赖关系。

直觉来看,如果 \mathbf{E}_{ab} 更“长”,则样本更有可能被正确分类,而 \mathbf{E}_{ab} 的范数依赖于a - b。这和我们在Fig.3中观察到的现象一致,即model A的logits表现出对a - b的强烈依赖。

3.3 Evidence II: Clearer Logit Patterns via Circle Isolation

为了更好地理解pizza algorithm,我们将embedding matrix \mathbf{E} 替换为一系列rank-2矩阵来做近似,即,仅使用第一和第二主成分,或仅使用第三和第四主成分,以此类推。对于每个这样的矩阵,embedding位于一个 2-D 子空间(subspace)中。对于model A 和model B,经过可视化后发现embedding在这个subspace中均呈现出一个圆形,如下图所示。

这个过程称作“circle isolation”。使用近似的rank-2矩阵代替原始embedding,我们发现model A 和model B的预测结果仍然是预期之内的:部分 (a,b,c) 的预测准确度很高,这取决于isolated circle的周期性。

Note: 周期性可以用 k 表示,k 的值等于两个连续数字之间在circle上的距离,例如上图Circle #1中,数字1和数字2之间的距离为17,Circle #2中则为3;而图中的 \delta 则代表相邻两个数字之间的差。

正如Fig.1中Pizza 和 Clock 算法所预测的那样,model A (pizza)的准确性在特定的a - b值处下降到零,而model B (clock)的准确性与a - b无关。

此外,对于model A来说,我们只使用first 2 principle components所构成的isolated circle对应的embedding替换掉actual embedding,再根据Fig.1中clock与pizza的公式去计算各自的logits,将此结果与model A的actual logits做比较,发现 Q_{abc}(\mathrm{Pizza}) 比 Q_{abc}(\mathrm{Clock}) 解释了更多的方差。这意味着model A倾向于遵循pizza algorithm而不是clock algorithm.

根据先前的分析,我们可以推测逻辑回归值 Q_{abc}(\mathrm{Clock}) 不会依赖于a - b,但并没有预测到它会依赖于a + b. 但是在上图中,我们预料之外地发现 Q_{abc}(\mathrm{Clock}) 对 a + b 的敏感性。

作者对此的推测是,clock algorithm中的第一步和第二步几乎是无噪声实现的,使得标签 c 相同的样本在第二步之后会坍缩到同一个点,使得有相同结果的 a+b\pmod{p} 会产生相同的logits,这解释了上图中每一列的结果几乎是一致的。然而在circle isolation之后,第三步的classification可能并不完善从而导致logits出现波动,因此各个列之间的logits彼此不一致。

3.4 Evidence III: Accompanied & Accompanying Pizza

细心的小伙伴可能会发现,pizza algorithm有一个致命的弱点,就是当 a,b 位于circle的对侧时(antipodal,连线经过圆心),那么它们的中点将位于圆点,例如下图中的(1,7),(2,8),(3,9),即使它们进行模加法之后会产生不同的结果,但此时模型将完全无法正确分类。即使对于奇数 p ,此时并没有严格的antipodal pairs,approximately antipodal pairs也比non-antipodal pairs分类更难,因为此时 \mathbf{E}_{ab} 更短。

有趣的是,对于(approximately) antipodal pairs,神经网络自行找到了一种“聪明”的方式来弥补这种failure mode. 作者发现,pizza通常会与“accompanying pizza”一起出现,accompanied pizza和accompanying pizza在某种意义上互补。原本在accompanied pizza中(approximately) antipodal pairs会在新的accompanying pizza中变得“很不antipodal”。

如果将circle上相邻数字之间的差异表示为 \delta,accompanied pizza与accompanying pizza上相邻数字之间的差异为 \delta_1 与 \delta_2,那么二者之间将满足 \delta_{1}=2\delta_{2}\pmod{p}. 在实验中,作者发现Fig.4 (见下图) 中的pizza #1 #2 #3 都有accompanying pizza,称之为pizza #4 #5 #6。

Note:  \omega_k 也满足二倍关系。

例如,上图最右侧的两个pizza(#3与#6)为accompanied and accompanying pizza,\delta 之间满足取模后的二倍关系,原本位于圆点两侧的antipodal pairs现在变得十分相邻(绿色圆圈)。

Note: 两个pizza之间是单向的accompany关系,而不是互为accompanying pizza!

然而,这些accompanying pizza在最终模型预测中并不起重要作用:

“Accompanied pizzas #1 #2 #3 can achieve 99.7% accuracy, but accompanying pizzas #4 #5 #6 can only achieve 16.7% accuracy.”

作者对训练过程的推测是:

  • 在初始化时,pizza #1 #2 #3 对应于三个不同的“lottery tickets”
  • 在训练的早期阶段,为了弥补pizza #1 #2 #3 的缺陷(antipodal pairs),形成了pizza  #4 #5 #6
  • 随着训练的进行(in the presence of weight decay),神经网络被剪枝

最终,pizza  #4 #5 #6将不会显著参与预测,尽管它们在embedding space中仍然是visible的。

Note: 判断accompanying pizza是否参与预测可以通过分析embedding的主要频率,即isolated circle对应的frequency \omega_k 来实现。我们也可以发现,accompanied pizza和accompanying pizza的主要频率是不一致的。

一些题外话,参考文献[1]使用离散傅里叶变换DFT提取embedding matrix的主要频率,而本文是根据visualization来获得 \omega_k —— 或许此处可以借鉴[1]使用DFT验证两种方式得到的频率是否一致。


四、算法相空间

在上一节中,我们介绍了一个典型的clock algorithm (model B)和一个典型的pizza algorithm (model A)。在本节,作者研究了架构和超参数将如何控制模型在这两个算法之间的选择,并提出了区分Pizza和Clock的量化指标。

4.1 Metrics

根据前面的叙述,我们发现clock algorithm和pizza algorithm具有梯度对称性、以及是否依赖于 a-b 的区别,因此作者得出两个指标:gradient symmetricity 和 distance irrelevance.

4.1.1 Gradient Symmetricity

正如在第二节中所讨论的,Pizza算法具有symmetric gradients,而Clock算法具有asymmetric gradients.第三节中model A (pizza)和model B (clock)的梯度对称性分别为99.37%和33.36%,见下图↓

4.1.2 Distance Irrelevance

观察all inputs所对应的correct logits的方差有多少取决于具有相同距离 d=a-b 的input pairs产生的correct logits的方差来衡量distance irrelevance,取值为[0,1],越大代表越不相关。

q 值越小,代表分子小,也就是说,具有相同距离 d 的input pairs几乎不产生方差,这意味着logits在 a-b 相同时彼此差距很小,即logits依赖于a-b.

在Fig.3中,model A和model B的distance irrelavance分别是0.17和0.85。

最后作者指出:pizza algorithm的typical distance irrelevance范围为0到0.4(与距离相关),而clock为0.4到1(与距离相关)。

4.1.3 Which Metric is More Decisive?

当两个指标的结果相互冲突时,哪一个更具有决定性?作者认为:

  • Distance irrelevance是pizza algorithm的决定性因素,因为依赖于距离的output logits高度暗示了pizza algorithm;
  • Gradient symmetricity可以用来排除clock algorithm,因为它需要将输入相乘,而这将导致梯度不对称。

Fig.6证实了在distance irrelevance很低(对应于pizza)的情况下,gradient symmetricity几乎总是接近1(对应于non-clock)。如下图所示,虚线左侧倾向于pizza,右侧倾向于clock.

4.2 Identifying algorithmic phase transitions

模型是如何在clock algorithm和pizza algorithm之间进行选择的呢?

作者通过在model A(transformer without attention)和model B(standard transformer with attention)之间进行interpolation来探索这个问题。为此,引入了一个新的超参数attention rate \alpha.

对于attention rate为 \alpha 的模型,将每个attention head的原注意力矩阵 M 修改为:

M'=M\alpha+J(1-\alpha)

其中 J 是全1矩阵。也就是说,参数 \alpha 定义了一批通过线性插值得到的由全1矩阵到original attention (post-softmax)之间的“过渡矩阵”,attention rate \alpha 可以控制模型保持多少attention。\alpha=0 对应于全1矩阵,\alpha=1 对应于原始的注意力矩阵。

随后,作者在transformer上进行了以下实验:

  1. width为128,\alpha从[0,1]中均匀采样的one-layer transformer(Fig.7)
  2. width为[32,512],\alpha从[0,1]中均匀采样的one-layer transformer(Fig.7)
  3. width为128,\alpha从[0,1]中均匀采样的2~4-layer transformer(Fig.11)

结果如下(Fig.7):

Fig.7上侧的两个图对应于固定width=128的one-layer transformer,下侧对应于width从32变化到512的one-layer transformer.

从Fig.7中我们可以发现:

  • 对于circular models,模型要么具有low gradient symmetricity(对应于Clock算法),要么具有low distance irrelevance(对应于Pizza算法)
  • 对于fixed width实验,观察到从Pizza算法到Clock算法的phase transition很明显
  • 对于attention rate和varied width,phase的边界几乎是线性的。换句话说,随着模型变宽,the attention rate transition point也会增加,在图像上展现为一条倾斜的直线。也就是说,width越宽,越不容易通过增加attention rate使算法从pizza转变为clock。作者对此的解释是,当模型变得更宽时,线性层变得更capable,而注意力机制得到的benefit更少,使得线性层更占主导地位,从而使算法倾向于pizza而不是clock
  • 连续的phase变化表明,在clock和pizza算法之间存在着其它networks ——"This is achievable by having some principal components acting as the Clock and some principal components acting as the Pizza." 这可以视为是不同算法的一种集成。

Fig.11:

我们还可以发现non-circular algorithms的存在(即,其embedding project到任何平面都不是圆形)。

到这里本篇文章的正文部分基本就讲解完毕了。本文专注于模加法问题,而即使在这个受限的领域中,在不同的architecture和seeds之间也会产生不同的模型行为。要将这些技术扩展到实际任务中使用的更为复杂的模型还需要大量的额外工作。


五、补充材料及问题

本篇论文的supplementary materials中包含着很多有趣且有价值的信息,内容比较多并且我本人也没有全部看过一遍,所以在这里只列举几点。完整的信息请感兴趣的小伙伴自行查阅原论文。

5.1 Supplementary A

Mathematical Analysis and An Example of Pizza Algorithm

主要涉及一些三角函数的计算,不难,但是这个公式的得出以及近似的那一步需要一些想象力。

  • Algorithm: Pizza, Example

5.2 Supplementary D

Pizza comes in pairs

  • Algorithm: Accompanying Pizza

这里再次体现出了accompnying and accompanied pizza角频率 \omega_k 之间的二倍关系。

5.3 Question 1

An Illustration on the Accompanying Pizza Algorithm

可以看到,原先在accompanied circle(左侧)中antipodal的两个点在accompanying circle(右侧)中彼此相邻。

TODO: 作者没有在文中对Fig.12做说明,我也暂时没有完全懂,留着以后再想...

现在仅有的信息是:所谓的negative/positive指的是正/负,当圆心与 a , b 二者中点的连线经过圆上的某个点时,结果为负;反之,不经过某点时,则为正。

Note: 再次强调,两个pizza之间只有单向关系,而不是互为accompanying pizza. 比如右图的0和8在左图中并不相邻(adjecent)

5.4 Question 2

作者在这里说accompanying and accompanied pizza拥有相同的 \omega_k. emmm...我对此表示怀疑。

具体看下图,分别是model A (pizza)的 accompanied and accompanying pizza:

以中间列的两个pizz为例,图中绿色圆圈所示圈出了数字0和数字1,二者的距离就是 k. 上面的pizza k_1=3,下面的pizza k_2=6(如果我没数错的话),可以发现二者仍然呈二倍关系(mod p)。而根据 w_k=2\pi k/p,二者也呈二倍关系(mod p)。总之 \omega_k 肯定是不同的,而不是作者说的 "Accompanying and accompanied pizza have the same w_k."

不知道这个地方是不是我理解错了,欢迎大家指出。


总体来说还是挺有意思的一篇文章,关于mechanism explanation的文章之前没有看过太多,有机会还是要扩充一下这方面的知识。

Reference

[1] Neel Nanda, Lawrence Chan, Tom Lieberum, Jess Smith, and Jacob Steinhardt. Progress measures for grokking via mechanistic interpretability. In The Eleventh International Conference on Learning Representations, 2023.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/3521.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探讨mfc100u.dll丢失的解决方法,修复mfc100u.dll有效方法解析

mfc100u.dll丢失是一个比较常见的情况,由于你电脑的各种操作,是有可能引起dll文件的缺失的,而mfc100u.dll就是其中的一个重要的dll文件,它的确实严重的话是会导致程序打不开,系统错误的。今天我们就来给大家科普一下mf…

太速科技-多路PCIe的阵列计算全国产化服务器

多路PCIe的阵列计算全国产化服务器 多路PCIe的阵列计算全国产化服务器以国产化处理器(海光、飞腾ARM、算能RSIC V)为主板,扩展6-8路PCIe3.0X4计算卡; 计算卡为全国产化的AI处理卡(瑞星微ARM,算能AI&#x…

【stm32】swjtu西南交大嵌入式实验三 外部中断实验:按键中断

实验内容: 1、编写程序,设置主程序:跑马灯以 0.2s 的速度旋转;将 KB1 设置为外部中断,下 降沿触发,按下 KB1 则全彩灯的 R 灯闪烁 5 次。编译、下载程序到开发板,观察实 验现象;按下…

阶跃星辰:探索智能科技的星辰大海

引言 在当今快速发展的科技时代,人工智能已经成为推动社会进步的重要力量。阶跃星辰,正是在这一背景下诞生的。 阶跃星辰是一家专注于通用人工智能探索的公司,成立于2023年4月。该公司的创始团队由一群对人工智能充满热情和渴望的人组成&am…

LM1875L-TB5-T 音频功率放大器 PDF中文资料_参数_引脚图

LM1875L-TB5-T 规格信息: 商品类型音频功率放大器 音频功率放大器的类型- 输出类型1-Channel (Mono) 作业电压16V ~ 60V 输出功率25W x 1 4Ω 额外特性过流保护,热保护 UTC LM1875是一款单片功率放大器,可为消费类音频应 用提供极低失真和高品质的…

物联网鸿蒙实训解决方案

一、建设背景 在数字化浪潮汹涌的时代,华为鸿蒙系统以其前瞻的技术视野和创新的开发理念,成为了引领行业发展的风向标。 据华为开发者大会2023(HDC. Together)公布的数据,鸿蒙生态系统展现出了强劲的发展动力&#x…

【论文浅尝】Phi-3-mini:A Highly Capable Language Model Locally on Your Phone

Phi-3-mini phi-3-mini,一个3.8亿个参数的语言模型,训练了3.3万亿个token,其总体性能,通过学术基准和内部测试进行衡量,可以与Mixtral 8x7B和GPT-3.5等模型相媲美(在MMLU上达到69%,在MT-bench上达到8.38)&…

深圳证券交易所Binary行情数据接口规范

对接深圳证券交易所Binary行情数据接口其实并不难,你需要具备以下知识。 1、需要了解Binary报文设计结构,消息头消息体消息尾。 消息体: 如果是纯map结构的比较简单,字段平铺开来即可。如{"id":"1","…

WEB服务的配置与使用 Apache HTTPD

服务端:服务器将发送由状态代码和可选的响应正文组成的 响应 。状态代码指示请求是否成功,如果不成功,则指示存在哪种错误情况。这告诉客户端应该如何处理响应。较为流星的web服务器程序有: Apache HTTP Server 、 Nginx 客户端&a…

bugfix: com.alibaba.druid.sql.parser.EOFParserException: EOF

前言 在日常的开发工作中,我们经常会遇到各种各样的问题,其中涉及数据库操作的接口联调尤其容易出现意想不到的状况。今天我就遇到了一个关于Druid SQL解析异常的问题,具体表现为com.alibaba.druid.sql.parser.EOFParserException: EOF。通过…

基于SpringBoot开发的同城租房系统租房软件APP小程序源码

项目背景 一、市场前景 随着城市化进程的加快和人口流动性的增强,租房市场正逐渐成为一个不可忽视的巨大市场。传统的租房方式往往存在着信息不对称、效率低下等问题,而同城租房软件的出现,则有效地解决了这些问题,为租房市场注…

k8s日常动手实践 ~~ pod访问 pod请求 k8s api ~ 含新版带curl的busybox镜像

前言: 可以使用 Kubernetes API 获取集群信息。使用 Service Account(SA)进行身份验证,可以以安全的方式访问 Kubernetes API,而无需在 Pod 中使用明文凭据。 以下是一个使用 Service Account 访问 Kubernetes API 获…

每日OJ题_DFS回溯剪枝①_力扣46. 全排列(回溯算法简介)

目录 回溯算法简介 力扣46. 全排列 解析代码 回溯算法简介 回溯算法是一种经典的递归算法,通常⽤于解决组合问题、排列问题和搜索问题等。 回溯算法的基本思想:从一个初始状态开始,按照⼀定的规则向前搜索,当搜索到某个状态无…

【韩国】UE5的MetaHuman确实可以导入Blender进行编辑。

UE5的MetaHuman确实可以导入Blender进行编辑。根据网络上的信息,你可以将MetaHuman模型导出为FBX文件,然后在Blender中进行修改。修改完成后,你可以将其重新导入到Unreal Engine 5中4。请注意,当你在Blender中编辑模型时&#xff…

虚拟线程的定义及使用

0.前言 长期以来,虚拟线程是 Java 中最重要的创新之一。 它们是在 Project Loom 中开发的,自 Java 19 作为预览功能以来一直包含在 JDK 中,自 Java 21 作为最终版本 (JEP 444) 以来,它们已包含在 JDK 中。 1.虚拟线程的作用 任…

Docker——开源的应用容器的引擎

目录 一、前言 1.虚拟化产品有哪些 1.1寄居架构 1.2源生架构 2.虚拟化产品对比/介绍 2.1虚拟化产品 2.1.1仿真虚拟化 2.1.2半虚拟化 2.1.3全虚拟化 2.2重点 2.2.1KVM——Linux内核来完成的功能和性能 2.2.2ESXI——用的比较多 二、Docker概述 1.Docker定义 2.Do…

BGP的基本配置

l 按照以下步骤配置BGP协议: 第1步:设备基本参数配置,AS内配置IGP确保内部网络连通性; l 配置IGP(OSPF协议等)路由解决peer对等体的源和目标IP之间连通性,确保peer之间TCP(179&a…

怎样把PDF分割成多个文件?有哪些方法可以分割PDF文件?这几个方法成功率很高!

一,引言 PDF分割,即将一个完整的PDF文档拆分为多个较小的部分,是许多用户在处理 PDF文件时经常需要执行的操作。无论是为了单独提取某个章节、创建电子书章节、还是为了在多个设备间轻松共享,PDF分割都显得非常实用。本文将详细介…

动手学深度学习——矩阵

1. 基本概念 1.1 标量 标量由只有一个元素的张量表示。 所以标量计算与程度开发中的普通变量计算没有差异。 import torchx torch.tensor(3.0) y torch.tensor(2.0)x y, x * y, x / y, x**y(tensor(5.), tensor(6.), tensor(1.5000), tensor(9.))1.2 向量 向量泛化自标量…

IDEA 中如何通过连接数据库自动生成代码

目录 1、IDEA 中安装 MyBatisX 插件 2、点击 IDEA 右侧的 database 数据库按钮,点击新建数据源 Data Source 3、编辑数据库连接信息 4、选择你要生成代码的数据库表 5、编辑你代码生成的基本路径以及一些配置项 6、选择annotation:mybatis-plus3&a…