NLP深度学习 DAY5:Sequence-to-sequence 模型详解

Seq2Seq(Sequence-to-Sequence)模型是一种用于处理输入和输出均为序列任务的深度学习模型。它最初被设计用于机器翻译,但后来广泛应用于其他任务,如文本摘要、对话系统、语音识别、问答系统等。


核心思想

Seq2Seq 模型的目标是将一个序列(如一句话)转换为另一个序列,例如:

  • 输入:英文句子 "Hello, how are you?"

  • 输出:法语句子 "Bonjour, comment ça va ?"


模型结构

Seq2Seq 模型通常由两部分组成:

  1. 编码器(Encoder)

    • 将输入序列(如源语言句子)编码为一个固定长度的上下文向量(Context Vector),用于捕捉输入序列的语义信息。

    • 常用循环神经网络(RNN、LSTM、GRU)或 Transformer 作为编码器。

  2. 解码器(Decoder)

    • 基于编码器生成的上下文向量,逐步生成输出序列(如目标语言句子)。

    • 解码器通常也是一个循环神经网络(或 Transformer),每一步生成一个输出词,直到生成结束符(如 <EOS>)。

首先,来简单介绍下RNN(循环神经网络)结构:

1. RNN 简介

                 

                                                                RNN结构  

RNN中,每个单元接受两个输入,一个是当前时间步输入的信息 X_{t} ,另一个是上一个单元的隐藏层状态 H_{t-1}。为什么这种结构的RNN适合用于做文本等序列型数据的任务,主要是因为隐藏状态的存在使得模型具有记忆性。针对不同的任务,根据输入和输出的数量,通常对RNN结构进行调整。

RNN的常见几种结构

1.1 N to N

该模型处理的一般是输入和输出序列长度相等的任务,如

  • 词性标注
  • 语言模型(Language Modeling)

                   

1.2 1 to N

此类结构的输入长度为1,输出长度为N,一般又可以分为两种:一种是将输入只输入到第一个神经元,另一种将输入输入到所有神经元。

一般用于以下任务:

图像生成文字,一般输入 X 为图片,输出为一段图片描述性的文字;
输入音乐类别,生成对应的音乐
根据小说(新闻情感)类别,生成对应的文字

                         

                         

1.3 N to 1

和1 to N相反,一般常见任务有:

  • 序列分类任务,如给定一段文本或语音序列,归类(情感分类,主题分类等)

              

2. Seq2Seq 模型

经过上面对几种RNN结构的分析,不难发现RNN结构大多对序列的长度比较局限,对于类似于机器翻译的任务,输入和输出长度并不对等,为N to M的结构,简单的RNN束手无策,因此便有了新的模型,Encoder-Decoder模型,也就是Seq2Seq模型。

模型一般由两部分组成:第一部分是Encoder部分,用于对输入的N长度的序列进行表征;第二部分是Decoder部分,用于将Encoder提取出的表征建立起到输出的M长度序列的映射。

2.1 编码器 Encoder 

                            

Encoder部分一般使用了普通RNN的结构。其将一个序列表征为一个定长的上下文向量c,计算方式有多种,如下:

2.2 解码器 Decoder

相对于编码器而言,解码器的结构更多,下面介绍三种:

第一种

                                     

这种结构直接Encoder得到的上下文向量作为RNN的初始隐藏状态输入到RNN结构中,后续单元不接受 c 的输入,计算公式如下:

  • 隐藏状态的更新:

                                                      

   

 第二种

                              

第二种将Encoder得到的上下文向量作为每个神经单元的输入,不再是只作为第一个单元的初始隐藏状态。计算公式如下:

第三种

                             

第三种在 c 的处理上和第二种类似,但是区别在于将前一个神经单元的输出作为当前神经单元的输出。计算公式如下:

3. Seq2Seq中的Trick

3.1 Teacher Forcing

