热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

卷积与自注意力的融合之Xvolution:OntheUnificationofConvolutionandSelfattention

本文原始文档:https:www.yuque.comlartpaperszpdmekCSDN:https:blog.csdn.netP_LarTarticledetails1217

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

  • 本文原始文档:https://www.yuque.com/lart/papers/zpdmek
  • CSDN: https://blog.csdn.net/P_LarT/article/details/121719360

今天,上交&华为海思提出了新的“卷王”Xvolution:它对卷积与自注意力进行了统一集成,同时利用了卷积的局部特征提取能力与自注意力的全局建模能力。更重要的是,它通过结构重参数化思想将训练与推理进行了解耦:在训练阶段采用多分支结构进行训练,在推理阶段等价转换为单一动态卷积形式。

——“新卷王”X-volution | 将卷积与自注意力进行高效集成,上交与华为海思提出了 Xvolution:https://mp.weixin.qq.com/s/yE9nwWjAUjAkmDSpnVuzKA

从摘要读论文

Convolution and self-attention are acting as two fundamental building blocks in deep neural networks, where the former extracts local image features in a linear way while the latter non-locally encodes high-order contextual relationships.

这里很精炼的总结了卷积和自注意力计算的计算形式的差异。一个是线性提取局部特征,另一个是计算非局部的上下文关系。

Though essentially complementary to each other (i.e., first-/high-order), stat-of-the-art ar-chitectures (i.e., CNNs or transformers) lack a principled way to simultaneously apply both operations in a single computational module, due to their heterogeneous computing pattern and excessive burden of global dot-product for visual tasks.

由于两种操作的不同计算模式和自注意力在视觉任务中全局点积计算的巨大负担,所以现有的架构缺少一种在单一计算单元同时应用两种具有互补价值的操作有原则的方式。
难道作者要降低自注意力运算的负担么?

In this work, we theoretically derive a global self-attention approximation scheme, which approximates self-attention via the convolution operation on transformed features.

果然是简化了自注意力操作。

Based on the approximate scheme, we establish a multi-branch elementary module composed of both convolution and self-attention operation, capable of unifying both local and non-local feature interaction.
Importantly, once trained, this multi-branch module could be conditionally converted into a single standard convolution operation via structural re-parameterization, rendering a pure convolution styled operator named X-volution, ready to be plugged into any modern networks as an atomic operation.

自注意力操作与卷积相结合,通过近似策略以及重参数化策略进行转化后,整体形成了一个多分支的卷积结构——X-volution

Extensive experiments demonstrate that the pro-posed X-volution, achieves highly competitive visual understanding improvements (+1.2% top-1 accuracy on ImageNet classification, +1.7 box AP and +1.5 mask AP on COCO detection and segmentation).

从摘要整体来看,这篇文章主要做的就是将自注意力操作通过特定的近似策略实现了与卷积运算的统一。
也就是说,如何保证这种近似足够有效果和有效率才是关键。

主要方法

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

右侧结构为推理阶段重参数化后的结构。而模型细节应该重点看图中左侧的结构,也就是训练阶段的模型。

左侧结构的核心是一个双分支结构:

  • 右侧支路包含级联的卷积层和 BN 层(这样的结构可以在推理阶段被融合为一个单一的卷积层),这一结构可以保证模型利用卷积来获得局部信息的增强。
  • 左侧支路构建在自注意力操作之上。是一个基于(空间)像素偏移操作()与卷积构成的单元和一个 BN 层,这用于近似全局自注意力操作。

关于 Conv 和 BN 层的推理时融合是一个常用的加速推理的策略,因为 BN 层的参数在推理时是固定的,即失去了训练时需要跨 batch 计算均值标准差的需求,所以可以被简单等价于 batch 共享的分组数输入通道数(也等于输出通道数)的\(1 \times 1\)卷积,从而便于与前一层合并。当然,实际代码可以直接通过将两个结构的计算过程合并后的公式进行构造。

为了更好的表述这个将注意力和卷积结合起来的过程,接下来将按照论文中的构思过程来描述。

卷积运算

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

