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

transfomer网络构建

目录

整体架构

详细模块分析

Transformer 算法的演进

代码讲解

1. 导入必要的库

2. InputEmbeddings 类

3. PositionalEncoding 类

4. LayerNormalization 类

5. FeedForwardBlock 类

6. MultiHeadAttentionBlock 类

7. ResidualConnection 类

8. EncoderBlock 类

9. Encoder 类

10. DecoderBlock 类

11. Decoder 类

12. ProjectionLayer 类

13. Transformer 类

14. build_transformer 函数

完整代码实现transfomer


整体架构

项目的核心目标是构建一个基于 Transformer 架构的神经网络模型,用于实现英法(en - it)双语的机器翻译任务。

配置管理:借助配置文件来设定模型训练所需的各类参数,像批次大小、训练轮数、学习率等。

数据集处理:加载数据集,对数据进行分词处理,并且构建自定义的数据集类,从而适配模型的输入要求。

模型构建:依据 Transformer 架构构建模型,包含输入嵌入层、位置编码层、编码器和解码器等组件。

训练过程:对模型进行训练,保存模型参数,同时使用 TensorBoard 记录训练过程中的损失值。

详细模块分析

配置管理 (config.py)

定义和获取模型训练所需的配置参数

def get_config():
    return {
        "batch_size": 8,
        "num_epochs": 20,
        "lr": 10 ** -4,
        "seq_len": 350,
        "d_model": 512,
        "datasource": 'opus_books',
        "lang_src": "en",
        "lang_tgt": "it",
        "model_folder": "weights",
        "model_basename": "tmodel_",
        "tokenizer_file": "tokenizer_{0}.json",
        "experiment_name": "runs/tmodel"
    }

这些参数涵盖了训练的基本设置、数据集信息、模型保存路径等内容。

数据集处理 (dataset.py)

该模块的主要任务是构建自定义的数据集类 BilingualDataset

对原始文本进行分词处理

为输入序列添加特殊标记(如 [SOS]、[EOS]、[PAD])

对序列进行填充,使其长度一致

生成编码器和解码器的掩码

class BilingualDataset(Dataset):
    def __init__(self, ds, tokenizer_src, tokenizer_tgt, src_lang, tgt_lang, seq_len):
        # 初始化数据集和分词器等
        ...    def __getitem__(self, index):
        # 获取数据并进行处理
        ...

模型构建 (model.py)

此模块按照 Transformer 架构构建模型,主要包含以下组件:

输入嵌入层 (InputEmbeddings):把输入的词索引转换为词向量。

位置编码层 (PositionalEncoding):为输入序列添加位置信息。

多头注意力机制 (MultiHeadAttentionBlock):在不同的子空间中计算注意力分数。

前馈网络层 (FeedForwardBlock):对多头注意力机制的输出进行非线性变换。

编码器和解码器 (Encoder 和 Decoder):由多个编码器块和解码器块组成。

投影层 (ProjectionLayer):把解码器的输出映射到词表大小的维度。

class Transformer(nn.Module):
    def __init__(self, encoder, decoder, src_embed, tgt_embed, src_pos, tgt_pos, projection_layer):
        # 初始化模型组件
        ...    def encode(self, src, src_mask):
        # 编码器前向传播
        ...    def decode(self, encoder_output, src_mask, tgt, tgt_mask):
        # 解码器前向传播
        ...    def project(self, x):
        # 投影层前向传播
        ...

训练过程 (train.py)

该模块负责模型的训练,具体步骤如下:

加载数据集和分词器。

构建模型和优化器。

定义损失函数。

分轮次和批次进行训练,同时记录损失值。

每个轮次结束后保存模型参数。

def train_model(config):
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    # 确保保存模型的文件夹存在
    ...
    train_dataloader, val_dataloader, tokenizer_src, tokenizer_tgt = get_ds(config)
    model = get_model(config, tokenizer_src.get_vocab_size(), tokenizer_tgt.get_vocab_size()).to(device)
    writer = SummaryWriter(config['experiment_name'])
    optimizer = torch.optim.Adam(model.parameters(), lr=config['lr'], eps=1e-9)
    loss_fn = nn.CrossEntropyLoss(ignore_index=tokenizer_src.token_to_id('[PAD]'), label_smoothing=0.1)
    # 分轮次和批次进行训练
    ...

Transformer 算法的演进

原始 Transformer

Transformer 最初在论文《Attention Is All You Need》中被提出,其核心创新点在于摒弃了传统的循环神经网络(RNN)和卷积神经网络(CNN),完全基于注意力机制构建模型。这种架构具有以下优势:

并行计算能力:能够并行处理输入序列,从而显著提高训练速度。

长序列处理能力:通过注意力机制,能够有效捕捉序列中的长距离依赖关系。

BERT(Bidirectional Encoder Representations from Transformers)

BERT 是基于 Transformer 编码器构建的预训练语言模型,其主要创新点在于:

双向训练:采用双向的注意力机制,能够同时考虑上下文信息,从而学习到更强大的语言表示。

预训练 - 微调(Pretraining - Fine-tuning):先在大规模无监督数据上进行预训练,然后在特定任务上进行微调,大大提高了模型在各种自然语言处理任务上的性能。

GPT(Generative Pretrained Transformer)

GPT 是基于 Transformer 解码器构建的预训练语言模型,其主要特点是:

单向训练:采用单向的注意力机制,从左到右生成文本。

生成式任务:在文本生成任务上表现出色,如对话生成、文本摘要等。

代码讲解

1. 导入必要的库

import torch
import torch.nn as nn
import math

torch:PyTorch 深度学习框架的核心库,提供了张量操作和自动求导等功能。

torch.nn:包含了构建神经网络所需的各种模块和层。

math:Python 标准库中的数学模块,用于进行数学计算。

2. InputEmbeddings 类

class InputEmbeddings(nn.Module):
    # 词嵌入本质会训练一个矩阵, (vocab_size, d_model)
    def __init__(self, d_model: int, vocab_size: int):
        super().__init__()
        self.d_model = d_model
        self.vocab_size = vocab_size
        self.embedding = nn.Embedding(vocab_size, d_model)    def forward(self, x):
        # nn.Embedding 里面是有参数的, 使用的时候相当于 lookup table
        # 乘上权重来自于论文 3.4
        return self.embedding(x) * math.sqrt(self.d_model)

功能:将输入的词索引转换为对应的词向量。

初始化:d_model:词向量的维度。

vocab_size:词汇表的大小。

nn.Embedding(vocab_size, d_model):创建一个嵌入层,将词索引映射到 d_model 维的向量空间。

前向传播:self.embedding(x):通过嵌入层将输入的词索引转换为词向量。

* math.sqrt(self.d_model):乘以 sqrt(d_model) 是为了缩放词向量,这是论文中的做法。

3. PositionalEncoding 类

