第 9 章 DeepSeek核心技术2:MLA注意力机制

DeepSeek-V2中文MoE模型实战:稀疏激活与MLA架构解析 MoE(Mixture of Experts)是一种通过动态路由实现计算稀疏化的先进大模型架构,其核心在于按需激活子网络而非全参数参与,显著降低推理成本并提升长程语义建模能力。结合MLA(Multi-Head Latent Attention)对KV缓存的语义感知压缩,MoE在中文场景中可兼顾高精度、低延迟与强领域适配性。该技术已广泛应用于医疗问诊、古籍理解、方言处理等对逻辑连贯性与文化适配性要求严苛的任务。DeepSeek-V2作为首个深度适配中文语义肌理的开源MoE模型,通过负载均衡路由、潜向量注意力与 阅读详情

DeepSeek原生应用与智能体开发实践(人工智能技术丛书)【行情 报价 价格 评测】-京东

王晓华DeepSeek开发AI应用入门书《DeepSeek原生应用与智能体开发实践》全文分享~持续更新-优快云博客

目录

9.1  从推理角度详解MLA注意力模型与代码实现

9.1.1  大模型的推理过程

9.1.2  通用大模型的显存占用量化计算

9.2  从缓存角度详解MLA注意力模型与代码实现

9.2.1  优化的MLA模型实现1:压缩低秩空间

9.2.2  优化的MLA模型实现2:核心注意力矩阵计算

9.2.3  优化的MLA模型实现3:对显存KV Cache部分的压缩

9.2.4  带有缓存的MLA注意力模型完整实现

9.3  MLA注意力模型的完整补充讲解

9.3.1  调参、记忆力以及矩阵计算优化

9.3.2  MLA、GQA以及MQA差异详解

9.4  本 章 小 结


DeepSeek中的MLA无疑是一种具有开创性的注意力机制。它巧妙地运用低秩联合压缩技术,将多个注意力头所对应的键(K)和值(V)精准地映射到一个低维潜在空间之中。这一精妙的设计,如同为数据洪流搭建了一座高效的桥梁,使得原本繁杂的KV缓存存储需求得到了显著削减,计算复杂度也大幅降低。在模型性能丝毫不打折扣的前提下,推理效率得到了质的飞跃,显存占用更是被有效控制,为深度学习模型的轻量化与高效运行开辟了新的路径。

值得一提的是,DeepSeek还巧妙地融合了MoE架构,即DeepSeekMoE技术。这一结合不仅将计算量降至最低,而且极大地提升了模型的总体性能,实现了质的飞跃。DeepSeek总体架构如图9-1所示。

图9-1   DeepSeek总体架构

在本章中,我们将以MLA为起点,开启一场探索DeepSeek技术奥秘的奇妙之旅。从MLA这一核心技术的基础原理出发,逐步深入剖析其背后的数学逻辑和实现细节,让读者能够清晰地理解它是如何在模型中发挥关键作用的。随后,我们会沿着技术的脉络,逐步展开对DeepSeek其他核心技术的介绍,带领读者全方位、多层次地领略DeepSeek这一深度学习领域杰出成果的独特魅力与卓越实力,一同探寻其在人工智能发展道路上的无限可能。

9.1  从推理角度详解MLA注意力模型与代码实现

MLA采用了一种极具巧思的压缩形式来对缓存进行优化处理。直白来讲,相较于直接存储键(K)和值(V),或是采用共享键值对的方式,MLA另辟蹊径,它先将键和值压缩成一个更为紧凑的潜在向量。在模型实际运行过程中,当需要使用这些键和值时,再精准地将其恢复出来。这种独特的处理方式,犹如为数据存储与调用打造了一个高效的“压缩包”,极大地提升了缓存的利用效率。

具体来看,MLA的核心创新之处主要体现在以下两个方面:

  • 低秩键值联合压缩:MLA突破了传统方法的局限,不再对键和值进行单独处理,而是将键和值所蕴含的信息进行深度融合,共同压缩到一个更小的潜在空间之中。这一创新举措,使得原本分散、冗余的数据信息得以高度整合,在减少数据存储空间的同时,也保留了数据的关键特征,为后续的高效计算奠定了坚实基础。
  • 矩阵乘法优化:在计算过程中,MLA通过巧妙地重排计算顺序,对矩阵乘法进行了深度优化。这一优化策略,如同为计算引擎注入了一剂高效催化剂,使得计算效率得到了显著提升,大大缩短了模型的推理时间。

在本节中,我们将从缓存优化的独特视角出发,深入剖析注意力模型在推理阶段的缓存占用情况,并通过严谨的量化计算,为读者呈现清晰的数据对比和分析。通过这一环节,读者将能够直观地了解到缓存优化对于模型性能提升的重要性。

之后,本节将详细演示MLA计算公式的推导过程,带领读者逐步揭开MLA背后的数学奥秘。同时,我们还将结合推导出的公式,实现对应的MLA注意力模型,让读者在实践中进一步加深对MLA技术的理解和掌握。

9.1.1  大模型的推理过程

我们在前面章节实现了经典生成模型,从推理输出上来看,在推理阶段,由于模型由多层Transformers堆叠而成,因此主要的计算负担落在了注意力模型内部,涉及MHA和前馈神经网络(或MoE)等核心操作。在MHA中,需要计算查询(Q)、键(K)和值(V)矩阵,以进行多头注意力的相关计算。

在大语言模型(LLM)的生成过程中,模型是基于前面的词序列来预测下一个词的。在这个过程中,每个词(token)仅与其前面的词进行交互以计算注意力,这种特定的注意力机制被称为因果注意力(Causal Attention)。在矩阵计算层面,通过一个下三角形状的因果注意力掩码(Causal Attention Mask)来确保每个词仅感知其前面的词序列。

KV Cache缓存的使用如图9-2所示。

图9-2  KV Cache缓存的使用

同样地,我们在介绍KV Cache缓存的章节中,已通过图示向读者清晰展示了输入的查询(Q)只与其对应位置前的键(K)和值(V)进行计算。因此,为了提升训练和推理的效率,在token-by-token的生成过程中,我们需要避免对前序token的重复计算。

为此,研究者们提出了一个有效的解决方案:将前序已经计算好的键(K)和值(V)缓存起来。这就是目前被广泛采用的KV Cache机制。KV Cache本质上是通过牺牲存储空间来换取时间效率的方法。然而,考虑到当前大语言模型(LLM)的规模都相当庞大,而GPU的显存空间又十分有限,使用显存来保存KV Cache势必会引发访问瓶颈。

换句话说,如果不使用KV Cache,模型将直接进行计算(包括重复计算前序token),这是一个计算密集型任务;而增加了KV Cache之后,键(K)和值(V)不再是通过实时计算获得,而是直接从存储介质中读取,这意味着GPT内核与存储介质之间需要频繁地进行数据读写,从而使任务转变为访存密集型。因此,虽然KV Cache机制解决了重复计算的问题,但存储访问的速度却直接影响了训练和推理的速度。

为了进一步优化这一流程,未来的研究可以探索更高效的存储解决方案,例如利用更快的存储介质或者优化数据访问模式,以减少访存延迟,从而进一步提高KV Cache机制的整体性能。此外,也可以考虑设计更加智能的缓存替换策略,以适应不同大小和特性的语言模型,确保在有限的显存资源下实现最优的性能提升。