主要针对第三种Decoder应用。当某一个单元输出出错时,如果将其输出传递给下一个单元,可能导致错误传递下去。这时候,需要在一定程度上减少这种传递,就采用按一定的比例决定是否对神经单元采用上一个上一个单元的输出作为输入。即:

3.2 Attention 机制(很重要)

提出Attention机制之前,我们先来看下之前的结构有什么问题:

核心问题是当序列过长时,上述的Encoder输出的上下文向量 c 无法记住所有信息,会出现长序列梯度消失的问题。比如句子有100个词,那么c里面可能丢失了前几个词的信息。

Attention 机制是怎样的?

Attention 机制其实是参考了人在翻译文章时候的注意力机制,它会将模型的注意力放在当前翻译的单词上,换句话说,它并不像前面提到的Encoder的结构一样对整个句子用一个表征,它对于每个单词都有一个以单词为中心的表征。Encoder结构如下:

                                  

3.3 束搜索(Beam Search)

注意:Beam Search只用于测试,不用于训练过程。
当模型训练好后,给其输入一段话,其输出的每个单元的 y 给的是各个词的概率,我们如何根据概率选词且如何判断是否句子终止呢?

采取的方法是在每个时间步,选取当前时间步条件概率最大的k个词,作为该时间步的候选输出序列。如下图,k选择2,第一步p(A|c)和p(C|c)最大;第二步 P(AB|c),P(CE|c)最大;第三步P(ABD|c),P(CED|c)最大。

这样,得到的最终候选序列就是各个时间步的得到的序列的集合,下图种即为6个 {A, C, AB, CE, ABD, CED}。那么最终预测结果就是要从这6个中选出分最高的。 

这时候,可能有小伙伴会发现,那按概率算的话,序列越长的概率肯定越小呀,所以一般最后分数计算会有一个和序列长度有关的惩罚系数,如下: 

其中L为候选序列的长度,α 一般选0.75. 这样一来,序列长的对应的系数更小,而由于取了对数,概率的对数是负数,如此变化后会使得长序列和短序列处于一个可比的情形。 

4. 详细代码对比(RNN VS Seq2Seq)

4.1 基础 RNN 示例(以文本分类为例)

4.1.1 模型结构

  • 输入:一个批次的句子(或序列),已被转化为数字索引表示(如词向量)。
  • RNN:使用 nn.RNN  来提取序列特征。
  • 输出:可以是序列最后一个时间步(或平均池化后的序列向量)接一个线性层,最终输出分类结果。