对于输入 X 使用空间共享的权重矩阵 W(参数与输入独立)来聚合大小为\(K \times K\)的局部窗口\(\Delta_K\)中的特征(这里公式中的\(\delta\)是相对计算的局部区域的中心的偏移量,有正有负,而在 W 中索引的形式里,通过加上了一个矩阵中心的最大距离,从而将其调整为了 W 索引形式),同时使用偏置 B 来进行调整。

这可以看作是一种一阶的线性加权操作。

自注意力运算

注意,这里讨论的是原始的全局自注意力机制,而非后续提出的各种简化版本。

自注意力通过对线性变换过的 X 计算全局的相似性关系,从而获得一个对于输入 X 的全局不共享的动态权重(参数与输入有关)。在文中所述的形式中,下式最后的等价权重可以看作是a dynamic (element-wise content-dependent) and spatially varying convolutional filter

这可以看作是一种高阶的全局操作。

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

这里要注意的是,这个公式实际上有问题。

假定按照文中的设定,输入序列设为\(X \in \mathbb{R}^{C \times L}\),序列长度\(L = H \times W\),操作中包含有独立的空间共享的线性嵌入变换权重\(W^Q, W^K, W^{V} \in \mathbb{R}^{D \times C}\)(这里按照常规设定,三者形状一致)。那么这里最后的\(W^{V}X\)应该有形状\(L \times D\)才对,但是按照其实际形状为\(D \times L\)。所以合理的形式应该是:

\[Y \in \mathbb{R}^{L \times D} \triangleq \text{softmax}(\underbrace{(W^QX)^{\top}}_{L \times D} \underbrace{W^KX}_{D \times L}) \underbrace{(W^VX)^{\top}}_{L \times D} \]

这里是无法等价于论文中公式最终的形式的,(Y 的形状与 X 并不一致),除非是一个概念意义上的等价,而非公式推导。

更合理的表示应该将该过程表示为\(Y \in \mathbb{R}^{D \times L} \triangleq \underbrace{W^VX}_{D \times L}\text{softmax}(\underbrace{(W^KX)^{\top}}_{L \times D}\underbrace{W^QX}_{D \times L})\)

但是该形式虽然在形状上符合,但是却并不能得到对应于论文公式最终的权重\(\bar{W}(X)\),除非去掉 softmax。

如果去掉 softmax,则式子可以转化为:

\[Y \in \mathbb{R}^{D \times L} \triangleq \underbrace{W^VX}_{D \times L} \underbrace{(W^KX)^{\top}}_{L \times D} \underbrace{W^QX}_{D \times L} = \underbrace{(W^{V}XX^{\top}W^{K\top}W^Q)}_{D \times C} \underbrace{X}_{C \times L} \\ \bar{W}(X) = W^{V}XX^{\top}W^{K\top}W^Q \]

看起来挺合适的 :>。
不过需要注意的是,作者并没有按照 self-attention 本身的形式来构建结构,并且后续的推导也不是基于 softmax 形式的。所以 logits 一直都是 logits????。

全局自注意力机制的近似

为了降低自注意力机制在计算动态权重过程中的\(O(n^2)\)的复杂度,作者们将目光放到了自注意力操作中的动态权重的计算上。即通过现成的(off-the-shelf)操作符例如卷积或者元素乘积等将其计算过程进行简化。

在最终的形式上,作者实际上使用空间元素偏移和元素点乘的策略将自注意力操作表示成了卷积的形式。

需要注意的是,这里的运算和注意力机制中的运算并不在数学推导上等价,而仅仅是概念上的等价。

不过,从另一个角度来说,为什么我们必须延续 self-attention 的形式来构造运算呢?self-attention 的有效点应该是其运算的逻辑,而非形式吧?我又为什么始终会期待其从 self-attention 上开始推导呢?

但是我似乎意识到了我为什么会产生这样的纠结:作者旨在近似自注意力操作,却将推导过程建立在一个仅仅是概念等价的构造之上,这就有些立不住脚了。