class PositionalEncoding(nn.Module):
    # d_model 是每个位置的向量维度, seq_len 是总共多少个位置, dropout 防止过拟合
    def __init__(self, d_model: int, seq_len: int, dropout: float):
        super().__init__()
        self.d_model = d_model
        self.seq_len = seq_len
        self.dropout = nn.Dropout(dropout)        # 创建一个矩阵, 形状(seq_len, d_model)
        pe = torch.zeros(seq_len, d_model)
        # 创建一个向量 (seq_len, 1)
        position = torch.arange(0, seq_len, dtype=torch.float).unsqueeze(1)
        # 实现公式 3.5, 但是在 log space 下计算的
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)        pe = pe.unsqueeze(0)  # (1, seq_len, d_model)        # 不需要去训练的参数, 最终它也是会保存在模型文件中的, 可以把它注册到 buffer 中
        self.register_buffer('pe', pe)    def forward(self, x):
        # (batch, seq_len, d_model)
        x = x + (self.pe[:, :x.shape[1], :]).requires_grad_(False)
        return self.dropout(x)

功能:为输入的词向量添加位置信息,因为 Transformer 模型本身不具备捕捉序列顺序的能力。

初始化:d_model:词向量的维度。

seq_len:序列的最大长度。

dropout:Dropout 概率,用于防止过拟合。

pe:位置编码矩阵,形状为 (seq_len, d_model)。

position:位置向量,形状为 (seq_len, 1)。

div_term:用于计算位置编码的分母项。

self.register_buffer('pe', pe):将位置编码矩阵注册为缓冲区,这样它不会被视为模型的可训练参数,但会随模型一起保存。

前向传播:x + (self.pe[:, :x.shape[1], :]).requires_grad_(False):将位置编码矩阵添加到输入的词向量上。

self.dropout(x):对添加了位置编码的词向量应用 Dropout。

4. LayerNormalization 类

class LayerNormalization(nn.Module):# layer norm 是对每个样本不同位置的向量求均值和方差,然后再进行归一化# features 是一个样本的特征数量def __init__(self, features: int, eps: float = 1e-6):super().__init__()
        self.eps = eps
        self.alpha = nn.Parameter(torch.ones(features))
        self.bias = nn.Parameter(torch.zeros(features))def forward(self, x):# x: (batch, seq_len, hidden_size) 每条文本的每个token由多个特征构成
        mean = x.mean(dim=-1, keepdim=True)
        std = x.std(dim=-1, keepdim=True)return self.alpha * (x - mean) / (std + self.eps) + self.bias

功能:对输入的张量进行层归一化操作,使得每个样本的特征向量具有零均值和单位方差。

初始化:features:输入张量的特征维度。

eps:一个小的常数,用于避免分母为零。

self.alpha:可训练的缩放因子,形状为 (features,)。

self.bias:可训练的偏移量,形状为 (features,)。

前向传播:mean = x.mean(dim=-1, keepdim=True):计算每个样本的特征向量的均值。

std = x.std(dim=-1, keepdim=True):计算每个样本的特征向量的标准差。

self.alpha * (x - mean) / (std + self.eps) + self.bias:进行层归一化操作,并应用缩放因子和偏移量。

5. FeedForwardBlock 类

class FeedForwardBlock(nn.Module):def __init__(self, d_model: int, d_ff: int, dropout: float):super().__init__()
        self.linear_1 = nn.Linear(d_model, d_ff)
        self.dropout = nn.Dropout(p=dropout)
        self.linear_2 = nn.Linear(d_ff, d_model)def forward(self, x):# 实现的就是论文中 3.3 FFN(x)return self.linear_2(self.dropout(torch.relu(self.linear_1(x))))

功能:实现一个前馈神经网络块,包含两个线性层和一个 ReLU 激活函数。

初始化:d_model:输入和输出的特征维度。

d_ff:中间层的特征维度。

dropout:Dropout 概率,用于防止过拟合。

self.linear_1:第一个线性层,将输入从 d_model 维映射到 d_ff 维。

self.linear_2:第二个线性层,将中间层的输出从 d_ff 维映射回 d_model 维。

前向传播:torch.relu(self.linear_1(x)):对输入应用第一个线性层和 ReLU 激活函数。

self.dropout(...):对激活函数的输出应用 Dropout。

self.linear_2(...):对 Dropout 的输出应用第二个线性层。

6. MultiHeadAttentionBlock 类

class MultiHeadAttentionBlock(nn.Module):
    def __init__(self, d_model: int, h: int, dropout: float):
        super().__init__()        self.d_model = d_model
        self.h = h
        assert d_model % h == 0, "d_model 必须可以整除 h"
        # 每个 head 对应的维度是多大
        self.d_k = d_model // h        self.w_q = nn.Linear(d_model, d_model, bias=False)
        self.w_k = nn.Linear(d_model, d_model, bias=False)
        self.w_v = nn.Linear(d_model, d_model, bias=False)
        self.w_o = nn.Linear(d_model, d_model, bias=False)        self.dropout = nn.Dropout(dropout)    @staticmethod
    def attention(query, key, value, mask, dropout: nn.Dropout):
        d_k = query.shape[-1]        attention_scores = (query @ key.transpose(-2, -1)) / math.sqrt(d_k)
        if mask is not None:
            # 将 mask 矩阵中值为 0的位置,对应在 attention_scores 里面的值用 -1e9 替换
            attention_scores.masked_fill_(mask == 0, -1e9)
        attention_scores = attention_scores.softmax(dim=-1)  # (Batch, h, seq_len, seq_len)
        if dropout is not None:
            attention_scores = dropout(attention_scores)        return (attention_scores @ value), attention_scores    def forward(self, q, k, v, mask):
        query = self.w_q(q)  # Q
        key = self.w_k(k)  # K
        value = self.w_v(v)  # V        # 多头注意力机制 切割 Q K V 为了给不同的 heads
        # (Batch, Seq_Len, d_model) --> (Batch, Seq_Len, h, d_k) --> (Batch, h, Seq_Len, d_k)
        query = query.view(query.shape[0], query.shape[1], self.h, self.d_k).transpose(1, 2)
        key = key.view(key.shape[0], key.shape[1], self.h, self.d_k).transpose(1, 2)
        value = value.view(value.shape[0], value.shape[1], self.h, self.d_k).transpose(1, 2)        x, self.attention_scores = MultiHeadAttentionBlock.attention(query, key, value, mask, self.dropout)
        # (Batch, h, seq_len, d_k) --> (Batch, Seq_Len, h, d_k) --> (Batch, Seq_Len, d_model)
        x = x.transpose(1, 2).contiguous().view(x.shape[0], -1, self.h * self.d_k)        return self.w_o(x)

功能:实现多头注意力机制,通过多个头并行计算注意力分数,然后将结果拼接并线性变换。

初始化:d_model:输入和输出的特征维度。

h:头的数量。

self.d_k:每个头的特征维度,d_k = d_model // h。

self.w_q、self.w_k、self.w_v:分别用于生成查询(Q)、键(K)和值(V)的线性层。

self.w_o:用于将多头注意力的输出进行线性变换的线性层。

self.dropout:Dropout 概率,用于防止过拟合。

attention 静态方法:计算注意力分数:attention_scores = (query @ key.transpose(-2, -1)) / math.sqrt(d_k)。

如果有掩码(mask),则将掩码矩阵中值为 0 的位置对应的注意力分数替换为 -1e9。