import torch
import torch.nn as nnclass BasicOnlyRNNModel(nn.Module):def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim,num_layers=1, bidirectional=False):super(BasicOnlyRNNModel, self).__init__()# 词向量层self.embedding = nn.Embedding(vocab_size, embedding_dim)# 仅使用RNNself.rnn = nn.RNN(input_size=embedding_dim, hidden_size=hidden_dim, num_layers=num_layers,batch_first=True,bidirectional=bidirectional)# 双向时需要 *2self.num_directions = 2 if bidirectional else 1rnn_output_dim = hidden_dim * self.num_directions# 全连接层, 用于将 RNN 的输出映射到分类空间self.fc = nn.Linear(rnn_output_dim, output_dim)def forward(self, text):"""text: [batch_size, seq_len]"""# 嵌入: [batch_size, seq_len] -> [batch_size, seq_len, embedding_dim]embedded = self.embedding(text)# 前向传播 RNN# rnn_out: [batch_size, seq_len, hidden_dim * num_directions]# hidden : [num_layers * num_directions, batch_size, hidden_dim]rnn_out, hidden = self.rnn(embedded)  # 取最后一层的 hidden state# hidden 的形状: [num_layers * num_directions, batch_size, hidden_dim]# 若是单向 RNN,hidden[-1] 即可# 若是双向 RNN,需拼接正向和反向最后时刻if self.num_directions == 1:out = hidden[-1, :, :]  # [batch_size, hidden_dim]else:# 对双向的情况,hidden[-2] 与 hidden[-1] 分别是正向/反向最后时刻out = torch.cat((hidden[-2, :, :], hidden[-1, :, :]), dim=1)# [batch_size, hidden_dim * 2]# 全连接映射至分类空间logits = self.fc(out)  # [batch_size, output_dim]return logits# ================ 以下是训练/推理时的简单示例 ================
if __name__ == "__main__":# 假设我们有一些超参数vocab_size = 10000      # 词典大小embedding_dim = 128     # 词向量维度hidden_dim = 256        # RNN 隐藏层维度output_dim = 2          # 假设做二分类num_layers = 1          # RNN 层数bidirectional = True    # 是否使用双向model = BasicOnlyRNNModel(vocab_size=vocab_size,embedding_dim=embedding_dim,hidden_dim=hidden_dim,output_dim=output_dim,num_layers=num_layers,bidirectional=bidirectional)# 假设当前批次的输入batch_size = 32seq_len = 50batch_text = torch.randint(0, vocab_size, (batch_size, seq_len))  # [batch_size, seq_len]# 前向传播logits = model(batch_text)  # 形状: [32, 2]print(logits.shape)  # 输出: torch.Size([32, 2])
基础 RNN 模型特点
  1. 数据流:输入序列 → 嵌入层 → RNN → 最后一层 hidden state → 全连接层 → 输出。
  2. 应用场景:常用于序列分类/回归(文本分类、情感分析、序列标注等)。
  3. 优点:结构简单,实现快速。
  4. 缺点:对长序列依赖可能不够,若需要输出一个序列(而不是一个标量或一个向量),就需要进一步改造或循环解码。

二、Seq2Seq 示例(以机器翻译为例)

对于Seq2Seq模型,一般包含 Encoder(编码器)Decoder(解码器)两个主要部分(可选地加入Attention机制)。下文示例使用 LSTM 结构,演示最基础的编码器-解码器形式(不带注意力机制)。带注意力的情况会多一步 Attention 计算。

1. Encoder(编码器)

import torch
import torch.nn as nnclass Encoder(nn.Module):def __init__(self, vocab_size, embedding_dim, hidden_dim, num_layers=1):super(Encoder, self).__init__()self.hidden_dim = hidden_dimself.num_layers = num_layersself.embedding = nn.Embedding(vocab_size, embedding_dim)self.lstm = nn.LSTM(embedding_dim, hidden_dim, num_layers, batch_first=True)def forward(self, src):"""src: [batch_size, src_len]"""embedded = self.embedding(src)  # [batch_size, src_len, embedding_dim]outputs, (hidden, cell) = self.lstm(embedded)# outputs: [batch_size, src_len, hidden_dim]# hidden: [num_layers, batch_size, hidden_dim]# cell:   [num_layers, batch_size, hidden_dim]return hidden, cell

2. Decoder(解码器)

class Decoder(nn.Module):def __init__(self, vocab_size, embedding_dim, hidden_dim, num_layers=1):super(Decoder, self).__init__()self.hidden_dim = hidden_dimself.num_layers = num_layersself.embedding = nn.Embedding(vocab_size, embedding_dim)self.lstm = nn.LSTM(embedding_dim, hidden_dim, num_layers, batch_first=True)self.fc_out = nn.Linear(hidden_dim, vocab_size)  # 输出到词表大小def forward(self, tgt, hidden, cell):"""tgt: [batch_size] 当前时间步解码器输入(可以是一个词或一批词)hidden, cell: 编码器传过来的(或者上一时间步传下来的)隐状态"""# 解码器一般一次输入一个token,也可以批量处理多个# 这里假设 tgt 形状是 [batch_size],先unsqueeze到[batch_size, 1]tgt = tgt.unsqueeze(1)  # [batch_size, 1]embedded = self.embedding(tgt)  # [batch_size, 1, embedding_dim]output, (hidden, cell) = self.lstm(embedded, (hidden, cell))# output: [batch_size, 1, hidden_dim]prediction = self.fc_out(output.squeeze(1))  # [batch_size, vocab_size]return prediction, hidden, cell