这不同于之前的类似于 lambda network https://www.yuque.com/lart/papers/lhnua2那样,人家直接就说了是一种新的形式,本就不再遵循 self-attention 的固有运算,所以后续的改造也无可非议,是顺理成章地。但是本文在前文的描述中却缺少了这样的铺垫与过渡。让阅读增加了不必要的期待,换句话说,如果延续 self-attention 自身的运算结构,那还是很难被简化的到本文的框架上的。

所以为了理解本文的推导,我们需要抛开 self-attention 本身的形式,而要以其运算的核心概念来作为基础,即特定位置的结果是通过利用其与全局上下文的相似关系来整合全局信息得到的。

self-attention 是一种基于相似性的聚合运算。

convolution 是一种基于预设权重的聚合运算。这里只考虑普通卷积,不考虑动态权重。

所以在本文新构造的形式中,包含了这两点——相似性计算(特征矢量的点积)、聚合操作(基于点积得到的相似性加权聚合全局特征)。

接下来介绍下作者的推导思路。

首先按照文中的表述,输入位置\(x_0\)对应的 attention logits 表示如下:

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

从这个式子可以知道,这里的 attention logits 并不是指代原始 self-attention 中的 attention logits map(即Q^TK),而是指代Q^TKV^T

由点乘运算可知,这里的\(\alpha_t \in \mathbb{R}^{C \times 1}\)是一个向量,其中用到输入 X 中的向量元素\(x_t \in \mathbb{R}^{C \times 1}\)以及对应于输入的三个权重矩阵中的元素,这里的运算都是 element-wise 乘法。

而这里使用相似性计算基本可以对标 QK 的计算。而在 QK 的计算中,每个输入特征对应的权重 w 都是全局共享通道不共享的,而这里\(w^q\)\(w^k\)被取了出来,独立于相似性计算的过程,并整合到了对于“V”的变换中。相当于直接基于了原始的输入计算了相似性。

原本对于全局的聚合,作者将其拆分成了两部分,一部分是如同卷积那样,将其局限于特定窗口内的局部区域,另一部分则是窗口之外的其他非局部区域。

考虑到图像自身具有较强的 markovian property[Efficient Inference in Fully Connected CRFs with Gaussian Edge Potentials],所以特定位置可以近似地由其局部邻域线性表示:\(x_0 \approx \sum_{x_k \in \mathring{A}}\beta_k x_k\),这里\(\beta_k\)是线性权重。于是前面式子的非局部项可以被改造如下:

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

式子中的当前位置的特征\(x_0\)被局部近似并替换成了特定窗口内的特征组合。

不失一般性,这里将非局部区域运算中被排除在外的“局部区域”的系数\(\alpha\)设为 0,从而将空缺填补上去:

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

考虑到图像的 markovian property,作者假设对于参考点\(x_0\)(以及附近的位置\(x_k\))和远离参考点的位置\(x_i\)的交互是非常弱的。所以进一步简化得到:

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

即将\(x_i\)进一步约束到\(x_0\)的临近点\(x_k\)的局部区域内。

这里有一种类似于二阶近似的感觉,通过特定位置局部邻域和其自身邻域的相似性(即邻域像素的注意力结果),从而近似表征该位置与更大范围邻域的相似性。即保留了最相关的两层关系。

通过整体替换原始式子,可以得到最终的 attention logits 形式:

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

这里的结合过程似乎有点让人迷惑。\(A\)头顶的圈是怎么没的?

\(\mathring{A}\)表示的区域中排除了中心点\(x_0\)

\[\sum_{x_i \in A} \alpha_i \ = \sum_{x_i \in U(x_k)} \alpha_i \beta_k ,\ k=0,\ \beta_0=1. \]

这局部项正好填补了被排除的中心点。所以\(A\)头顶的圈被去掉了。

于是这里公式对应的具体含义为:局部项中“局部区域中心点与其邻居的关系的加权和”加上非局部项中“局部区域中心点之外的其他点和其自身邻居的关系的加权和结果的加权和”,得到了“以\(x_0\)为中心的局部区域内所有点与各自邻居的关系加权和结果的加权和”。

两项的结合好像显得前面的“局部”与“非局部”的拆分多此一举?直接按照全局计算前面的推导看起来也是满足的?