对注意力分数应用 Softmax 函数:attention_scores.softmax(dim=-1)。

如果有 Dropout,则对注意力分数应用 Dropout。

返回注意力加权的值和注意力分数。

前向传播:通过线性层生成查询(Q)、键(K)和值(V)。

将 Q、K、V 分割成多个头:query.view(...).transpose(1, 2)。

调用 attention 方法计算多头注意力的输出。

将多头注意力的输出拼接并线性变换:x.transpose(1, 2).contiguous().view(...); self.w_o(x)。

7. ResidualConnection 类

class ResidualConnection(nn.Module):
    def __init__(self, features: int, dropout: float):
        super().__init__()
        self.dropout = nn.Dropout(dropout)
        self.norm = LayerNormalization(features=features)    def forward(self, x, sublayer):
        # 此处和论文中 transformer 给的图略有不同, 先进行 norm 再进行 self-attention 或 feed-forward
        return x + self.dropout(sublayer(self.norm(x)))

功能:实现残差连接,将输入和子层的输出相加,有助于缓解梯度消失问题。

初始化:features:输入和输出的特征维度。

dropout:Dropout 概率,用于防止过拟合。

self.norm:层归一化层。

前向传播:对输入应用层归一化:self.norm(x)。

将归一化后的输入传递给子层:sublayer(self.norm(x))。

对 子层的输出应用 Dropout:self.dropout(...)。

将输入和子层的输出相加:x + ...。

8. EncoderBlock 类

class EncoderBlock(nn.Module):
    def __init__(self, features: int, self_attention_block: MultiHeadAttentionBlock,
                 feed_forward_block: FeedForwardBlock, dropout: float):
        super().__init__()
        self.self_attention_block = self_attention_block
        self.feed_forward_block = feed_forward_block
        self.residual_connections = nn.ModuleList(
            [ResidualConnection(features, dropout) for _ in range(2)]
        )    def forward(self, x, src_mask):
        x = self.residual_connections[0](x, lambda x: self.self_attention_block(x, x, x, src_mask))
        x = self.residual_connections[1](x, self.feed_forward_block)
        return x

功能:实现编码器块,包含一个自注意力层和一个前馈神经网络层,以及两个残差连接。

初始化:features:输入和输出的特征维度。

self_attention_block:多头自注意力块。

feed_forward_block:前馈神经网络块。

self.residual_connections:包含两个残差连接的模块列表。

前向传播:对输入应用自注意力层和第一个残差连接:self.residual_connections[0](x, lambda x: self.self_attention_block(x, x, x, src_mask))。

对自注意力层的输出应用前馈神经网络层和第二个残差连接:self.residual_connections[1](x, self.feed_forward_block)。

9. Encoder 类

class Encoder(nn.Module):
    def __init__(self, features: int, layers: nn.ModuleList):
        super().__init__()
        self.layers = layers
        self.norm = LayerNormalization(features=features)    def forward(self, x, mask):
        for layer in self.layers:
            x = layer(x, mask)
        return self.norm(x)

功能:实现编码器,由多个编码器块组成,最后进行层归一化。

初始化:features:输入和输出的特征维度。

layers:包含多个编码器块的模块列表。

self.norm:层归一化层。

前向传播:依次将输入传递给每个编码器块:for layer in self.layers: x = layer(x, mask)。

对最后一个编码器块的输出应用层归一化:self.norm(x)。

10. DecoderBlock 类

class DecoderBlock(nn.Module):
    def __init__(self, features: int, self_attention_block: MultiHeadAttentionBlock,
                 cross_attention_block: MultiHeadAttentionBlock,
                 feed_forward_block: FeedForwardBlock, dropout: float):
        super().__init__()
        self.self_attention_block = self_attention_block
        self.cross_attention_block = cross_attention_block
        self.feed_forward_block = feed_forward_block
        self.residual_connections = nn.ModuleList(
            [ResidualConnection(features, dropout) for _ in range(3)]
        )    def forward(self, x, encoder_output, src_mask, tgt_mask):
        x = self.residual_connections[0](x, lambda x: self.self_attention_block(x, x, x, tgt_mask))
        x = self.residual_connections[1](x, lambda x: self.cross_attention_block(x, encoder_output, encoder_output,
                                                                                 src_mask))
        x = self.residual_connections[2](x, self.feed_forward_block)
        return x

功能:实现解码器块,包含一个自注意力层、一个交叉注意力层和一个前馈神经网络层,以及三个残差连接。

初始化:features:输入和输出的特征维度。

self_attention_block:多头自注意力块。

cross_attention_block:多头交叉注意力块。

feed_forward_block:前馈神经网络块。

self.residual_connections:包含三个残差连接的模块列表。

前向传播:对输入应用自注意力层和第一个残差连接:self.residual_connections[0](x, lambda x: self.self_attention_block(x, x, x, tgt_mask)),这里的 tgt_mask 用于屏蔽目标序列中后续位置的信息,避免解码器提前看到未来的信息。

对自注意力层的输出应用交叉注意力层和第二个残差连接:self.residual_connections[1](x, lambda x: self.cross_attention_block(x, encoder_output, encoder_output, src_mask)),交叉注意力层中,查询来自解码器当前层的输入,键和值来自编码器的输出,src_mask 用于屏蔽源序列中填充位置的信息。

对交叉注意力层的输出应用前馈神经网络层和第三个残差连接:self.residual_connections[2](x, self.feed_forward_block)。

11. Decoder 类

class Decoder(nn.Module):
    def __init__(self, features: int, layers: nn.ModuleList):
        super().__init__()
        self.layers = layers
        self.norm = LayerNormalization(features=features)    def forward(self, x, encoder_output, src_mask, tgt_mask):
        for layer in self.layers:
            x = layer(x, encoder_output, src_mask, tgt_mask)
        return self.norm(x)

功能:实现解码器,由多个解码器块组成,最后进行层归一化。

初始化:features:输入和输出的特征维度。

layers:包含多个解码器块的模块列表。

self.norm:层归一化层。

前向传播:依次将输入、编码器输出、源序列掩码和目标序列掩码传递给每个解码器块:for layer in self.layers: x = layer(x, encoder_output, src_mask, tgt_mask)。

对最后一个解码器块的输出应用层归一化:self.norm(x)。

12. ProjectionLayer 类

class ProjectionLayer(nn.Module):
    def __init__(self, d_model, vocab_size):
        super().__init__()
        self.proj = nn.Linear(d_model, vocab_size)    def forward(self, x):
        # (batch, seq_len, d_model) --> (batch, seq_len, vocab_size)
        return self.proj(x)

功能:将解码器的输出投影到词汇表大小的维度,以便进行词的预测。

初始化:d_model:输入的特征维度。

vocab_size:目标词汇表的大小。

self.proj:线性层,将 d_model 维的输入映射到 vocab_size 维的输出。

前向传播:对输入应用线性层,将其维度从 (batch, seq_len, d_model) 转换为 (batch, seq_len, vocab_size)。

13. Transformer 类