3. Seq2Seq 整合 

class Seq2Seq(nn.Module):def __init__(self, encoder, decoder, device):super(Seq2Seq, self).__init__()self.encoder = encoderself.decoder = decoderself.device = devicedef forward(self, src, tgt, teacher_forcing_ratio=0.5):"""src: [batch_size, src_len]tgt: [batch_size, tgt_len] 训练时通常会有“开始标志 <sos>”和“结束标志 <eos>”。teacher_forcing_ratio: float,表示在训练时使用老师强制的概率"""batch_size = src.shape[0]tgt_len = tgt.shape[1]vocab_size = self.decoder.fc_out.out_features# 用于存储解码器每个时间步的输出词分布outputs = torch.zeros(batch_size, tgt_len, vocab_size).to(self.device)# 1. 编码器对源序列进行编码,获取初始 hidden, cellhidden, cell = self.encoder(src)# 2. 解码器的第一个输入通常是 <sos>input_t = tgt[:, 0]  # 取第0个词(即<sos>)for t in range(1, tgt_len):# 2.1 将当前时间步的 token 喂给 Decoderoutput, hidden, cell = self.decoder(input_t, hidden, cell)# output 形状: [batch_size, vocab_size]# 2.2 存储outputs[:, t, :] = output# 2.3 决定下一时间步输入:是用模型自己的预测还是用老师的标签(teacher forcing)teacher_force = torch.rand(1).item() < teacher_forcing_ratiotop1 = output.argmax(1)  # [batch_size], 最大值所对应的词索引input_t = tgt[:, t] if teacher_force else top1return outputs
Seq2Seq 模型特点
  1. 整体结构:输入序列先经过 Encoder 编码,将序列信息“压缩”到 hidden, cell(或 h_n, c_n),再在解码阶段通过 Decoder 逐步解码出目标序列。
  2. 输出:是一个序列而非一个标量/向量,通过循环或一步步地喂入上一步的输出(或真实标签)来生成。
  3. 扩展:在解码阶段可加入 Attention(Luong/Bahdanau 等),或者进一步用 Transformer 替代 RNN,形成更强大的序列到序列生成模型。
  4. 应用场景:机器翻译、文本摘要、对话系统、序列到序列的生成任务(如代码自动生成、语音到文本等)。

三、RNN VS Seq2Seq(回答问题:为什么要有编码器?直接把词向量拼在一起,然后用 RNN 1 to N 不行吗?)

在序列到序列(Seq2Seq)任务中(如机器翻译、文本摘要等),直接使用RNN后通过全连接层输出(1 to N)看似简单,但存在以下关键问题,而编码器-解码器(Encoder-Decoder)结构通过分步编码和解码的方式有效解决了这些挑战:

在序列到序列(Seq2Seq)任务中(如机器翻译、文本摘要等),直接使用词嵌入后通过全连接层(“M个神经元”)输出看似简单,但存在以下关键问题,而编码器-解码器(Encoder-Decoder)结构通过分步编码和解码的方式有效解决了这些挑战:


1. 序列的时序依赖性

自然语言中的单词顺序至关重要。例如:

  • 句子1猫追老鼠

  • 句子2老鼠追猫
    两个句子包含相同的词,但含义完全相反。

  • 简单词嵌入+全连接的缺陷
    若直接将所有词嵌入拼接成一个向量(如[猫, 追, 老鼠] → 一个长向量),模型会丢失词序信息,无法区分两个句子的差异。

  • 编码器-解码器的优势
    通过LSTM或Transformer按顺序处理输入词,编码器能够保留词序信息,并在隐藏状态中传递时序依赖关系。