9.1.2  通用大模型的显存占用量化计算

对于通用的大模型在推理阶段时,主要有三部分数据会放到显存中,如下所示:

  • 模型参数:包括Transformers、Embedding等模型参数会存到显存里。模型大小固定后,这个存储空间是固定的。
  • KV Cache:如上一节所述,前序token序列计算的KV结果,会随着后面token推理过程逐步存到显存中。存储的量随着Batch和sequence_len长度而动态变化。
  • 运行时中间数据:推理过程中产出的一些中间数据会临时存到显存中,即用即释放,一般占用空间比较小。

完整的模型推理时显存空间的占用情况如图9-3所示。

图9-3  完整的模型推理时显存空间的占用

可以看到推理阶段主要存储消耗是两部分:模型参数和KV Cache。那么模型参数占多少,KV Cache又占多少?首先我们先以一个token的计算过程为例,看下一个token计算要存储多少KV?计算公式如下:

存储的KV数目=2×注意力头数×层数

下面我们举一个简单的例子,当我们设置的Config如下:

class Config:

    n_embd = hidden_size = 384

    num_attention_heads = 6

    vocab_size = 4000

    vocab_size = 7000   #在进行SFT时的长度为7000

    assert hidden_size % num_attention_heads == 0, 'hidden_size must be divisible by num_head'

    intermediate_size = hidden_size * 4

    dropout = 0.1

    layer_norm_epsilon = layer_norm_eps = 1e-12

    num_hidden_layers = n_layers = 6

根据上面的公式计算,我们的一个KV占用的 2×6×6=72,这表示推理一个token就要缓存72个KV个数,而统计占据了多少缓存,计算公式如下:

每个token_占据空间=每个参数占据空间×参数个数×存储的KV数目

假设推理阶段是半精度(BF16,128位)参数,每个参数占2B。最终一个token的存储占用如下:

我们现在知道了一个Token计算后需要缓存的KV数量和存储量。那么对于一个实际的推理场景,还要考虑批量batch_size和序列长度seq_len两个维度,来确认整体KV Cache的存储消耗。下面是序列长度消耗公式:

单条缓存占用=单token存储×batch_size×seq_len

通过计算我们可以很轻易地得到模型在推断阶段在不同batch_size下进行推理时的显存占用。

9.1.3  手把手MLA注意力公式的总体推导

前面我们在讲解MHA多头注意力时,在讲解对于不同的输入查询(Q)、键(K)和值(V)的计算如下:

而对于MLA中的注意力维度参数矩阵的计算,我们则修改了这里可训练参数矩阵的大小,即将原有的统一维度大小的可训练参数矩阵,修改如下:

1. 查询(Q)

2. 键(K)与值(V)

可以看到,通过这种方式MLA实现了参数量的节省,并在进行注意力计算时完成了速度优化。

9.2  从缓存角度详解MLA注意力模型与代码实现

在深度学习模型日益庞大、复杂的当下,推理空间占用的优化显得尤为关键,而MLA凭借其独特的设计,在这方面表现得极为出色。其通过先进的压缩算法和巧妙的数据处理方式,将原本需要大量空间存储的键(K)和值(V)信息进行高效压缩,从而大幅降低了模型在推理过程中对内存和显存的占用。

节省推理空间占用只是MLA带来的基础益处,由此还引发了一系列积极的连锁反应。由于占用空间的减少,模型在推理时的数据读取和传输速度得到了显著提升。这就好比在一条原本拥堵的道路上,车辆(数据)能够更加顺畅地行驶,减少了等待和延误,从而加快了整个推理流程。推理速度的提升意味着模型能够更快地给出预测结果,这对于一些对实时性要求极高的应用场景,如自动驾驶、在线实时翻译等,具有至关重要的意义。

此外,MLA节省推理空间占用的特性还为模型的部署提供了更大的灵活性。在资源有限的设备上,如移动设备、嵌入式系统等,传统的注意力模型可能因空间占用过大而无法顺利运行。而MLA则打破了这一限制,使得这些设备也能够轻松承载和运行复杂的深度学习模型,极大地拓展了模型的应用  范围。

在接下来的内容中,我们将深入探究MLA是如何实现节省推理空间占用的具体机制,包括其背后的算法原理、关键技术的运用等。同时,我们还将通过实际案例和实验数据,直观地展示MLA在节省推理空间占用以及提升推理效率方面的卓越表现,让读者对这一创新技术有更全面、更深入的认识。

9.2.1  优化的MLA模型实现1:压缩低秩空间

MLA的创新之一就是低秩空间压缩,我们通过将输入的向量压缩到低秩维度从而完成了维度变换。而在具体实现上,我们则可以通过定义和组成对应的可训练参数完成模型的结构。

1. 变换参数的定义

#首先我们需要定义MLA中的参数,在这里我们定义参数如下:

self.q_proj_up = d_model * 2   #先把Query的维度升高

self.qk_proj_down = d_model     #再降低Query的维度进行计算

self.query_head_dim = self.qk_proj_down // n_heads

#这里是进行压缩kv的维度,可以设置为原有d_model大小的2/3为好