class Transformer(nn.Module):
    def __init__(self, encoder: Encoder, decoder: Decoder, src_embed: InputEmbeddings, tgt_embed: InputEmbeddings,
                 src_pos: PositionalEncoding, tgt_pos: PositionalEncoding, projection_layer: ProjectionLayer):
        super().__init__()
        self.encoder = encoder
        self.decoder = decoder
        self.src_embed = src_embed
        self.tgt_embed = tgt_embed
        self.src_pos = src_pos
        self.tgt_pos = tgt_pos
        self.projection_layer = projection_layer    def encode(self, src, src_mask):
        # (batch, seq_len, d_model)
        src = self.src_embed(src)
        src = self.src_pos(src)
        return self.encoder(src, src_mask)    def decode(self, encoder_output: torch.Tensor, src_mask: torch.Tensor, tgt: torch.Tensor, tgt_mask: torch.Tensor):
        # (batch, seq_len, d_model)
        tgt = self.tgt_embed(tgt)
        tgt = self.tgt_pos(tgt)
        return self.decoder(tgt, encoder_output, src_mask, tgt_mask)    def project(self, x):
        return self.projection_layer(x)  # (batch, seq_len, vocab_size)

功能:整合编码器、解码器、嵌入层、位置编码层和投影层,构建完整的 Transformer 模型。

初始化:encoder:编码器模块。

decoder:解码器模块。

src_embed:源语言嵌入层。

tgt_embed:目标语言嵌入层。

src_pos:源语言位置编码层。

tgt_pos:目标语言位置编码层。

projection_layer:投影层。

encode 方法:对源序列进行嵌入和位置编码:src = self.src_embed(src); src = self.src_pos(src)。

将处理后的源序列传递给编码器:self.encoder(src, src_mask)。

decode 方法:对目标序列进行嵌入和位置编码:tgt = self.tgt_embed(tgt); tgt = self.tgt_pos(tgt)。

将处理后的目标序列、编码器输出、源序列掩码和目标序列掩码传递给解码器:self.decoder(tgt, encoder_output, src_mask, tgt_mask)。

project 方法:将解码器的输出传递给投影层,得到最终的预测结果。

14. build_transformer 函数

def build_transformer(src_vocab_size: int, tgt_vocab_size: int, src_seq_len: int, tgt_seq_len: int, d_model: int = 512,
                      N: int = 6, h: int = 8, dropout: float = 0.1, d_ff: int = 2048) -> Transformer:# embedding layers
    src_embed = InputEmbeddings(d_model, src_vocab_size)
    tgt_embed = InputEmbeddings(d_model, tgt_vocab_size)# positional encoding layers
    src_pos = PositionalEncoding(d_model, src_seq_len, dropout)
    tgt_pos = PositionalEncoding(d_model, tgt_seq_len, dropout)# encoder blocks
    encoder_blocks = []for _ in range(N):
        encoder_self_attention_block = MultiHeadAttentionBlock(d_model, h, dropout)
        feed_forward_block = FeedForwardBlock(d_model, d_ff, dropout)
        encoder_block = EncoderBlock(d_model, encoder_self_attention_block, feed_forward_block, dropout)
        encoder_blocks.append(encoder_block)# encoder
    encoder = Encoder(d_model, nn.ModuleList(encoder_blocks))# decoder blocks
    decoder_blocks = []for _ in range(N):
        decoder_self_attention_block = MultiHeadAttentionBlock(d_model, h, dropout)
        decoder_cross_attention_block = MultiHeadAttentionBlock(d_model, h, dropout)
        feed_forward_block = FeedForwardBlock(d_model, d_ff, dropout)
        decoder_block = DecoderBlock(d_model, decoder_self_attention_block, decoder_cross_attention_block,
                                     feed_forward_block, dropout)
        decoder_blocks.append(decoder_block)# decoder
    decoder = Decoder(d_model, nn.ModuleList(decoder_blocks))# projection layer
    projection_layer = ProjectionLayer(d_model, tgt_vocab_size)# transformer
    transformer = Transformer(encoder, decoder, src_embed, tgt_embed, src_pos, tgt_pos, projection_layer)# 初始化transformer模型中的参数for p in transformer.parameters():if p.dim() > 1:
            nn.init.xavier_normal_(p)return transformer

功能:根据给定的参数构建一个完整的 Transformer 模型。

参数:src_vocab_size:源语言词汇表的大小。

tgt_vocab_size:目标语言词汇表的大小。

src_seq_len:源序列的最大长度。

tgt_seq_len:目标序列的最大长度。

d_model:词向量和隐藏层的维度,默认值为 512。

N:编码器和解码器中块的数量,默认值为 6。

h:多头注意力机制中头的数量,默认值为 8。

dropout:Dropout 概率,默认值为 0.1。

d_ff:前馈神经网络中间层的维度,默认值为 2048。

构建过程:分别创建源语言和目标语言的嵌入层和位置编码层。

构建编码器块和编码器。

构建解码器块和解码器。

创建投影层。

将上述组件组合成一个完整的 Transformer 模型。

对模型的参数进行初始化,对于维度大于 1 的参数,使用 xavier_normal_ 方法进行初始化。

返回构建好的 Transformer 模型。

完整代码实现transfomer