2. 输入和输出的变长问题

在Seq2Seq任务中,输入和输出的长度通常是动态变化的。例如:

  • 输入:英文句子 "Hello world"(2个词)

  • 输出:中文翻译 "你好世界"(3个词)

  • 简单词嵌入+全连接的缺陷
    全连接层需要固定维度的输入和输出,无法处理变长序列。

  • 编码器-解码器的优势

    • 编码器可处理任意长度的输入序列,将其压缩为固定长度的上下文向量(hiddencell)。

    • 解码器基于上下文向量逐步生成变长的输出序列(逐词生成,直到预测到<eos>)。


3. 长距离依赖建模

语言中常存在跨越多个单词的依赖关系。例如:

  • 句子The cat, which was hungry and had been wandering the streets for days, finally found some food.
    主句的主语cat与谓语found相隔很远。

  • 简单词嵌入+全连接的缺陷
    全连接层难以捕捉长距离依赖(尤其是当句子较长时)。

  • 编码器-解码器的优势

    • LSTM通过门控机制(遗忘门、输入门)逐步更新cell状态,传递长期信息。

    • Transformer通过自注意力机制(Self-Attention)直接建模词与词之间的全局依赖。


4. 信息压缩与语义表示

编码器的核心作用是将输入序列编码为一个全局语义表示(上下文向量)。

  • 简单词嵌入+全连接的缺陷
    直接将所有词嵌入拼接为一个向量,缺乏对整体语义的抽象(相当于“词袋模型”)。

  • 编码器-解码器的优势

    • 编码器通过循环或注意力机制逐步融合上下文信息,生成紧凑的语义表示。

    • 解码器基于此表示逐步展开生成目标序列,确保输出与输入语义一致。


5. 模型效率与参数共享

  • 简单词嵌入+全连接的缺陷
    若输入长度为N,输出长度为M,全连接层的参数量为 (N×embedding_dim) × M,随序列长度增长迅速膨胀,导致计算成本高且易过拟合。

  • 编码器-解码器的优势

    • LSTM或Transformer通过参数共享(同一层处理所有时间步),参数量仅与隐藏层维度相关,与序列长度无关。

    • 例如,LSTM的参数量为 4×(embedding_dim + hidden_dim)×hidden_dim,与输入长度N无关。


6. 实际案例对比

假设用两种模型处理机器翻译任务:

方案1:简单全连接
  • 输入:将源句子所有词嵌入拼接为一个向量(如N=5embedding_dim=256 → 输入维度1280)。

  • 输出:直接映射到目标语言的词表(如vocab_size=10000),参数量为 1280×10000 = 12.8M

  • 问题

    • 无法处理长度变化的输入输出。

    • 无法建模词序和长距离依赖。

    • 参数量大且难以训练。

方案2:编码器-解码器(LSTM)
  • 编码器:LSTM逐步处理源序列,输出上下文向量(如hidden_dim=256)。

  • 解码器:LSTM基于上下文向量逐词生成目标序列。

  • 参数量:编码器和解码器的LSTM参数量均为 4×(256+256)×256 ≈ 1M,总计约2M

  • 优势

    • 处理变长序列。

    • 建模词序和长距离依赖。

    • 参数量小且高效。


总结

编码器-解码器结构通过分步编码和解码,解决了以下核心问题:

  1. 时序依赖性:保留词序信息。

  2. 变长序列处理:动态生成输出。

  3. 长距离依赖建模:通过LSTM或注意力机制捕捉全局关系。

  4. 语义压缩与传递:生成紧凑的上下文表示。

  5. 模型效率:参数共享降低计算成本。

直接使用词嵌入+全连接的方案虽然在理论上可行,但无法满足实际任务的需求。编码器-解码器及其改进模型(如Transformer)已成为序列建模的主流方法,广泛应用于机器翻译、对话系统、文本生成等任务。

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

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

相关文章