self.kv_lora_rank = int((d_model * 3)//2)     #变为hidden压缩了维度

在上面代码中,我们分别设置了MLA中的参数,q_proj_up与qk_proj_down是对输入的查询(Q)进行计算,我们采用双参数期望能够在输入的参数较少(在推理时只有1个token)的情况下,也能获得一个较为合理的特征向量。

kv_lora_rank对整体的Key和Value整合计算维度,其作用是建立一个过度的低维处理向量,用于后期的整合。

2. Query的维度变换处理

下面我们首先看Query的维度变换,代码如下所示:

self.W_dq = torch.nn.Parameter(0.01 * torch.randn(d_model, self.q_proj_dim))

self.q_norm = torch.nn.LayerNorm(self.q_proj_dim)

self.W_Uq = torch.nn.Parameter(0.01 * torch.randn(self.q_proj_dim, self.qk_proj_dim))

在这里,我们首先依据公式定义了多个映射参数,旨在对输入的特征向量x进行变换。其中,qk_proj_dim与qk_head_num的设定是为了调整维度的尺寸,以便我们人为地修正输入和输出的维度。在进行qk计算时,我们仅需确保最后一个维度保持一致即可。

而Query的计算代码如下所示:

compressed_q = x @ self.W_dq

compressed_q = self.q_norm(compressed_q)

query = compressed_q @ self.W_Uq

q_nope = self._split_heads(query, self.num_heads, self.query_head_dim)  # 将query分割为多头 shape = [-1,6,48,64]

3. Key与Value的维度变换处理

对于Key和Value的维度变换与处理,我们同样按推理公式中首先对其进行变换,之后将其变换为输入维度,代码如下所示:

q_absorb = torch.einsum('bqd,hdc->bhqc', compressed_kv, self.kv_b_proj[:,:,
:self.query
_head_dim])

这里我们首先完成了Key与Value的总体维度变换,将其拆分后我们所需要的Key和Value维度矩阵,计算过程如下:

v_nope = torch.einsum('bqc,hcd->bqhd', compressed_kv, self.kv_b_proj[:,:,self.query_head_dim:])

attn_output = torch.einsum('bhql,blhd->bhqd', attn_weights,v_nope)

顺便说一下,MLA中的低秩压缩的核心思想是:我们可以用一个较小的矩阵来近似表示一个大矩阵。而这个小矩阵正常来说是通过矩阵分解得到的,但在MLA中是直接设计小矩阵的维度,让它们通过训练自动学习到一个好的低秩表示。

秩就是信息压缩的维度,我们通过一个具体的例子来理解这个过程:想象一个5120维的向量,它可能代表了一幅图像的所有像素值。当我们用一个秩为512的变换去处理它时,本质上我们是在说:这5120个数字中,实际上可以用512个独立的特征来表达主要信息。

而这种压缩之所以有效,是因为在实际应用中:

  • 真实数据通常存在大量冗余。
  • 并非所有维度都同等重要。

因此在实际中保留最重要的维度往往足以表达数据的主要特征。

9.2.2  优化的MLA模型实现2:核心注意力矩阵计算

注意力模型MLA核心优化之一就是对核心计算使用矩阵计算的方法,在这里我们按公式完成了新的注意力计算优化,代码如下所示:

def _attn(self, q_nope, compressed_kv, attention_mask=None):

    q_cope = q_nope.clone()

    # 为了与compressed_kv结合计算attention_score

    if True:

        q_absorb = torch.einsum('bqd,hdc->bhqc', compressed_kv, self.kv_b_proj[:,:,:self.query_head_dim])

        attn_weights = torch.einsum('bhqc,bhlc->bhlq', q_absorb, q_nope)

    else:

        pass

    # 缩放注意力权重

    attn_weights = attn_weights / torch.full([], q_nope.size(-1) ** 0.5, dtype=attn_weights.dtype,device=attn_weights.device)

    query_length, key_length = q_nope.size(-2), compressed_kv.size(-2)

    causal_mask = self.bias[:, :, key_length - query_length: key_length, :key_length].to(q_nope.device)

    attn_weights = torch.where(causal_mask, attn_weights.to(attn_weights.dtype), self.mask_value)

    if attention_mask is not None:

        # 如果有额外的注意力掩码,应用它

        attn_weights = attn_weights + attention_mask

    attn_weights += self.cope(q_cope, attn_weights)

    attn_weights = torch.nn.functional.softmax(attn_weights, dim=-1)  # 计算Softmax

    attn_weights = attn_weights.type(compressed_kv.dtype)

    attn_weights = self.attn_dropout(attn_weights)  # 应用dropout

    if True:

        v_nope = torch.einsum('bqc,hcd->bqhd', compressed_kv, self.kv_b_proj[:,:,self.query_head_dim:])

        attn_output = torch.einsum('bhql,blhd->bhqd', attn_weights,v_nope)

    else:

        pass

    return attn_output, attn_weights

在上面代码中,我们分别对两个部分进行优化,首先是attn_weights的计算,而同样的attn_output部分我们也进行优化,将维度变换过程整合到一个完整过程中实现。另外,读者在具体操作时,可能注意到代码的最后部分使用了if…else条件语句进行判断。这是由于在这个位置进行维度变换时可以将if条件下的两个变换过程整合成一个。这样的计算过程虽然会节省时间,但是这种变换对于硬件资源消耗较大,部分GPU并不适合这种直接维度变换的操作,因此我们建议有兴趣的读者可以自行尝试。

9.2.3  优化的MLA模型实现3:对显存KV Cache部分的压缩

与传统的我们分别对生成的Key和Value值进行缓存不同,MLA中首先对Key和Value进行一个整体变换,将其压缩后通过维度计算重新获取对应的Key和Value值。在这个过程中我们可以通过缓存中间过程,也就是压缩的整体值从而完成对值的缓存。代码如下所示:

if layer_past is not None:

    current_kv = x @ self.W_dkv

    compressed_kv = torch.cat([layer_past, current_kv], dim=1)

else:

    compressed_kv = x @ self.W_dkv

    present = compressed_kv #在这里进行了键值对的压缩

    compressed_kv = compressed_kv@self.W_duv

    compressed_kv = self.kv_norm(compressed_kv)

在这里我们完成了对键值对的联合压缩过程,这也是MLA的创新,我们可以将其理解为:

  1. x:是输入的原始向量。
  2. W_dkv:是一个特殊的下投影矩阵,它同时服务于键和值的压缩。
  3. compressed_kv:是压缩后的潜在向量,它包含了键和值共享的信息。

compressed_kv作为一个存储关键信息供模型在计算时快速访问它包含了键和值的压缩信息,这个向量的维度一般认为比原始的键值对小得多,因此存储这个压缩向量比存储完整的键和值更节省空间。

9.2.4  带有缓存的MLA注意力模型完整实现

我们已经对MLA模型的各个模块进行了详细的讲解,而MLA注意力机制的一个显著优点,就是其在推理阶段能够出色地完成缓存的优化与利用。这一特性不仅提升了模型的运行效率,还为实际应用带来了更多的便利性。

接下来,本小节将着手构建一个带有缓存功能的MLA完整模型。通过整合缓存机制,我们将进一步展示MLA模型在实际应用中的优势。以下是实现这一完整模型的代码示例:

class CoPEMLA(torch.nn.Module):

    def __init__(self, config, layer_idx=None):

        super().__init__()

        self.config = config

        self.max_position_embeddings = max_positions = config.max_position_embeddings

        # 创建一个下三角矩阵,用于因果掩码(causal mask)

        self.bias = torch.tril(torch.ones((max_positions, max_positions), dtype=torch.bool)).view(1, 1, max_positions,max_positions)

        self.mask_value = torch.tensor(-1E+9)  # 用于掩码的极大负值

        # 维度参数

        d_model = config.hidden_size

        self.d_model = torch.tensor(d_model)

        self.num_heads = n_heads = config.num_attention_heads

        # 投影维度

        self.q_proj_up = d_model * 2         # 先把Query的维度升高

        self.qk_proj_down = d_model          # 再降低Query的维度进行计算

        self.query_head_dim = self.qk_proj_down // n_heads

        # 这里是进行压缩kv的维度,可以设置为原有d_model大小的2/3为好

        self.kv_lora_rank = int((d_model * 3)//2)     # 变为hidden压缩了维度

        self.qk_nope_head_dim = self.query_head_dim * 2

        self.kv_attn_dim = (self.query_head_dim + self.qk_nope_head_dim)

        # Q投影

        self.W_dq = torch.nn.Parameter(0.01 * torch.randn(d_model, self.q_proj_up))

        self.q_norm = torch.nn.RMSNorm(self.q_proj_up)

        self.W_Uq = torch.nn.Parameter(0.01 * torch.randn(self.q_proj_up, self.qk_proj_down))

        # KV投影

        self.W_dkv = torch.nn.Parameter(0.01 * torch.randn((d_model), (self.kv_lora_rank)))

        self.W_duv = torch.nn.Parameter(0.01 * torch.randn((self.kv_lora_rank), (self.kv_lora_rank)))

        self.kv_norm = torch.nn.RMSNorm((self.kv_lora_rank))

        self.kv_b_proj = torch.nn.Parameter(0.01 * torch.randn(size=(self.num_heads, (self.kv_attn_dim), self.kv_lora_rank)))

        # 输出

        self.W_o = torch.nn.Parameter(0.01 * torch.randn(d_model, d_model))

        self.attn_dropout = torch.nn.Dropout(config.dropout)

        #kq_weight要参与多头后的query与key计算

        self.uk_weight = torch.torch.nn.Parameter(0.01 * torch.randn(self.num_heads,self.kv_lora_rank, self.query_head_dim))

        #v_proj_weight要参与value计算,将压缩的内容重新映射回value

        self.uv_weight = torch.torch.nn.Parameter(0.01 * torch.randn(self.num_heads,self.kv_lora_rank, self.query_head_dim))

        self.cope = updat_moudle.CoPE(config.max_position_embeddings, self.query_head_dim)

    def forward(self, x, layer_past=None, attention_mask=None):

        # Q投影

        compressed_q = x @ self.W_dq

        compressed_q = self.q_norm(compressed_q)

        query = compressed_q @ self.W_Uq

        q_nope = self._split_heads(query, self.num_heads, self.query_head_dim) 

        # KV投影

        if layer_past is not None:

            current_kv = x @ self.W_dkv

            compressed_kv = torch.cat([layer_past, current_kv], dim=1)

        else:

            compressed_kv = x @ self.W_dkv

        present = compressed_kv #在这里进行了键值对的压缩

        compressed_kv = compressed_kv@self.W_duv

        compressed_kv = self.kv_norm(compressed_kv)

        # 计算注意力输出和注意力权重

        attn_output, attn_weights = self._attn(q_nope, compressed_kv,attention_mask)

        attn_output = self._merge_heads(attn_output, self.num_heads, self.query_head_dim)  # 合并多头

        attn_output = attn_output @ self.W_o

        attn_output = self.attn_dropout(attn_output)  # 应用dropout

        outputs = (attn_output, present)  # 返回注意力输出和当前的key、value

        return outputs

    def _split_heads(self, tensor, num_heads, attn_head_size):

        """

        将隐藏层维度分割为多头注意力的头和头的大小。

        """

        new_shape = tensor.size()[:-1] + (num_heads, attn_head_size)

        tensor = tensor.view(new_shape)

        return tensor.permute(0, 2, 1, 3)  # (batch, head, seq_length, head_features)

    def _attn(self, q_nope, compressed_kv, attention_mask=None):

        q_cope = q_nope.clone()

        #为了与compressed_kv结合计算attention_score

        if True:

            q_absorb = torch.einsum('bqd,hdc->bhqc', compressed_kv, self.uk_weight)

            attn_weights = torch.einsum('bhqc,bhlc->bhlq', q_absorb, q_nope)

        else:

            pass

        # 缩放注意力权重

        attn_weights = attn_weights / torch.full([], q_nope.size(-1) ** 0.5, dtype=attn_weights.dtype,device=attn_weights.device)

        query_length, key_length = q_nope.size(-2), compressed_kv.size(-2)

        causal_mask = self.bias[:, :, key_length - query_length: key_length, :key_length].to(q_nope.device)

        attn_weights = torch.where(causal_mask, attn_weights.to(attn_weights.dtype), self.mask_value)

        if attention_mask is not None:

            # 如果有额外的注意力掩码,应用它

            attn_weights = attn_weights + attention_mask

        attn_weights += self.cope(q_cope, attn_weights)

        attn_weights = torch.nn.functional.softmax(attn_weights, dim=-1)  # 计算softmax

        attn_weights = attn_weights.type(compressed_kv.dtype)

        attn_weights = self.attn_dropout(attn_weights)  # 应用dropout

        if True:

            v_nope = torch.einsum('bqc,hcd->bqhd', compressed_kv, self.uv_weight)

            attn_output = torch.einsum('bhql,blhd->bhqd', attn_weights,v_nope)

        else:

            #下面这个压缩代码在训练时会报错

            pass

        return attn_output, attn_weights

    def _merge_heads(self, tensor, num_heads, attn_head_size):

        """

        将多头注意力的头和头的大小合并回隐藏层维度。

        """

        tensor = tensor.permute(0, 2, 1, 3).contiguous()

        new_shape = tensor.size()[:-2] + (num_heads * attn_head_size,)

        return tensor.view(new_shape)

上面代码完整实现了标准的MLA注意力模型。其中加粗的部分代码为注意力计算模块,在具体使用上读者可以将MLA替代原有我们的上一章对比计算中的经典多头注意力模型,读者可以自行尝试。

9.3  MLA注意力模型的完整补充讲解

通过上面两节内容的讲解,我们了解了MLA注意力模型并完整实现了MLA注意力。在实际的MLA注意力计算中,对于多头注意力数值的计算,我们可以使用matmul的方式一次性完整地进行。然而,有时候为了更好地利用硬件计算性能,例如分布式多GPU计算单元的情况,我们则可以把整体的多头计算拆分成分布式多头计算,而在具体处理上我们可以参考如下的形式进行:

#伪代码的形式

import torch

all_querys = []

all_keys = []

all_values = []

for head in n_heads:

    query = torch.matmul(per_query,q_weight)

    key = torch.matmul(per_key,k_weight)

    value = torch.matmul(per_value,v_weight)

   

    all_querys.append(query)

    all_keys.append(key)

    all_values.append(value)

...

all_attention_outputs = []

for q,k,v in zip(all_querys,all_keys,all_values)

    attention_score = torch.matmul(q,k.transpose())

    attention_weight = torch.nn.functional.softmax(attention_score,dim=-1)

    attention_output = torch.matmul(attention_weight,v)

    all_attention_outputs.append(attention_output)

上面代码采用了伪代码的形式,清晰展示了分布式多头计算的方法。针对不同的计算硬件资源,我们可以灵活地手动调整,将单一计算任务分配到不同的计算单元上并行处理,最后将各单元的计算结果汇总整合。

除此之外,在相关公式中,我们还特别提及了为简化计算过程,MLA(假设为某算法缩写)运用了一个简洁的乘法变换法则。这一法则旨在有效减轻矩阵计算的复杂度,提升计算效率。

鉴于这两部分内容均涉及分布式硬件计算的深入应用,本书在此不做进一步的详细讨论和实现展示,仅提供伪代码及基本实现算法作为参考。对此感兴趣的读者,请自行深入探索和实践。

9.3.1  调参、记忆力以及矩阵计算优化

上面我们讲解并完成了MLA模型的基本结构,可以看到相对于传统的注意力模型,MLA在设计上采用了较多巧妙的设计,例如参数调整、矩阵计算优化以及加载了记忆力模块。下面我们分别对这些设计进行讲解。

1. 可调参的MLA注意力模型

MLA模型在设计之初,通过可变维度的参数对注意力模型的计算的大小进行修正,相对于经典的注意力模型,MLA可以根据不同的任务强度对注意力计算参数进行配置。代码如下所示:

# 投影维度

# 投影维度

self.q_proj_up = int((d_model * 3)//2)   #先把Query的维度升高

self.qk_proj_down = d_model     #再降低Query的维度进行计算

self.query_head_dim = self.qk_proj_down // n_heads

self.kv_lora_rank = int((d_model * 3)//2)     #变为hidden压缩了维度

self.qk_nope_head_dim = self.query_head_dim * 2

而为了验证我们的投影维度调整后对模型大小的影响,我们可以采用如下的参数对注意力参数进行统计,代码如下所示:

def get_parameter_number(net):

    total_num = sum(p.numel() for p in net.parameters())

    trainable_num = sum(p.numel() for p in net.parameters() if p.requires_grad)

    print({'Total': total_num, 'Trainable': trainable_num})

读者可以使用参数打印函数打印在不同条件下的MLA注意力参数。

2. MLA注意力中的记忆力模块

相对于经典的注意力机制,MLA在计算Query和Value之间添加了一个记忆力模块,self.kv_b_proj就起到这个作用,在局部缓存并计算Query、Key和Value的向量。记忆模块如下所示:

#kq_weight要参与多头后的query与key计算

#self.uk_weight = torch.torch.nn.Parameter(0.01 * torch.randn(self.num_heads,self.kv_lora_rank, self.query_head_dim))

#v_proj_weight要参与value计算,将压缩的内容重新映射回value

#self.uv_weight = torch.torch.nn.Parameter(0.01 * torch.randn(self.num_heads,self.kv_lora_rank, self.query_head_dim))

#在这里我们把上面的拟合在一起计算

self.ukv_weight = torch.torch.nn.Parameter(0.01 * torch.randn(2,self.num_heads,self.kv_lora_rank, self.query_head_dim))

在具体处理上:

q_absorb = self.kv_b_proj[0]

...

v_absorb = self.kv_b_proj[1]

q_absorb与v_absorb分别作为中间向量参与了注意力计算。

3. MLA注意力中的矩阵计算优化

我们在计算Query向量以及最终对attn_output输出计算时,分别采用了分阶段的计算方法,然而实际上我们在计算时可以根据要求对这部分的矩阵计算进行进一步的优化,代码如下所示:

q_absorb = torch.einsum('bqd,hdc->bhqc', compressed_kv, self.ukv_weight[0])

attn_weights = torch.einsum('bhqc,bhlc->bhlq', q_absorb, q_nope)

这里我们修正了矩阵计算过程,将原有的分段计算整合成一个完整的计算过程,这样带来的好处是可以加速计算过程,但是由于计算的空间需求较大,在使用上还要读者自行斟酌。

注意力矩阵计算的代码如下所示:

if True:

   v_nope = torch.einsum('bqc,hcd->bqhd', compressed_kv, self.ukv_weight[1])

   attn_output = torch.einsum('bhql,blhd->bhqd', attn_weights,v_nope)

else:

   #下面这个压缩代码在训练时会报错

   pass

读者可以自行验证比较。

4. 优化后的MLA注意力模型完整实现

对于优化后的MLA模型的完整实现,我们直接给代码,如下所示:

class CoPEMLA(torch.nn.Module):

    def __init__(self, config, layer_idx=None):

        super().__init__()

        self.config = config

        self.max_position_embeddings = max_positions = config.max_position_embeddings

        # 创建一个下三角矩阵,用于因果掩码(causal mask)

        self.bias = torch.tril(torch.ones((max_positions, max_positions), dtype=torch.bool)).view(1, 1, max_positions,max_positions)

        self.mask_value = torch.tensor(-1E+9)  # 用于掩码的极大负值

        # 维度参数

        d_model = config.hidden_size

        self.d_model = torch.tensor(d_model)

        self.num_heads = n_heads = config.num_attention_heads

        # 投影维度

        self.q_proj_up = int((d_model * 3)//2)   #先把Query的维度升高

        self.qk_proj_down = d_model     #再降低Query的维度进行计算

        self.query_head_dim = self.qk_proj_down // n_heads

        self.kv_lora_rank = int((d_model * 3)//2)     #变为hidden压缩了维度

        self.qk_nope_head_dim = self.query_head_dim * 2

        #这里是用作生成一组memory参数,

        self.kv_attn_dim = (self.query_head_dim + self.qk_nope_head_dim)

        # Q投影

        self.W_dq = torch.nn.Parameter(0.01 * torch.randn(d_model, self.q_proj_up))

        self.q_norm = torch.nn.RMSNorm(self.q_proj_up)

        self.W_Uq = torch.nn.Parameter(0.01 * torch.randn(self.q_proj_up, self.qk_proj_down))

        # KV投影

        self.W_dkv = torch.nn.Parameter(0.01 * torch.randn((d_model), (self.kv_lora_rank)))

        self.W_duv = torch.nn.Parameter(0.01 * torch.randn((self.kv_lora_rank), (self.kv_lora_rank)))

        self.kv_norm = torch.nn.RMSNorm((self.kv_lora_rank))

        # 输出

        self.W_o = torch.nn.Parameter(0.01 * torch.randn(d_model, d_model))

        self.attn_dropout = torch.nn.Dropout(config.dropout)

        #kq_weight要参与多头后的query与key计算

        #self.uk_weight = torch.torch.nn.Parameter(0.01 * torch.randn(self.num_heads,self.kv_lora_rank, self.query_head_dim))

        #v_proj_weight要参与value计算,将压缩的内容重新映射回value

        #self.uv_weight = torch.torch.nn.Parameter(0.01 * torch.randn(self.num_heads,self.kv_lora_rank, self.query_head_dim))

        #在这里把上面的拟合在一起进行优化

        self.ukv_weight = torch.torch.nn.Parameter(0.01 * torch.randn(2,self.num_heads,self.kv_lora_rank, self.query_head_dim))

        self.cope = updat_moudle.CoPE(config.max_position_embeddings, self.query_head_dim)

    def forward(self, x, layer_past=None, attention_mask=None):

        # Q投影

        compressed_q = x @ self.W_dq

        compressed_q = self.q_norm(compressed_q)

        query = compressed_q @ self.W_Uq

        q_nope = self._split_heads(query, self.num_heads, self.query_head_dim)  # 将query分割为多头 shape = [-1,6,48,64]

        # KV投影

        if layer_past is not None:

            current_kv = x @ self.W_dkv

            compressed_kv = torch.cat([layer_past, current_kv], dim=1)

        else:

            compressed_kv = x @ self.W_dkv

        present = compressed_kv #在这里进行了键值对的压缩

        compressed_kv = compressed_kv@self.W_duv

        compressed_kv = self.kv_norm(compressed_kv)

        # 计算注意力输出和注意力权重

        attn_output, attn_weights = self._attn(q_nope, compressed_kv,attention_mask)

        attn_output = self._merge_heads(attn_output, self.num_heads, self.query_head_dim)  # 合并多头

        attn_output = attn_output @ self.W_o

        attn_output = self.attn_dropout(attn_output)  # 应用dropout

        outputs = (attn_output, present)  # 返回注意力输出和当前的key、value

        return outputs

    def _split_heads(self, tensor, num_heads, attn_head_size):

        """

        将隐藏层维度分割为多头注意力的头和头的大小。

        """

        new_shape = tensor.size()[:-1] + (num_heads, attn_head_size)

        tensor = tensor.view(new_shape)

        return tensor.permute(0, 2, 1, 3)  # (batch, head, seq_length, head_features)

    def _attn(self, q_nope, compressed_kv, attention_mask=None):

        q_cope = q_nope.clone()

        #为了与compressed_kv结合计算attention_score

        if True:

            q_absorb = torch.einsum('bqd,hdc->bhqc', compressed_kv, self.ukv_weight[0])

            attn_weights = torch.einsum('bhqc,bhlc->bhlq', q_absorb, q_nope)

        else:

            pass

        # 缩放注意力权重

        attn_weights = attn_weights / torch.full([], q_nope.size(-1) ** 0.5, dtype=attn_weights.dtype,device=attn_weights.device)

        query_length, key_length = q_nope.size(-2), compressed_kv.size(-2)

        causal_mask = self.bias[:, :, key_length - query_length: key_length, :key_length].to(q_nope.device)

        attn_weights = torch.where(causal_mask, attn_weights.to(attn_weights.dtype), self.mask_value)

        if attention_mask is not None:

            # 如果有额外的注意力掩码,应用它

            attn_weights = attn_weights + attention_mask

        attn_weights += self.cope(q_cope, attn_weights)

        attn_weights = torch.nn.functional.softmax(attn_weights, dim=-1)  # 计算softmax

        attn_weights = attn_weights.type(compressed_kv.dtype)

        attn_weights = self.attn_dropout(attn_weights)  # 应用dropout

        if True:

            v_nope = torch.einsum('bqc,hcd->bqhd', compressed_kv, self.ukv_weight[1])

            attn_output = torch.einsum('bhql,blhd->bhqd', attn_weights,v_nope)

        else:

            #下面这个压缩代码在训练时会报错

            pass

        return attn_output, attn_weights

    def _merge_heads(self, tensor, num_heads, attn_head_size):

        """

        将多头注意力的头和头的大小合并回隐藏层维度。

        """

        tensor = tensor.permute(0, 2, 1, 3).contiguous()

        new_shape = tensor.size()[:-2] + (num_heads * attn_head_size,)

        return tensor.view(new_shape)

在具体使用上,读者可以替代原有的注意力模型重新完成模型的训练。

9.3.2  MLA、GQA以及MQA差异详解

MLA(多头潜在注意力)、GQA(分组查询注意力)和MQA(多查询注意力)是3种不同类型的注意力机制,它们在信息处理上的差异,我们可以将其类比为一个图书馆的信息检索系统,以更直观地理解它们各自的特点。

1. MLA

在MLA中,每个图书管理员(注意力头)都拥有自己的检索系统,但这些系统通过智能压缩技术进行了优化。具体来说:

  • 特征提取:每个图书管理员首先会提取图书的关键特征,如科技类图书的关键词、技术领域和出版年份,或文学类图书的作者风格、主题和写作手法。
  • 智能压缩:这些关键特征随后被压缩成一个精简的索引(例如,256维)。这种压缩不是简单地删减信息,而是找到最能代表原始信息的特征组合。
  • 信息重建:在需要时,可以从这些关键特征中重建出详细的检索信息。虽然可能会损失一些细节,但保留了最重要的区分性特征。

因此,MLA在信息损失方面相对较小,因为它通过智能压缩保留了最重要的特征,同时每个头仍然保持了一定的独特性。这使得MLA能够在节省存储空间的同时,仍然保持较好的性能。

2. GQA

GQA则采用了一种分组共享编目系统的方式,具体来说:

  • 分组共享:图书管理员被分成不同的组,每组共享一个专业的编目系统。例如,科技组的管理员共享一个科技文献编目系统,文学组的管理员共享一个文学作品编目系统。
  • 专业化能力:这种方式比MQA好,因为它保留了一定的专业化能力,不同领域可以有各自的检索方式。
  • 组内混合:然而,GQA仍然存在组内信息混合的问题,因为同一组内的管理员仍然需要使用相同的编目系统进行检索。

3. MQA

在MQA中,所有图书管理员共享同一个编目系统,具体来说:

  • 共享系统:无论管理员专注于哪个领域,他们都必须使用同样的检索方式。
  • 信息损失:这会导致信息损失最大,因为所有专业化的检索能力都被限制在一个统一的系   统中。

例如,科技类图书可能无法按照技术领域精确分类,文学作品可能无法按照文学流派详细归类。

MLA、GQA和MQA在信息处理上的差异主要体现在它们如何处理信息损失和保留专业化能力上。

  • MQA:信息损失最大,因为完全共享同一套系统,无法保留不同领域的专业化检索能力。
  • GQA:信息损失较大,但通过分组共享编目系统保留了一定的专业化能力,仍然存在组内信息混合的问题。
  • MLA:信息损失相对最小,因为通过智能压缩技术保留了最重要的区分性特征,同时每个头仍然保持了一定的独特性。这使得MLA能够在节省存储空间的同时,仍然保持较好的性能。

因此,MLA通过智能压缩技术实现了在节省存储空间的同时保持较好性能的目标,而GQA和MQA则在不同程度上牺牲了专业化能力以换取存储空间的节省。

9.4  本 章 小 结

在本章中,我们深入探讨了注意力模型的优化策略,特别是在减少推理过程中的资源占用方面。我们详细阐述了MLA注意力模型,并比较了MQA、GQA以及MLA三种模型的特点,了解到每种模型都有其独特的优势和重点关注的领域。

特别地,我们对MLA模型的公式推理及其实现进行了全面的介绍。通过对其算法技巧的灵活调整,MLA模型展现出了卓越的性能和效率。它不仅优化了资源利用,还提升了处理复杂任务的能力,充分展示了注意力模型在优化后的强大潜力。在未来的研究和应用中,这些优化策略将为我们提供更多可能性和创新空间。

【DeepSeek创新点】基础介绍+MLA+MoE+量化+管道并行 DeepSeek是深度求索公司推出的一些列创新型架构的总称,这一系列模型包括通用大语言模型DeepSeek v3,推理大模型DeepSeek R1,以及系列基于R1模型完成蒸馏的小型模型群。DeepSeek系列模型以其超高性能、超低成本立足于市场,不仅很快激了中国大模型落地狂潮,也在全世界范围内掀起了基于强化学习的新一轮大模型创新。DeepSeekv3、R1、蒸馏,彼此之间是什么关系?DeepSeek v3模型。 阅读详情

相关推荐

【DeepSeek 论文精读】13. DeepSeek-V3.2-Exp 技术报告与部署实践

DeepSeek 发布实验性模型 V3.2-Exp,引入DeepSeek稀疏注意力(DSA),显著提升长文本处理效率。本文详细介绍 DeepSeek-V3.2-Exp 技术报告,并提供本地部署方案的技术实现。

AI_zhiyu的博客 2377

【大模型】DeepSeek核心技术之MLA (Multi-head Latent Attention)

在讲解MLA之前,需要大家对几个基础的概念(KV Cache, Grouped-Query Attention (GQA), Multi-Query Attention (MQA),RoPE)有所了解,这些有助于理解MLA是怎么工作的,为什么需要这么做。

酒酿小圆子呀~ 3452

Whisper-MLA:优化ASR模型GPU内存的高效注意力机制

自动语音识别(ASR)技术在现代语音处理中扮演着关键角色,其核心Transformer架构通过Multi-Head Attention(MHA)机制实现序列建模。然而,MHA在处理长序列时面临GPU内存线性增长的瓶颈,特别是KV Cache机制导致显存需求激增。针对这一问题,低秩近似和潜在空间投影等高效注意力技术应运而生,通过压缩键值维度显著降低内存占用。Whisper-MLA创新性地结合联合SVD分解和维度保留策略,在保持模型性能的同时将KV Cache大小减少87.5%。这种技术特别适用于会议录音、客服

dfuw13072的博客 420

我们都想错了!DeepSeek-V2-Lite-Chat真正的技术核心,不是MoE,而是被忽略的MLA

你还在为大模型推理成本居高不下而发愁吗?当业界将目光聚焦于MoE(Mixture of Experts,混合专家模型)架构带来的参数效率提升时,DeepSeek-V2-Lite-Chat却凭借一项被忽视的核心技术——MLA(Multi-head Latent Attention,多头潜注意力),在40G单GPU上实现了163840上下文长度的高效推理。本文将深入剖析MLA如何通过**低秩分解**与...

gitblog_02381的博客 439

从MOE分诊到MLA压缩:手把手拆解DeepSeek-V3低成本背后的架构黑科技

本文深入解析DeepSeek-V3大模型如何通过MOE(混合专家)架构和MLA(多头隐式注意力)压缩技术实现低成本高性能。MOE架构通过动态路由和稀疏化训练大幅降低计算资源消耗,MLA技术则通过键值矩阵降维和混合精度优化存储效率。这些创新使DeepSeek-V3在保持95%精度的同时仅需5%存储成本,为AI模型的经济性和实用性树立了新标杆。

weixin_33737774的博客 387

简单的图书管理系统---SpringBoot+mysql通过前后端分离实现增删查改

SpringBoot+mysql通过前后端分离实现增删查改 上篇文章介绍了如何写后端接口 SpringBoot连接MySQL获取数据写后端接口 这篇文章,我们就介绍一下怎么写前端 点击修改跳出修改界面,点击添加书籍跳出添加书籍界面 点击删除,直接删除一行数据 其他的也没什么解释了,直接上代码(看不懂的可以私聊我哟) <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>

爱笑的博客 2014

DeepSeek FlashMLA:用于Hopper GPU的高效MLA解码内核

FlashMLA指的是DeepSeek针对Hopper GPU的高效MLA解码内核,针对可变长度序列进行了优化,现已投入生产。采用BF16,以及块大小为64的分页kvcache(键值缓存)。几个参数:经实测,FlashMLA在H800 SXM5平台上(CUDA 12.6),在内存受限配置下可达最高3000GB/s,在计算受限配置下可达峰值580 TFLOPS。简单点说,FlashMLA 是一个能让 LLM 模型在 H800 上跑得更快、更高效的优化方案,尤其适用于高性能 AI 任务。

BOTOAI 1202

kali虚拟机-----破解wifi密码(WiFi渗透)

文章目录一、将无线网卡挂载到 虚拟机上二、查看是否挂载成功三、查看网卡是否支持监听模式四、检查文件监听影响并杀死影响五、开启无线监听模式六、开始监听七、开始抓包(新建一个命令窗口)八、对已连接的终端进行攻击,使它掉线重连,以此来获取数据包。(新建一个命令窗口)九、开始解密 一、将无线网卡挂载到 虚拟机上 可能出现的问题:在可移动设备处无法连接无线网卡; 解决:在虚拟机设置中将usb控制器设置成如图所示。 注意要先关闭虚拟机在设置。 二、查看是否挂载成功 使用ifconfig命令查看 三、查看网卡是

weixin_46471800的博客 1万+

deepseek开源了FlashMLA,但它究竟是个啥?(终于懂了...)

《‍deepseek原理应用与实践》9.deepseek极限潜能 - MLAdeepseek开源Flash-MLA,业内纷纷表示:“这是加速AGI进程的里程碑技术”“deepseek才是真正的open AI”今天简单聊聊:1. 吃瓜:FLASH-MLA是干嘛的?2. 技术:MLA是个啥?3. 普通人有什么用:对写提示词有什么启示?【1】Flash-MLA是干嘛的?GPU高速解码器,可以理解为这是为...

shenjian58的博客 2001

HFSS入门 - 传输线线路损耗和串扰仿真

下图中两相近传输线存在端口间的串扰,而同一根传输线存在线路损耗。 我们可用S21描述端口1到端口2的线路损耗(插损?),用S13描述近端串扰,S24描述远端串扰,串扰通常要求-20dB以下。 实验目的:传输线线路损耗和串扰仿真 具体步骤: 1.草图: 其中板厚Subh为1mm。其余参数具体值如下: 2.由草图作图: 其中介质板表面设为GND。 3.设置激励:先在第一根传输线相连的XZ平面上做一...

qq_37274411的博客 9156

刷题单向链表

实现一个数据结构,维护一张表(最初只有一个元素 11)。接下来 qq 行,每行表示一次操作,操作具体间题目描述。a[i] 里面放的是下一个元素,为0代表链表结束。如单链表1->4 -> 2->3->0用数组表示是。对于每个操作 2,输出一个数字,用换行隔开。第一行一个整数 qq 表示操作次数。

power的专栏 1714

MLA是什么:DeepSeek-V2/V3推理效率跃迁的隐式KV压缩技术

Multi-head Latent Attention(MLA)是一种突破传统Attention范式的隐式键值压缩机制,其核心在于将多头K/V矩阵联合编码为低维潜在空间表示,再按需动态解码。相比标准Multi-head Attention,MLA通过可学习投影、非线性激活与残差结构实现信息蒸馏,在保障RoPE位置精度前提下显著降低KV Cache显存占用。该技术直接支撑了7B级大模型在消费级GPU(如RTX 4090)上的本地部署,并成为vscode插件、IDE代码补全等低延迟场景落地的关键基础。本文深入解

weixin_30172941的博客 240

指纹浏览器降维打击(下):Cloudflare Turnstile 与 hCaptcha 的底层交互逻辑

本文将深度拆解:Turnstile 与 hCaptcha 的 Iframe 沙箱通信机制,动态混淆 JS 与 PoW(工作量证明)的物理破解法则,以及如何通过 C++ 底层事件合成与环境基因强绑定,实现验证码的“无感过验”。

数据知道的博客 415

DeepSeek技术演进全解析:DeepSeek-V2/V3、DeepSeek-VL2、Janus/Janus-Pro 从大语言模型到多模态统一

DeepSeek技术演进路径分析:从大语言模型到多模态统一 DeepSeek团队构建了完整的大模型技术体系,其演进路径包括三大方向: 大语言模型系列:从基础型DeepSeek-LLM到采用MoE架构的V2/V3版本,通过多头潜在注意力机制和DeepSeekMoE架构显著提升效率,V3模型实现671B参数规模,训练成本降低42.5%,推理吞吐量提升5.76倍。 视觉语言模型系列:DeepSeek-VL/VL2实现跨模态理解,采用统一编码架构处理图像和文本。 多模态统一模型系列:Janus/Janus-Pro系

1828

Qt5.14.2开发Mqtt应用程序

然后,你就做不下去了…很明显,大部分博主写的东西不是缺头就是缺尾,带偏了许多读者。,因此我们需要clone的是这个分支版本,而不是这个默认的。然后将编译产物中include里的所有.h文件复制到。下载完后直接默认安装即可,这一步没什么好说的。看到了没,这个才是正确的操作方式,而主线的。信号来判断,自行实现自己的槽函数。然后选择构建方式,这里我选择的是。信号来判断自行实现自己的槽函数。信号来判断自行实现自己的槽函数。源代码,如下图所示,双击打开。收到下行消息时,可以通过连接。

Bruce.yang的嵌入式之旅 2306

ElectrolyteGPT:首个电池电解液逆向设计的生成式 AI 系统 —— 算法原理与复现解析

数据驱动的重要性:1100 万→100 万的精心筛选,比单纯增大模型更有效领域适配:fLine 表示法、正则分词、化学感知的数据增强(SMILES randomization)都是关键小模型的力量:6M 参数在特定化学空间的表现,远超通用大模型在相同任务上的零样本能力条件生成的极限:10 维条件导致模型崩溃,提示我们需要更好的条件编码策略(如 diffusion guidance、RLHF-style 偏好优化)未来方向配方实验验证。

ASKCOS博客 122

DeepSeek技术全景解析(一):一场效率革命的技术解密

DeepSeek的崛起不仅代表了国产AI技术的一次重大突破,也为全球AI领域注入了新的活力。通过一系列算法创新,DeepSeek打破了传统计算架构的限制,在效率和性能上达到了新的高度。其在MoE架构、注意力机制、推理能力等方面的创新,解决了算力瓶颈问题,并通过开源生态的力量推动了技术的普惠和发展。DeepSeek不仅展示了中国团队在AI领域的创新能力,还为全球AI产业格局的重塑提供了新的视角。从短期来看,DeepSeek的V3和R1系列将在多个行业场景中大放异彩,推动人工智能技术在更多领域的落地应用;

kaka0722ww的博客 2040

YOLOv8源码解析与复现:ShuffleAttention:高效的混合注意力机制 实现通道和空间混合注意力

随着深度学习在计算机视觉领域的飞速发展,卷积神经网络(CNNs)已经成为图像分类、目标检测、语义分割等任务的核心。为了进一步提升模型的性能,研究者们引入了“注意力机制”,旨在让网络能够动态地关注输入数据中最具信息量的部分。经典的注意力模块,如SE-Net(Squeeze-and-Excitation Networks)和CBAM(Convolutional Block Attention Module),通过通道注意力或结合通道与空间注意力,显著增强了模型的特征表达能力。

FJN110的博客 553

DeepSeek核心技术解剖:MoE架构+双向流水线如何炼成AI超体?

从模型蒸馏实战到多场景落地,一文解锁高效智能的秘密

weixin_45880725的博客 1335

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

DeepSeek-V2-Lite:如何通过MLA与MoE架构创新实现AI推理成本降低60%与性能提升236%

在当今AI大模型快速发展的时代,企业面临着前所未有的技术挑战与成本压力。传统大模型部署需要高昂的硬件投入,推理效率低下,训练成本巨大,这些问题严重制约了AI技术的规模化应用。DeepSeek-V2-Lite作为一款创新的轻量级混合专家语言模型,通过架构层面的突破性设计,为技术决策者和架构师提供了经济高效的解决方案。 ## 1. 行业痛点与技术挑战:大模型部署的现实困境 企业级AI应用面临着三大

gitblog_00223的博客 519

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

DeepSeek大模型原创核心技术解读:MLA、GRPO与MoE的工程化拆解

从工程视角拆解 DeepSeek 大模型的 MLA、GRPO 与 MoE 三大原创技术,提供可复制的 config.toml 骨架与 TaoToken 统一 Key 配置方式,并给出逐项验证注意力压缩、组内评分与路由行为的操作路径。官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 可统一管理调用链路。

weixin_35752645的博客 15

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

DeepSeek-V3.2震撼发布:DSA技术彻底解决长文本处理难题,程序员必看!

DeepSeek-V3.2-Exp引入了DeepSeek Sparse Attention (DSA)技术,通过Lightning Indexer和细粒度token选择机制,将长文本注意力计算复杂度从O(L²)降低到O(L*k)。该技术采用两阶段训练方法,在保持模型性能的同时,显著提升了长上下文处理效率。实验证明,在处理超长文本时,DSA使推理时间和GPU占用大幅降低,而输出质量几乎不变,为解决大模型长文本处理瓶颈提供了有效方案。

m0_65555479的博客 1214

【架构解析】深入浅析DeepSeek-V3的技术架构

模型层数:61 层隐藏层维度:7168前馈网络维度:18432注意力头数:128词汇表大小:129280最大位置嵌入:163840该模型通过精细的架构设计,实现了在计算效率和性能上的平衡。高性能表现:在编程、数学等任务上取得领先成绩,展现出卓越的智商水平。低成本高效能:以较低的训练成本,实现了与大型闭源模型相当的性能。技术创新:在 FP8 混合精度训练、MLA、无辅助损失负载均衡等方面取得突破。支持超长上下文:通过 YaRN 方法,模型能够处理超长文本,拓展了应用场景。开源共享。

2509_93869842的博客 932

王晓华DeepSeek开发AI应用入门书《DeepSeek原生应用与智能体开发实践》全文分享~持续更新

减少空间占用的生成模型实战与推理资源消耗量化对比。章 大模型驱动的即时金融信息采集与分析平台。在线蒸馏的损失函数与经典微分方程的求解方法。对于智能客服模型垂直领域知识注入的补充讲解。微调的目的:让生成的结果更聚焦于任务目标。减少空间占用的自回归模型代码实现与详解。驱动的即时金融信息采集与分析平台实战。未运行缓存的生成模型推理资源量化展示。自回归模型中的单分类与多分类激活函数。使用微调后的智能客服基座模型完成推理。驱动的即时金融信息采集与分析平台。在缓存的生成模型推理资源量化展示。

夏天又到了的专栏 680

DeepSeek-V3 与 GPT 核心技术原理及差异:从 Transformer、MLA 到 MoE 的架构拆解

用 TaoToken 统一入口对照 DeepSeek-V3 与 GPT 的推理差异:从 Transformer 注意力到 MLA 压缩 KV Cache、MoE 稀疏激活,附可复制配置与 401、local proxy failed 排查步骤。官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 可切换模型实测长上下文表现。

weixin_33173126的博客 161

AI Compass前沿速览:DeepSeek-V3.2、Sora 2、Imagine v0.9、LONGLIVE–英伟达、xLLM、OpenAgents

AI Compass前沿速览:DeepSeek-V3.2、Sora 2、Imagine v0.9、LONGLIVE–英伟达、xLLM、OpenAgents

丨汀、的博客 2386
上一篇: 第 8 章DeepSeek核心技术1:KV Cache加持的推理加速
下一篇: 4.5 智能体的评估与优化
夏天又到了
博客等级 码龄19年 6582粉丝 1589原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值