import torch
import torch.nn as nn
import mathclass InputEmbeddings(nn.Module):# 词嵌入本质会训练一个矩阵, (vocab_size, d_model)def __init__(self, d_model: int, vocab_size: int):super().__init__()
        self.d_model = d_model
        self.vocab_size = vocab_size
        self.embedding = nn.Embedding(vocab_size, d_model)def forward(self, x):# nn.Embedding 里面是有参数的, 使用的时候相当于 lookup table# 乘上权重来自于论文 3.4return self.embedding(x) * math.sqrt(self.d_model)class PositionalEncoding(nn.Module):# d_model 是每个位置的向量维度, seq_len 是总共多少个位置, dropout 防止过拟合def __init__(self, d_model: int, seq_len: int, dropout: float):super().__init__()
        self.d_model = d_model
        self.seq_len = seq_len
        self.dropout = nn.Dropout(dropout)# 创建一个矩阵, 形状(seq_len, d_model)
        pe = torch.zeros(seq_len, d_model)# 创建一个向量 (seq_len, 1)
        position = torch.arange(0, seq_len, dtype=torch.float).unsqueeze(1)# 实现公式 3.5, 但是在 log space 下计算的
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)        pe = pe.unsqueeze(0)  # (1, seq_len, d_model)# 不需要去训练的参数, 最终它也是会保存在模型文件中的, 可以把它注册到 buffer 中
        self.register_buffer('pe', pe)def forward(self, x):# (batch, seq_len, d_model)
        x = x + (self.pe[:, :x.shape[1], :]).requires_grad_(False)return self.dropout(x)class LayerNormalization(nn.Module):# layer norm 是对每个样本不同位置的向量求均值和方差,然后再进行归一化# features 是一个样本的特征数量def __init__(self, features: int, eps: float = 1e-6):super().__init__()
        self.eps = eps
        self.alpha = nn.Parameter(torch.ones(features))
        self.bias = nn.Parameter(torch.zeros(features))def forward(self, x):# x: (batch, seq_len, hidden_size) 每条文本的每个token由多个特征构成
        mean = x.mean(dim=-1, keepdim=True)
        std = x.std(dim=-1, keepdim=True)return self.alpha * (x - mean) / (std + self.eps) + self.biasclass FeedForwardBlock(nn.Module):def __init__(self, d_model: int, d_ff: int, dropout: float):super().__init__()
        self.linear_1 = nn.Linear(d_model, d_ff)
        self.dropout = nn.Dropout(p=dropout)
        self.linear_2 = nn.Linear(d_ff, d_model)def forward(self, x):# 实现的就是论文中 3.3 FFN(x)return self.linear_2(self.dropout(torch.relu(self.linear_1(x))))class MultiHeadAttentionBlock(nn.Module):def __init__(self, d_model: int, h: int, dropout: float):super().__init__()        self.d_model = d_model
        self.h = hassert d_model % h == 0, "d_model 必须可以整除 h"# 每个 head 对应的维度是多大
        self.d_k = d_model // h        self.w_q = nn.Linear(d_model, d_model, bias=False)
        self.w_k = nn.Linear(d_model, d_model, bias=False)
        self.w_v = nn.Linear(d_model, d_model, bias=False)
        self.w_o = nn.Linear(d_model, d_model, bias=False)        self.dropout = nn.Dropout(dropout)@staticmethoddef attention(query, key, value, mask, dropout: nn.Dropout):
        d_k = query.shape[-1]        attention_scores = (query @ key.transpose(-2, -1)) / math.sqrt(d_k)if mask is not None:# 将 mask 矩阵中值为 0的位置,对应在 attention_scores 里面的值用 -1e9 替换
            attention_scores.masked_fill_(mask == 0, -1e9)
        attention_scores = attention_scores.softmax(dim=-1)  # (Batch, h, seq_len, seq_len)if dropout is not None:
            attention_scores = dropout(attention_scores)return (attention_scores @ value), attention_scoresdef forward(self, q, k, v, mask):
        query = self.w_q(q)  # Q
        key = self.w_k(k)  # K
        value = self.w_v(v)  # V# 多头注意力机制 切割 Q K V 为了给不同的 heads# (Batch, Seq_Len, d_model) --> (Batch, Seq_Len, h, d_k) --> (Batch, h, Seq_Len, d_k)
        query = query.view(query.shape[0], query.shape[1], self.h, self.d_k).transpose(1, 2)
        key = key.view(key.shape[0], key.shape[1], self.h, self.d_k).transpose(1, 2)
        value = value.view(value.shape[0], value.shape[1], self.h, self.d_k).transpose(1, 2)        x, self.attention_scores = MultiHeadAttentionBlock.attention(query, key, value, mask, self.dropout)# (Batch, h, seq_len, d_k) --> (Batch, Seq_Len, h, d_k) --> (Batch, Seq_Len, d_model)
        x = x.transpose(1, 2).contiguous().view(x.shape[0], -1, self.h * self.d_k)return self.w_o(x)class ResidualConnection(nn.Module):def __init__(self, features: int, dropout: float):super().__init__()
        self.dropout = nn.Dropout(dropout)
        self.norm = LayerNormalization(features=features)def forward(self, x, sublayer):# 此处和论文中 transformer 给的图略有不同, 先进行 norm 再进行 self-attention 或 feed-forwardreturn x + self.dropout(sublayer(self.norm(x)))class EncoderBlock(nn.Module):def __init__(self, features: int, self_attention_block: MultiHeadAttentionBlock,
                 feed_forward_block: FeedForwardBlock, dropout: float):super().__init__()
        self.self_attention_block = self_attention_block
        self.feed_forward_block = feed_forward_block
        self.residual_connections = nn.ModuleList([ResidualConnection(features, dropout) for _ in range(2)])def forward(self, x, src_mask):
        x = self.residual_connections[0](x, lambda x: self.self_attention_block(x, x, x, src_mask))
        x = self.residual_connections[1](x, self.feed_forward_block)return xclass Encoder(nn.Module):def __init__(self, features: int, layers: nn.ModuleList):super().__init__()
        self.layers = layers
        self.norm = LayerNormalization(features=features)def forward(self, x, mask):for layer in self.layers:
            x = layer(x, mask)return self.norm(x)class DecoderBlock(nn.Module):def __init__(self, features: int, self_attention_block: MultiHeadAttentionBlock,
                 cross_attention_block: MultiHeadAttentionBlock,
                 feed_forward_block: FeedForwardBlock, dropout: float):super().__init__()
        self.self_attention_block = self_attention_block
        self.cross_attention_block = cross_attention_block
        self.feed_forward_block = feed_forward_block
        self.residual_connections = nn.ModuleList([ResidualConnection(features, dropout) for _ in range(3)])def forward(self, x, encoder_output, src_mask, tgt_mask):
        x = self.residual_connections[0](x, lambda x: self.self_attention_block(x, x, x, tgt_mask))
        x = self.residual_connections[1](x, lambda x: self.cross_attention_block(x, encoder_output, encoder_output,
                                                                                 src_mask))
        x = self.residual_connections[2](x, self.feed_forward_block)return xclass Decoder(nn.Module):def __init__(self, features: int, layers: nn.ModuleList):super().__init__()
        self.layers = layers
        self.norm = LayerNormalization(features=features)def forward(self, x, encoder_output, src_mask, tgt_mask):for layer in self.layers:
            x = layer(x, encoder_output, src_mask, tgt_mask)return self.norm(x)class ProjectionLayer(nn.Module):def __init__(self, d_model, vocab_size):super().__init__()
        self.proj = nn.Linear(d_model, vocab_size)def forward(self, x):# (batch, seq_len, d_model) --> (batch, seq_len, vocab_size)return self.proj(x)class Transformer(nn.Module):def __init__(self, encoder: Encoder, decoder: Decoder, src_embed: InputEmbeddings, tgt_embed: InputEmbeddings,
                 src_pos: PositionalEncoding, tgt_pos: PositionalEncoding, projection_layer: ProjectionLayer):super().__init__()
        self.encoder = encoder
        self.decoder = decoder
        self.src_embed = src_embed
        self.tgt_embed = tgt_embed
        self.src_pos = src_pos
        self.tgt_pos = tgt_pos
        self.projection_layer = projection_layerdef encode(self, src, src_mask):# (batch, seq_len, d_model)
        src = self.src_embed(src)
        src = self.src_pos(src)return self.encoder(src, src_mask)def decode(self, encoder_output: torch.Tensor, src_mask: torch.Tensor, tgt: torch.Tensor, tgt_mask: torch.Tensor):# (batch, seq_len, d_model)
        tgt = self.tgt_embed(tgt)
        tgt = self.tgt_pos(tgt)return self.decoder(tgt, encoder_output, src_mask, tgt_mask)def project(self, x):return self.projection_layer(x)  # (batch, seq_len, vocab_size)def build_transformer(src_vocab_size: int, tgt_vocab_size: int, src_seq_len: int, tgt_seq_len: int, d_model: int = 512,
                      N: int = 6, h: int = 8, dropout: float = 0.1, d_ff: int = 2048) -> Transformer:# embedding layers
    src_embed = InputEmbeddings(d_model, src_vocab_size)
    tgt_embed = InputEmbeddings(d_model, tgt_vocab_size)# positional encoding layers
    src_pos = PositionalEncoding(d_model, src_seq_len, dropout)
    tgt_pos = PositionalEncoding(d_model, tgt_seq_len, dropout)# encoder blocks
    encoder_blocks = []for _ in range(N):
        encoder_self_attention_block = MultiHeadAttentionBlock(d_model, h, dropout)
        feed_forward_block = FeedForwardBlock(d_model, d_ff, dropout)
        encoder_block = EncoderBlock(d_model, encoder_self_attention_block, feed_forward_block, dropout)
        encoder_blocks.append(encoder_block)# encoder
    encoder = Encoder(d_model, nn.ModuleList(encoder_blocks))# decoder blocks
    decoder_blocks = []for _ in range(N):
        decoder_self_attention_block = MultiHeadAttentionBlock(d_model, h, dropout)
        decoder_cross_attention_block = MultiHeadAttentionBlock(d_model, h, dropout)
        feed_forward_block = FeedForwardBlock(d_model, d_ff, dropout)
        decoder_block = DecoderBlock(d_model, decoder_self_attention_block, decoder_cross_attention_block,
                                     feed_forward_block, dropout)
        decoder_blocks.append(decoder_block)# decoder
    decoder = Decoder(d_model, nn.ModuleList(decoder_blocks))# projection layer
    projection_layer = ProjectionLayer(d_model, tgt_vocab_size)# transformer
    transformer = Transformer(encoder, decoder, src_embed, tgt_embed, src_pos, tgt_pos, projection_layer)# 初始化transformer模型中的参数for p in transformer.parameters():if p.dim() > 1:
            nn.init.xavier_normal_(p)return transformer