吴恩达深度学习——优化神经网络

本文来自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;仅为本人学习所用。 文章目录 优化样本大小mini-batch 优化梯度下降法动量梯度下降法指数加权平均概念偏差纠正 动量梯度下降法 RMSpropAdam优化算法 优化学习率局部最优问题&#xff08;了解&#xff09; 优…

Shell篇-字符串处理

目录 1.变量引用 2.获取字符串长度 3.字符串截取 4.删除子字符串 5.字符串替换 总结&#xff1a; Bash&#xff08;Shell 脚本&#xff09;中的字符串处理语法。以下是对其的介绍和总结&#xff1a;Bash 变量可以使用不同的语法来获取、修改和删除字符串的内容。图片中列…

CMake项目编译与开源项目目录结构

Cmake 使用简单方便&#xff0c;可以跨平台构建项目编译环境&#xff0c;尤其比直接写makefile简单&#xff0c;可以通过简单的Cmake生成负责的Makefile文件。 如果没有使用cmake进行编译&#xff0c;需要如下命令&#xff1a;&#xff08;以muduo库echo服务器为例&#xff09;…

书生大模型实战营7

文章目录 L1——基础岛提示词工程实践什么是Prompt(提示词)什么是提示工程提示设计框架CRISPECO-STAR LangGPT结构化提示词LangGPT结构编写技巧构建全局思维链保持上下文语义一致性有机结合其他 Prompt 技巧 常用的提示词模块 浦语提示词工程实践(LangGPT版)自动化生成LangGPT提…

Shadow DOM举例

这东西具有隔离效果&#xff0c;对于一些插件需要append一些div倒是不错的选择 <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"utf-8"> <title>演示例子</title> </head> <body> <style&g…

SQLAlchemy 2.0的简单使用教程

SQLAlchemy 2.0相比1.x进行了很大的更新&#xff0c;目前网上的教程不多&#xff0c;以下以链接mysql为例介绍一下基本的使用方法 环境及依赖 Python:3.8 mysql:8.3 Flask:3.0.3 SQLAlchemy:2.0.37 PyMySQL:1.1.1使用步骤 1、创建引擎&#xff0c;链接到mysql engine crea…

《LLM大语言模型+RAG实战+Langchain+ChatGLM-4+Transformer》

文章目录 Langchain的定义Langchain的组成三个核心组件实现整个核心组成部分 为什么要使用LangchainLangchain的底层原理Langchain实战操作LangSmithLangChain调用LLM安装openAI库-国内镜像源代码运行结果小结 使用Langchain的提示模板部署Langchain程序安装langserve代码请求格…

某网盘工具,限速下载上传!

聊一聊 某度盘对于个人和未开通会员的情况下&#xff0c;容量还是有点小。最近自己的盘满了&#xff0c;还有很多东西放不进去。转眼发现正在下载的寻雷&#xff0c;就点进去看看寻雷盘有多大&#xff0c;一看&#xff0c;还好&#xff0c;比某度盘容量大。 但一想&#xff0…

【后端开发】字节跳动青训营Cloudwego脚手架

Cloudwego脚手架使用 cwgo脚手架 cwgo脚手架 安装的命令&#xff1a; GOPROXYhttps://goproxy.cn/,direct go install github.com/cloudwego/cwgolatest依赖thriftgo的安装&#xff1a; go install github.com/cloudwego/thriftgolatest编辑echo.thrift文件用于生成项目&…

LabVIEW纤维集合体微电流测试仪

LabVIEW开发纤维集合体微电流测试仪。该设备精确测量纤维材料在特定电压下的电流变化&#xff0c;以分析纤维的结构、老化及回潮率等属性&#xff0c;对于纤维材料的科学研究及质量控制具有重要意义。 ​ 项目背景 在纤维材料的研究与应用中&#xff0c;电学性能是评估其性能…

Python 深拷贝与浅拷贝:数据复制的奥秘及回溯算法中的应用