实际上还是有必要的,因为这里的近似仅仅是在非局部项中。前式可以直接合并仅仅是因为局部近似的窗口大小和前一项局部窗口大小一样。如果不一样了,那就不能这样融合了。

最后通过这样一个局部邻域的聚合过程,实现了对于全局关系的近似,即Pixel Shift Self-Attention (PSSA)

接下来就是本文的重头戏,即如何将前述的推导得到的形式使用空间偏移和卷积操作实现出来。

Pixel Shift Self-Attention (PSSA)的实现方式

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

上图展示了附录中 PSSA 的具体过程。文章正文中的描述对此非常容易让人产生误解(这个糟糕的写作风格:<)。

首先对特征图进行空间偏移,沿着给定方向的八个方向各偏移 L 个像素位置,之后使用 Key 变换整合特征。

然后对经过 Query 变换后的原始特征和 Key 变换之后的特征使用 element-wise 乘法获得转换后的特征。

实际上,shift-product 操作构建邻域点之间的上下文关系,并且通过分层堆叠的形式,上下文信息被逐渐传播到全局范围。

最后通过使用卷积加权求和聚集这些邻域信息来获得一个近似的 self-attention map。

由于空间偏移、element-wise product 和加权求和的复杂度都是\(O(n)\),所以整体构成的 PSSA 也是\(O(n)\)复杂度的运算单元。

总而言之,通过这样的策略,self-attention 被转换为一个作用域变换特征上的标准卷积操作。通过多层堆叠,该结构可以通过上下文关系传播来实现对于全局自注意力的有效近似。

等等~说到这里,我们需要考虑,为什么前面的式子就可以通过这样的偏移加变换的形式来等效呢?

在最终的公式中,attention 过程可以拆分成级联的相似性计算和局部集成拆两步操作,即先在每个小的局部区域计算相似性,之后再集成所有的这些小区域的结果来得到最终的结果。

  • 每个小的局部区域的相似性计算可以直接通过空间偏移和乘法来实现。特定方向的偏移和乘法实现了特定方向上距离等于偏移量的两点之间的相似性计算。通过使用(共享?)权重\(w^k \& w^q\)(key 变换和 query 变换),不同方向的特征图会被单独处理。从而可以得到每个位置和相邻局部区域内各点之间的相似性。
    • 这里的计算过程的加权明显是在计算相关性(乘法)之前的,和前面公式中的设计并不一致(真不知道作者怎么回事)。
  • 通过 query 变换后的原始特征与 key 变换后的偏移特征计算得到相似性之后,接下来就该第一次聚合了(即后续推导中和忽略的系数\(\beta_k\)),正常来说,这该将不同的偏移的结果进行合并,从而得到局部聚合后的结果。之后该第二次加权聚合了,在特征图上应用卷积来整合局部特征(我觉得这里的参数可以看作是\(w^v\))。
  • 两次加权聚合进而实现了对于全局信息的近似聚合。获得的值可以看作是对于局部区域内的位置\(x_i\)的一个动态加权后的结果。作者提到“实际上,我们通常通过分层堆叠使用 PSSA,并且可以省略堆叠结构中的加权操作,因为分层堆叠意味着加权邻居像素的操作。”所以应该是第一次聚合被省略了,直接一次聚合搞定。

对卷积和自注意力的统一

关于卷积和自注意力是互补的,作者总结的内容非常精辟,这里摘录下来:

The convolution employs the inductive bias of locality and isotropy endowing it the capability of translation equivariance [1]. However, the local inherent instinct makes convolution failed to establish the long-term relationship which is necessary to formulate a Turing complete atomic operator [4, 23].

In contrast to convolution, self-attention discards mentioned inductive bias, so-called low-bias, and strives to discover natural patterns from a data-set without explicit model assumption. The low-bias principle gives self-attention the freedom to explore complex relationships (e.g., long-term dependency, anisotropic semantics, strong local correlations in CNNs [7], e.t.c.), resulting in the scheme usually requires pre-training on extra oversize data-sets (e.g., JFT-300M, ImageNet21K). In addition, self-attention is difficult to optimize, requiring a longer training cycle and complex tricks [31, 20, 38, 2].