相关文章:

transfomer网络构建

目录 整体架构 详细模块分析 Transformer 算法的演进 代码讲解 1. 导入必要的库 2. InputEmbeddings 类 3. PositionalEncoding 类 4. LayerNormalization 类 5. FeedForwardBlock 类 6. MultiHeadAttentionBlock 类 7. ResidualConnection 类 8. EncoderBlock 类 9. Encoder 类…...

【mathematica】常见命令

mathematica官方文档 下载安装 安装激活教程 基本用法 输入、画图、基本运算、方程组求解、公式导出、 笔记本新建: 文件-新建-笔记本 输入: 直接在界面输入定义的变量、式子或者方程组即可 输出(计算) ENTER : 换行ENTER SHIF…...

photoshop学习笔记2

第一章 第01节-界面的重要性(学习方法) 第02节-文件的打开新建及储存 第03节-移动工具(图层概念) 学习目标: 1.了解图层概念 2.认识工具属性 3.掌握工具使用 图层的概念 移动工具 移动工具就是用来移动图层内容的。是否可以用来移动组…...

从软件到硬件:三大主流架构的特点与优劣详解

常见的架构包括软件架构、企业架构、硬件架构等,以下是对这几种常见架构的分析: 一、软件架构 1.分层架构 描述:分层架构是一种经典的软件架构模式,将软件系统按照功能划分为不同的层次,一般包括表现层(…...

网狐旗舰大联盟组件源码私测笔记:结构分层、UI重构与本地实操全流程

作为一套衍生于传统网狐架构的源码版本,大联盟这套源码组件可谓是在经典基础上进行了深度重塑。与老版死板的框架风格不同,它不仅对界面做了大刀阔斧的重构,还在组件层级的组织上做了优化。本文将基于一整套源码进行深度解析,强调…...

Oracle OCP认证考试考点详解083系列07

题记: 本系列主要讲解Oracle OCP认证考试考点(题目),适用于19C/21C,跟着学OCP考试必过。 31. 第31题: 题目 解析及答案: 从 Oracle 19c 开始,数据库配置助手(DBCA)在克…...

Qt .pro配置msvc相关命令(二)

目录 1. 指定编译器版本 2. 设置编译器选项 3. 设置链接器选项 4. 定义预处理器宏 5. 指定包含目录和库目录 6. 配置生成目标 7. 配置调试和发布模式 8. 指定生成文件的目录 9. 使用特定的 MSVC 功能 10. 条件编译 在 Qt 中,.pro 文件是项目配置文件&…...

Debezium Binlog解析与事件转换流程详解

Debezium Binlog解析与事件转换流程详解 1. Binlog解析整体流程 #mermaid-svg-2ghVgmGOnV4elpya {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-2ghVgmGOnV4elpya .error-icon{fill:#552222;}#mermaid-svg-2ghVgmG…...

SpringBoot接口防抖(防重复提交)

目录 一.流程分析: 二.案例代码详解: 前提条件: 1.自定义注解: 2.编写异常类: 3.创建key生成器: 4.自定义AOP切面: 5.Controller: 三.Redission分布式解决方案:…...

HTML02:网页基本信息

网页的基本信息 DOCTYPE声明 < title 标签 < meat 标签 <!-- DOCTYPE:告诉浏览器&#xff0c;我们要使用什么规格 --> <!DOCTYPE html> <!-- head标签代表网页头部 --> <html lang"en"> <head><!-- meta描述性标签&#…...

uniswap v4 hooks标志位

hooks的代码位置在这&#xff0c;它是是组织校验&#xff0c;调用用户创建钩子的类库。 首先看其中定义的常量&#xff1a; uint160 internal constant ALL_HOOK_MASK uint160((1 << 14) - 1);uint160 internal constant BEFORE_INITIALIZE_FLAG 1 << 13;uint16…...

YOLOv7细节解读

RepVGG 推理加速 背景与动机&#xff1a;在模型的骨干网络&#xff08;backbone&#xff09;优化中&#xff0c;VGG 因结构简单&#xff0c;在显存利用上有优势&#xff08;单一路径&#xff0c;仅需一倍显存&#xff09;&#xff0c;但被多分支结构的 ResNet 超越。然而&#…...

nt!MiSessionAddProcess函数分析和nt!MmSessionSpace全局变量的关系

第一部分&#xff1a; 1: kd> g Breakpoint 42 hit nt!MiSessionAddProcess: 80ab2fbe 55 push ebp 1: kd> kc # 00 nt!MiSessionAddProcess 01 nt!MmCreateProcessAddressSpace 02 nt!PspCreateProcess 03 nt!NtCreateProcessEx 04 nt!_KiSystemServic…...

情绪ABC——AI与思维模型【93】

一、定义 情绪ABC思维模型是一种心理学上的理论&#xff0c;它认为人们的情绪和行为反应&#xff08;C&#xff0c;Consequence&#xff09;并非直接由激发事件&#xff08;A&#xff0c;Activating event&#xff09;引起&#xff0c;而是由个体对激发事件的认知和评价所产生…...

基于k8s系统的API网关-kong网关

1. 为什么需要 API 网关 API网关是一个服务器&#xff0c;是系统的唯一入口。API网关封装了系统内部架构&#xff0c;为每个客户端提供一个定制的API。它可能还具有其它职责&#xff0c;如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。API网关方式的核心要点…...

8.2 GitHub企业级PDF报告生成实战:ReportLab高级技巧与性能优化全解析

GitHub企业级PDF报告生成实战:ReportLab高级技巧与性能优化全解析 GitHub Sentinel 高级功能实现:PDF 报告生成技术详解 关键词:PDF 报告生成, ReportLab 实战, 结构化数据转换, 容器化字体配置, 企业级报告模板 1. 需求分析与技术选型 PDF 报告生成需要满足以下技术要求…...

一周学会Pandas2 Python数据处理与分析-Pandas2复杂数据查询操作

锋哥原创的Pandas2 Python数据处理与分析 视频教程&#xff1a; 2025版 Pandas2 Python数据处理与分析 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 前面我们学了.loc[]等几个简单的数据筛选操作&#xff0c;但实际业务需求往 往需要按照一定的条件甚至复杂的组合条件…...

四年级数学知识边界总结思考-下册

目录 一、背景二、过程1.四则运算小学四年级课本下册《四则运算》知识点、由来、作用与意义解析**一、核心知识点****二、历史由来****三、作用与意义****四、总结** 2.运算律小学四年级课本下《运算律》知识点、由来、作用与意义解析**一、核心知识点****二、历史由来****三、…...

Git从入门到精通-第四章-更新仓库

目录 检查当前文件状态 追踪新文件 暂存已修改的文件&#xff08;git add作用总结&#xff09; 简化输出状态 忽略文件 查看已暂存和未暂存的修改 git diff 提交更新 git commit 跳过使用暂存区 前言&#xff1a;在工作区和Git仓库间设置暂存区的意义 1. ​精准控制…...

RPG8.增加武器

1.创建一个Actor的c类 2.创建武器WeaponBase的子类&#xff0c;给玩家的武器 3.进入WeaponBase&#xff0c;只留下构造函数&#xff0c;并且将bCanEventTick改为false&#xff0c;增加组件。 #pragma once#include "CoreMinimal.h" #include "GameFramework/Ac…...

力扣1128题解

记录 2525.5.4 题目&#xff1a; 思路&#xff1a; 先将dominoes[i]的二元全部变为前大后小的形式&#xff0c;再遍历该数组&#xff0c;用数组来记录。 代码&#xff1a; class Solution {public int numEquivDominoPairs(int[][] dominoes) {int [] [] cnt new int [10…...

微服务框架选型

1 Thrift&#xff0c; gRPC&#xff0c; Dubbo&#xff0c;Spring Cloud性能对比 指标ThriftgRPCDubboSpring Cloud序列化速度最快 (Binary)快 (Protobuf)中等 (Hessian2)慢 (JSON/XML)网络吞吐量最高 (无HTTP开销)高 (HTTP/2)中等 (TCP)低 (HTTP/1.1)延迟<1ms1-3ms2-5ms10…...

DeepSeek-Prover-V2模型原理速览

文章目录 prerequisite&#xff1a;Lean4研究亮点通过子目标分解实现递归证明搜索基于子目标的定理证明中的课程学习 统一非形式化推理和形式化证明通过合成数据实现冷启动以推理为导向的强化学习 DeepSeek-Prover-V2 的训练细节专家迭代监督式微调 快速使用REF DeepSeek-Prove…...

网络编程,使用select()进行简单服务端与客户端通信

这里在Ubuntu环境下演示 一般流程 服务端常用函数&#xff1a; socket()&#xff1a;创建一个新的套接字。bind()&#xff1a;将套接字与特定的IP地址和端口绑定。listen()&#xff1a;使套接字开始监听传入的连接请求。accept()&#xff1a;接受一个传入的连接请求&#xff…...

QT数据库实验

一、实验目的和要求 1、掌握Qt中掌握绘图工具和图形界面设计&#xff1b;绘制常见的图形。 2、熟悉Qt界面设计中常用的控件。 3、了解滚动条、滑动条、进度条、旋转按钮控件的用法。 二、实验内容 1、设计一个绘图软件&#xff0c;完成图像的绘制操作。 2、建立按钮的信号…...

【PyTorch完全指南】从深度学习原理到工业级实践

目录 🌟 前言技术背景与价值当前技术痛点解决方案概述目标读者说明🔍 一、技术原理剖析核心概念图解核心作用讲解关键技术模块技术选型对比🛠 二、实战演示环境配置要求核心代码实现1. 基础Tensor操作2. 神经网络构建3. 训练循环实现运行结果验证⚡ 三、性能对比测试方法…...

Spring AI 实战:第七章、Spring AI Advisor机制之记忆大师

引言:当AI的记性比金鱼还差 你:我叫张三,很高兴认识你AI:很高兴认识你,张三! 如果你有任何问题或者需要帮助,请随时告诉我你:我叫什么AI:抱歉,我无法知道你的名字。不过你可以告诉我一些关于你的信息,如果你愿意分享的话!AI的内心OS:爱谁谁,我反正不知道 如上图所…...

工业AI质检:从传统算法到多模态大模型应用

工业AI质检:从传统算法到多模态大模型应用 引言 在制造业质量控制领域,传统人工检测的漏检率高达15%-20%,而基于规则算法的视觉检测系统仅能处理已知缺陷类型。随着多模态大模型技术的突破,工业质检正进入"认知智能"新阶段——系统不仅能识别缺陷,更能理解工艺…...

STM32智能垃圾桶:四种控制模式实战开发

简介 从零到一打造企业级智能垃圾桶系统,实现按键、语音、红外、蓝牙多模式控制。本项目采用STM32F103C8T6作为主控芯片,通过模块化设计整合多种控制方式,确保系统稳定、高效且易于维护。文章将提供完整硬件连接方案、代码实现细节及企业级开发技术,帮助开发者掌握智能垃圾…...

Python语句入门:从基础到实践

Python作为一门简洁优雅的编程语言&#xff0c;其语句结构清晰易懂&#xff0c;非常适合初学者学习。本文将全面介绍Python中的各种基本语句&#xff0c;帮助编程新手快速掌握Python编程基础。语句是计算机执行程序的最小单位。 一、Python语句概述 Python程序由一系列语句组…...

Kubernetes(k8s)学习笔记(五)--部署Ingress实现域名访问和负载均衡

Ingress是基于nginx&#xff0c;通过在k8s中部署ingress&#xff0c;可实现域名访问和pod节点间的负载均衡。 下面是实现过程&#xff1a; 一.准备一个ingress-controller.yaml文件 apiVersion: v1 kind: Namespace metadata:name: ingress-nginxlabels:app.kubernetes.io/n…...

数据库MySQL学习——day8(复习与巩固基础知识)

文章目录 1. 数据库基础概念复习2. 常用SQL命令复习2.1 SELECT 查询数据2.2 INSERT 插入数据2.3 UPDATE 更新数据2.4 DELETE 删除数据 3. 表操作复习3.1 创建表3.2 修改表3.3 删除表 4. 实践任务4.1 创建样例数据库和表4.2 插入和更新数据4.3 使用WHERE、ORDER BY、LIMIT进行查…...

【ArcGIS微课1000例】0144:沿线或多边形要素添加折点,将曲线线段(贝塞尔、圆弧和椭圆弧)替换为线段。

文章目录 增密工具介绍举例1. 圆2. 椭圆3. 折线增密工具介绍 沿线或多边形要素添加折点。还可将曲线线段(贝塞尔、圆弧和椭圆弧)替换为线段。 原理图如下所示: 用法: 通过距离参数对直线段进行增密。利用距离、最大偏转角或最大偏移偏差参数,通过增密操作对曲线段进行简化…...

python中的模块/库

python中的模块/库 什么是库/模块&#xff0c;通俗来讲是用来干啥的&#xff1f; 模块/库就是一个/多个.py的一个文件。通常是用来定义一些通用的方法&#xff0c;避免代码冗余。怎么python中自带的这些模块和库&#xff1f; 使用import进行导入&#xff0c;之后其中的内容就可…...

全面掌握 Jetpack Compose 的 State 体系:核心用法与最佳实践

Jetpack Compose 中的 State 类型全面解析 Jetpack Compose 提供了多种 State 类型来管理 UI 状态。以下是主要的 State 类型及其使用场景&#xff1a; 基础 State 类型 1. mutableStateOf 最基本的可观察状态&#xff0c;用于简单值的变化跟踪&#xff1a; var count by …...

Pyhton类方法添加装饰器案例解析

from functools import wrapsdef keep_alive(func):"""装饰器&#xff1a;为方法自动维护长连接"""wraps(func)def wrapper(self, *args, **kwargs):if not self.conn:self.conn ConnectHandler(**self.device_params)self.conn.enable()return…...

58认知干货:创业经验分享及企业形式的汇总

机会永远都是留给有眼光、能发现机会的人,而不是留给有准备的人!往往机会就在身边,普罗大众却无法发现,而真正适合创业的人,天然具备这方面的能力。 当然后天的补足也未尝不可:“故常有欲以观其微,常无欲以观其妙。””引用《道德经》 读懂这句话自然便会拥有对商业和…...

n8n 快速入门2:构建自动化工作流

n8n 快速入门2:构建自动化工作流 什么是n8n?项目目标准备工作步骤一:创建新工作流步骤二:添加触发节点步骤三:配置NASA节点与凭证1. 添加NASA节点2. 设置NASA API凭证3. 使用表达式设置时间范围步骤四:添加If条件节点1. 创建条件分支2. 测试条件逻辑步骤五:配置输出节点…...

TimSort算法解析

文章目录 1. 核心数据结构1.1 TimSort类定义1.2 关键概念&#xff1a;Run 2. TimSort解决的具体问题分析2.1 处理现实世界中的数据特性2.2 提高排序稳定性2.3 优化归并排序的空间复杂度2.4 处理特殊情况的鲁棒性2.5 适应性能力与算法自调整2.6 优化合并操作效率 3. TimSort核心…...

CATIA高效工作指南——曲面设计篇(一)

引言 在工业设计领域&#xff0c;CATIA的曲面建模与线束展开功能是构建复杂产品的核心技术。本文整合了​​曲面封闭性检查​​、​​无参数曲面创建​​、​​缝合优化策略​​等核心知识点&#xff0c;结合实战案例与高阶技巧&#xff0c;为工程师提供系统化的解决方案。 一…...

PCB叠层设计方案

1叠层处理 在设计多层 PCB 电路板之前&#xff0c; 设计者需要首先根据电路的规模、 电路板的尺寸和电磁兼容&#xff08; EMC&#xff09;的要求来确定所采用的电路板结构&#xff0c; 也就是决定采用 4 层&#xff0c;6 层&#xff0c; 还是更多层数的电路板。 这就是设计多层…...

机器人编程基础---C语言中的控制语句

C语言中的控制语句 C语言中的控制语句条件语句if 语句switch 语句循环语句for 循环while 循环do-while 循环代码示例C语言中的控制语句 控制语句是编程中用于控制程序执行流程的语句。在C语言中,控制语句包括条件语句和循环语句,它们允许程序根据条件选择不同的执行路径或重…...

13.Excel:分列

一 分列的作用 将一个单元格中的内容拆分到两个或多个单元格当中。 二 如何使用 1.常规分列使用 注意&#xff1a;分列功能一次只能拆分一列。 长度一致或者数据间有分隔符。 补充&#xff1a;快速选择一列。 CTRL shift 向下箭头。 补充&#xff1a;中英文逗号不同。 可以先通…...

理解数学概念——幂律(power law)

在统计学中&#xff0c;幂律(power law)(即按照幂的规律)是指两个量之间的函数关系&#xff0c;其中一个量的相对变化会导致另一个量以与常量指数成正比的关系产生相对变化&#xff1a;一个量随着另一个量的幂而变化。(例如&#xff0c; &#xff0c;r 的变化导致s 按照幂 的…...

Go语言chan底层原理

本篇文章内容参考小徐先生等文章&#xff0c;带有个人注解等内容&#xff0c;帮助大家更好的了解chan的底层实现&#xff0c;原文是在语雀chan底层&#xff0c;可以点击查看&#xff0c;如果感觉还不错的同学&#xff0c;不妨点一个免费的赞和关注&#xff0c;冲冲冲&#xff0…...

传感器数据处理笔记

里程计模型&#xff1a; 两轮差分地盘的运动学模型三轮全向底盘的运动学模型航迹推算&#xff08;Dead Reckoning&#xff09; 里程计标定 线性最小二乘的基本原理最小二乘的直线拟合最小二乘在里程计标定中的应用 差分底盘的优势就是&#xff1a; 结构简单便宜&#xff0…...

8.5 从零到生产:Docker+K8s+CI/CD全链路部署实战手册

从零到生产:Docker+K8s+CI/CD全链路部署实战手册 #mermaid-svg-61OPZrCvQokymEG2 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-61OPZrCvQokymEG2 .error-icon{fill:#552222;}#mermaid-svg-61OPZrCvQokymEG2 .err…...

Android逆向学习(八)Xposed快速上手(上)

Android逆向学习&#xff08;八&#xff09;Xposed快速上手(上) 前言 xposed是一个用来hook的工具&#xff0c;简而言之&#xff0c;通过替换/system/bin/app_process程序控制zygote进程&#xff0c;这样的话&#xff0c;app_process在启动过程中会加载XposedBridge.jar这个j…...

Linux网络编程:套接字

目录 一 前言 二 源ip地址和目的ip地址 三 认识端口号 四 理解 "端口号" 和 "进程ID" 五 理解源端口号和目的端口号 六 认识TCP&#xff08;Transmission Control Protocol&#xff09;协议 七 UDP&#xff08;(User Datagram Protocol&#xff…...

C++八股--6--mysql 日志与并发控制

这里向大家介绍一下数据库基础&#xff1a;共分为以下章节 10前序.日志系统 这是数据库的核心。我放到首页来介绍&#xff0c;给大家一个前置概念&#xff0c;方便进行更好的学习 日志文件我们用来记录事务对数据库更新操作的文件&#xff0c;分为以记录为单位的文件和数据块…...