引言 在 Python 编程领域&#xff0c;数据复制是极为常见的操作。而深拷贝和浅拷贝这两个概念&#xff0c;如同紧密关联却又各具特色的双子星&#xff0c;在数据处理过程中扮演着重要角色。深入理解它们&#xff0c;不仅有助于编写出高效、准确的代码&#xff0c;还能避免许多…

《基于Scapy的综合性网络扫描与通信工具集解析》

在网络管理和安全评估中&#xff0c;网络扫描和通信是两个至关重要的环节。Python 的 Scapy 库因其强大的网络数据包处理能力&#xff0c;成为开发和实现这些功能的理想工具。本文将介绍一个基于 Scapy 编写的 Python 脚本&#xff0c;该脚本集成了 ARP 扫描、端口扫描以及 TCP…

GEE | 计算Sentinel-2的改进型土壤调整植被指数MSAVI

同学们好&#xff01;今天和大家分享的是 “改进型土壤调整植被指数MSAVI”&#xff0c;它能够更准确地反映植被生长状态&#xff0c;且广泛应用于植被覆盖监测、生态环境评估等领域。 1. MSAVI 改进型土壤调整植被指数&#xff08;MSAVI&#xff09;是一种针对植被覆盖区域土…

[c语言日寄]C语言类型转换规则详解

【作者主页】siy2333 【专栏介绍】⌈c语言日寄⌋&#xff1a;这是一个专注于C语言刷题的专栏&#xff0c;精选题目&#xff0c;搭配详细题解、拓展算法。从基础语法到复杂算法&#xff0c;题目涉及的知识点全面覆盖&#xff0c;助力你系统提升。无论你是初学者&#xff0c;还是…

进阶数据结构——双向循环链表

目录 前言一、定义与结构二、特点与优势三、基本操作四、应用场景五、实现复杂度六、动态图解七、代码模版&#xff08;c&#xff09;八、经典例题九、总结结语 前言 这一期我们学习双向循环链表。双向循环链表不同于单链表&#xff0c;双向循环链表是一种特殊的数据结构&…

稀疏混合专家架构语言模型(MoE)

注&#xff1a;本文为 “稀疏混合专家架构语言模型&#xff08;MoE&#xff09;” 相关文章合辑。 手把手教你&#xff0c;从零开始实现一个稀疏混合专家架构语言模型&#xff08;MoE&#xff09; 机器之心 2024年02月11日 12:21 河南 选自huggingface 机器之心编译 机器之心…

PVE 中 Debian 虚拟机崩溃后,硬盘数据怎么恢复

问题 在 PVE 中给 Debian 虚拟机新分配硬盘后&#xff0c;通过 Debian 虚拟机开启 Samba 共享该硬盘。如果这个 Debian 虚拟机崩溃后&#xff0c;怎么恢复 Samba 共享硬盘数据。 方法 开启 Samba 共享相关知识&#xff1a;挂载硬盘和开启Samba共享。 新建一个虚拟机&#xf…

Baklib如何改变内容管理平台的未来推动创新与效率提升

内容概要 在信息爆炸的时代&#xff0c;内容管理平台成为了企业和个人不可或缺的工具。它通过高效组织、存储和发布内容&#xff0c;帮助用户有效地管理信息流。随着技术的发展&#xff0c;传统的内容管理平台逐渐暴露出灵活性不足、易用性差等局限性&#xff0c;这促使市场需…

想品客老师的第天:类

类是一个优化js面向对象的工具 类的声明 //1、class User{}console.log(typeof User)//function//2、let Hdclass{}//其实跟1差不多class Stu{show(){}//注意这里不用加逗号&#xff0c;对象才加逗号get(){console.log(后盾人)}}let hdnew Stu()hd.get()//后盾人 类的原理 类…

Java 大视界 -- Java 大数据在自动驾驶中的数据处理与决策支持(68)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…