Witnessing this, several works [1, 36] propose that convolution should be introduced into the self-attention mechanism to improve its robustness and performance.

In short, different model assumptions are adopted to make convolution and self-attention complement each other in terms of optimization characteristics (i.e., well-condition/ill-condition), attention scope (i.e., local/long-term), and content dependence (content-dependent/independent) e.t.c..

这里总结道:不同的模型假设被用来使卷积和自注意互相补充,例如在优化特性方面(即 well-condition/ill-condition),注意范围方面(即局部还是长距离)以及内容依赖性方面 (内容依赖的还是内容独立的)等。

为了实现对于二者的统一,现有方法已经有一些尝试,例如 Cvt: Introducing convolutions to vision transformers 和 AANet: Attention augmented convolutional networks。然而他们的策略过于粗糙,例如直接分层堆叠或者是拼接,这并不便于获得一个单独的原子操作(即在相同模块中应用卷积和自注意操作),并且使得结构不够标准化。虽然两种操作之间差异明显的计算模式带来了许多阻碍,但是通过前面的近似处理,二者可以实现基于统一的模式来实现,即卷积操作。从另一个视角来看,卷积反过来也可以看作是自注意力操作的空间归纳偏置的形式。由此,作者们将利用二者构建了图 1 所示的多分支结构,这可以同时受益于二者。

于是训练阶段,该结构的公式表达如下:

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

这里的运算中的相关计算,由于使用空间偏移来模拟领域与领域的关系建模,所以上式展现的局部运算形式中只体现了偏移后的运算。

通过已经计算得到的相关性和卷积操作,自注意力运算被转化成了一个局部的动态卷积的过程。

这样的结构通过重参数化在推理时可以合并为一个独立的动态卷积算子,命名为X-volution

实验结果

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

卷积与自注意力的融合之X-volution: On the Unification of Convolution and Self-attention

感想

论文的方法包装的有点过度,想法确实挺有趣,将全局的自注意力计算近似为一种局部范围内各点与其自身局部范围的关系的整体聚合

但是文章的方法介绍却并不清晰。

最为让我不舒服的一点就是,公式与方法的对应并不紧密,看了半天也对不上方法的介绍。不知道这些公式在写给谁看。

极其不痛快的一次阅读经历。

链接

  • 论文:https://arxiv.org/pdf/2106.02253.pdf
  • Vision Transformer: https://www.yuque.com/lart/architecture/nmxfgf
  • Pytorch中Spatial-Shift-Operation的5种实现策略:https://www.yuque.com/lart/ugkv9f/nnor5p

推荐阅读
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 深度学习中的Vision Transformer (ViT)详解
    本文详细介绍了深度学习中的Vision Transformer (ViT)方法。首先介绍了相关工作和ViT的基本原理,包括图像块嵌入、可学习的嵌入、位置嵌入和Transformer编码器等。接着讨论了ViT的张量维度变化、归纳偏置与混合架构、微调及更高分辨率等方面。最后给出了实验结果和相关代码的链接。本文的研究表明,对于CV任务,直接应用纯Transformer架构于图像块序列是可行的,无需依赖于卷积网络。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • 本文整理了315道Python基础题目及答案,帮助读者检验学习成果。文章介绍了学习Python的途径、Python与其他编程语言的对比、解释型和编译型编程语言的简述、Python解释器的种类和特点、位和字节的关系、以及至少5个PEP8规范。对于想要检验自己学习成果的读者,这些题目将是一个不错的选择。请注意,答案在视频中,本文不提供答案。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • Gitlab接入公司内部单点登录的安装和配置教程
    本文介绍了如何将公司内部的Gitlab系统接入单点登录服务,并提供了安装和配置的详细教程。通过使用oauth2协议,将原有的各子系统的独立登录统一迁移至单点登录。文章包括Gitlab的安装环境、版本号、编辑配置文件的步骤,并解决了在迁移过程中可能遇到的问题。 ... [详细]
author-avatar
华浦即热式电热水龙头_376
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有