GPT模型搭建
GPT模型搭建
1. 章节介绍
本章节聚焦于从0搭建GPT模型,通过事先准备的基础代码,引导学习者逐步构建模型。旨在让程序员、软件架构师和工程师等掌握GPT模型搭建的核心流程,理解其关键组件与技术细节,为实际应用和面试做好准备。
核心知识点 | 面试频率 |
---|---|
搭建GPT模型的基础代码 | 中 |
单向注意力机制 | 高 |
Transformer模型架构 | 高 |
仅用解码器的优势 | 中 |
GPT模型结构 | 高 |
多头单向注意力 | 高 |
位置嵌入与文本嵌入 | 高 |
模型训练与过拟合问题 | 中 |
2. 知识点详解
搭建GPT模型的基础代码
- 涵盖安装和引入第三方工具,定义模型结构与训练超参数。
- 下载数据、定义分词器,划分训练集与测试集,其流程与循环神经网络类似。
- 定义生成文本、评估模型效果及训练模型的函数,因注意力机制长度限制,生成文本时需截断背景。
单向注意力机制
- 包含key、query和value三个重要线性模型组件。
- 组件产出经累积计算与加权平均得到背景向量。
- 输入张量形状为BTC,输出为BTH,输入输出形状不同。
Transformer模型架构
- 分为编码器和解码器。
- 编码器重要组件有嵌入层和双向注意力机制。
- 解码器重要组件有嵌入层、单向自注意力机制、交叉注意力机制和语言解码头。
- 主要用于翻译工作,编码器学习一种语言文本,通过交叉注意力将特征传给解码器进行词源预测。但对训练数据格式要求高,需配对翻译文本,准备工作困难。
仅用解码器的优势
- 数据准备容易:无需准备配对翻译文本,收集单一语言文本相对轻松。
- 模型结构简单:相比完整Transformer模型,仅用解码器结构更简洁,训练难度降低。
- 应用场景多:便于文本生成,能更好地与人类交互。
GPT模型结构
- 宏观结构:由嵌入层、重复n次的解码块及语言建模头组成。
- 解码块:包含层归一化层、多头单向注意力层、归一化层和多层感知器,还有两个残差连接。
- 图示差异:与常见图示相比,部分层归一化层位置不同,但不影响模型语义表达,因参考开源及官方实现,且层归一化层主要加速训练。
多头单向注意力
- 原因:因解码块需残差连接,需保证输入输出张量形状一致,而单项式注意力输入输出形状不同,故需封装。
- 实现:使用多个单向注意力,将得到的张量拼接,使输入输出张量形状相同。
位置嵌入与文本嵌入
- 注意力机制缺陷:能处理词元相关关系,但忽略词元位置关系。
- 解决方法:增加位置嵌入层,其输入为词元在文本中的位置,与文本嵌入层(输入为词元在字典中的位置)相加,同时捕捉词元相关关系与位置关系。
模型训练与过拟合问题
- 模型训练:调用train_model方法训练模型。
- 过拟合问题:与预期结果有差异且出现过拟合,可能原因一是训练数据量相对模型规模少,二是搭建模型时未使用对抗过拟合技术,如增加惩罚项等。
3. 章节总结
本章节从搭建GPT模型的基础代码入手,介绍单向注意力机制,深入剖析Transformer模型架构及仅用解码器的优势。详细讲解GPT模型结构,包括多头单向注意力及位置与文本嵌入的结合。最后涉及模型训练及过拟合问题。通过这些内容,全面展示了从0搭建GPT模型的过程与要点。
4. 知识点补充
相关知识点
- 预训练与微调:GPT模型通常先在大规模无监督数据上预训练,再针对特定任务微调。预训练学习通用语言特征,微调适应具体任务需求,面试常考其原理与流程。
- 注意力机制变体:除单向、双向和交叉注意力,还有全局注意力、局部注意力等变体。它们在不同场景有独特应用,如全局注意力用于处理长序列时关注所有位置,面试可能考查其特点与适用场景。
- 模型压缩技术:大语言模型参数多、计算量大,模型压缩技术如剪枝(去除不重要连接)、量化(降低参数数据精度)可减少存储和计算需求,提升部署效率,面试可能涉及相关原理与方法。
- 数据集处理技巧:在准备训练数据时,数据清洗(去除噪声、重复数据)、增强(如回译、同义词替换增加数据多样性)等技巧能提升数据质量,提高模型训练效果,面试可能考查相关实践经验。
- 模型评估指标:除模型损失,在文本生成任务中,常用BLEU(衡量生成文本与参考文本相似度)、ROUGE(基于召回率评估生成文本与参考文本重叠程度)等指标评估模型性能,面试可能要求解释其含义与使用场景。
最佳实践
在搭建和训练GPT类似模型时,可参考以下最佳实践:
- 数据处理阶段:对收集到的数据进行严格清洗,使用专业工具或自定义脚本去除乱码、错误标注等噪声数据。采用数据增强技术,如对文本进行同义词替换、随机插入或删除单词等操作,扩充数据集规模与多样性。例如,在处理Python代码学习数据时,可将代码中的变量名用同义词替换,生成新的代码样本。
- 模型搭建阶段:参考开源的成熟模型结构与参数设置,如参考GPT官方实现的模型架构细节。在构建解码块等组件时,合理设置超参数,通过实验对比不同参数组合下模型在验证集上的性能表现,确定最优参数。例如,调整多头单向注意力机制中的头数,观察模型对不同长度文本的处理能力变化。
- 训练阶段:选择合适的优化器与学习率调度策略。如使用AdamW优化器结合余弦退火学习率调度,在训练初期采用较大学习率快速收敛,后期逐渐减小学习率使模型更稳定地收敛到最优解。同时,定期在验证集上评估模型性能,绘制损失曲线和评估指标曲线,监控模型训练状态,及时发现过拟合或欠拟合问题并调整训练策略。
编程思想指导
- 模块化编程思想:将模型搭建过程中的不同功能模块分开实现,如将数据处理、模型结构定义、训练过程等分别封装在不同的函数或类中。以数据处理为例,将数据下载、清洗、划分数据集等功能封装成独立函数,便于维护和复用。在模型结构定义中,将嵌入层、解码块、语言建模头等分别定义为类,每个类负责特定功能,使代码结构清晰,易于理解和修改。
- 抽象与泛化思想:从GPT模型的搭建过程中抽象出通用的神经网络构建模式。例如,将解码块这种重复使用的结构抽象成可配置参数的类,通过传入不同参数(如层数、隐藏层维度等),可灵活构建不同规模的解码块。在实现多头单向注意力时,将其设计成通用组件,可应用于不同的基于注意力机制的模型中,提高代码的复用性和扩展性。
- 调试与优化思想:在编写代码过程中,充分利用调试工具(如PyTorch的调试器)排查错误。在模型训练过程中,关注模型性能指标变化,针对性能瓶颈进行优化。例如,发现模型训练速度慢,可检查是否充分利用GPU加速,是否存在不必要的循环操作导致计算效率低下。同时,对模型参数初始化、激活函数选择等方面进行优化,以提升模型训练效果和效率。
5. 程序员面试题
简单题
请简述GPT模型中解码块的主要组成部分。
答案:GPT模型的解码块主要由层归一化层、多头单向注意力层、归一化层和多层感知器组成,还包含两个残差连接。这些组件协同工作,对输入进行处理和特征提取,为后续的语言生成等任务做准备。
中等难度题
- 对比Transformer模型的编码器和解码器在注意力机制使用上的区别。
答案:Transformer模型的编码器使用双向注意力机制,能够同时关注输入序列的前后信息,全面捕捉序列中的依赖关系,适用于对整个输入序列进行编码和特征提取。而解码器使用单向自注意力机制,在生成过程中只能关注当前位置之前的信息,保证生成的因果性;同时还使用交叉注意力机制,用于参考编码器输出的特征,在翻译等任务中结合源语言信息进行目标语言生成。 - 解释为什么在GPT模型中需要多头单向注意力机制,而不是直接使用单向注意力机制。
答案:在GPT模型的解码块中,由于要使用残差连接,需要保证输入和输出的张量形状一致。而单向注意力机制输入和输出张量形状不同,通常输出长度小于输入长度。多头单向注意力机制通过使用多个单向注意力,并将得到的张量进行拼接,最终使输入张量形状等于输出张量形状,满足了残差连接对张量形状的要求,同时多个头可以从不同角度学习输入特征,增强模型的表示能力。
高难度题
- 假设你在训练一个类似GPT的模型时遇到了过拟合问题,请详细说明你会采取哪些措施来解决它。
答案:- 数据方面:
- 增加数据量:收集更多相关领域的训练数据,扩充数据集规模,使模型学习到更丰富的模式,减少对少量数据的过拟合。例如在学习Python代码的模型中,收集更多不同类型、复杂度的Python代码片段。
- 数据增强:采用数据增强技术,如对文本进行同义词替换、随机删除或插入单词、回译等操作,增加数据的多样性,让模型接触到更多不同形式的样本,提高模型泛化能力。
- 模型方面:
- 调整模型结构:适当减小模型规模,如减少解码块的重复次数、降低隐藏层维度等,降低模型复杂度,防止模型过于复杂而拟合训练数据中的噪声。
- 增加正则化项:在损失函数中加入L1或L2正则化项,惩罚模型参数的大小,使模型参数趋向于更小更简单的值,避免模型过拟合。例如在PyTorch中,通过修改损失函数,添加正则化项来约束模型参数。
- 采用Dropout:在模型的适当位置(如多层感知器后)增加Dropout层,随机丢弃部分神经元的输出,使模型在训练时不能依赖特定神经元,增强模型的泛化能力。
- 训练过程方面:
- 调整学习率:采用学习率衰减策略,如指数衰减或余弦退火,在训练初期使用较大学习率快速收敛,后期逐渐减小学习率,使模型更稳定地收敛到最优解,避免学习率过大导致模型在训练后期过拟合。
- 早停法:在验证集上监控模型性能,当验证集上的损失不再下降或评估指标不再提升时,停止训练,防止模型在训练集上过拟合太久。
- 数据方面:
- 请详细描述如何实现一个包含位置嵌入的文本嵌入层,使其能够应用于GPT类似模型中,并给出相应的代码示例(使用Python和PyTorch框架)。
答案:
import torch
import torch.nn as nnclass PositionalEmbedding(nn.Module):def __init__(self, max_len, embedding_dim):super(PositionalEmbedding, self).__init__();# 创建一个位置编码矩阵pe = torch.zeros(max_len, embedding_dim)position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)div_term = torch.exp(torch.arange(0, embedding_dim, 2).float() * (-torch.log(torch.tensor(10000.0)) / embedding_dim))pe[:, 0::2] = torch.sin(position * div_term)pe[:, 1::2] = torch.cos(position * div_term)pe = pe.unsqueeze(0).transpose(0, 1)# 将位置编码矩阵注册为模型的参数,使其在训练中可被优化self.register_buffer('pe', pe)def forward(self, x):# x的形状为(batch_size, sequence_length)batch_size, seq_len = x.size()# 将位置编码加到输入的文本嵌入上return self.pe[:seq_len].repeat(batch_size, 1, 1)class TextWithPositionalEmbedding(nn.Module):def __init__(self, vocab_size, embedding_dim, max_len):super(TextWithPositionalEmbedding, self).__init__();self.word_embedding = nn.Embedding(vocab_size, embedding_dim)self.position_embedding = PositionalEmbedding(max_len, embedding_dim)def forward(self, x):# 对输入文本进行词嵌入word_emb = self.word_embedding(x)# 获取位置嵌入pos_emb = self.position_embedding(x)# 将词嵌入和位置嵌入相加return word_emb + pos_emb# 示例使用
vocab_size = 10000
embedding_dim = 128
max_len = 100
model = TextWithPositionalEmbedding(vocab_size, embedding_dim, max_len)
# 假设输入文本的索引
input_text = torch.tensor([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
output = model(input_text)
print(output.shape)
在上述代码中,PositionalEmbedding
类用于生成位置嵌入,通过三角函数计算不同位置的编码值。TextWithPositionalEmbedding
类将文本嵌入和位置嵌入结合起来,在forward
方法中,先对输入文本进行词嵌入,再获取位置嵌入并将两者相加,得到包含位置信息的文本嵌入表示,可应用于GPT类似模型中。
文章目录
- GPT模型搭建
- 1. 章节介绍
- 2. 知识点详解
- 搭建GPT模型的基础代码
- 单向注意力机制
- Transformer模型架构
- 仅用解码器的优势
- GPT模型结构
- 多头单向注意力
- 位置嵌入与文本嵌入
- 模型训练与过拟合问题
- 3. 章节总结
- 4. 知识点补充
- 相关知识点
- 最佳实践
- 编程思想指导
- 5. 程序员面试题
- 简单题
- 中等难度题
- 高难度题
- 代码实现
- 代码说明
BV1Hb421n7hC
代码实现
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader# 1. 数据集准备
class TextDataset(Dataset):def __init__(self, texts, labels, vocab_size):"""初始化数据集:param texts: 文本数据(词元索引列表):param labels: 标签数据:param vocab_size: 词汇表大小"""self.texts = textsself.labels = labelsself.vocab_size = vocab_sizedef __len__(self):"""返回数据集大小"""return len(self.texts)def __getitem__(self, idx):"""获取单个样本"""text = self.texts[idx]label = self.labels[idx]return torch.LongTensor(text), torch.LongTensor(label)# 2. 位置编码模块
class PositionalEmbedding(nn.Module):def __init__(self, max_len, embed_dim):"""初始化位置编码:param max_len: 最大序列长度:param embed_dim: 嵌入维度"""super().__init__()# 计算位置编码矩阵pe = torch.zeros(max_len, embed_dim)position = torch.arange(0, max_len).unsqueeze(1).float()div_term = torch.exp(torch.arange(0, embed_dim, 2) * (-torch.log(torch.tensor(10000.0)) / embed_dim))pe[:, 0::2] = torch.sin(position * div_term)pe[:, 1::2] = torch.cos(position * div_term)pe = pe.unsqueeze(0) # 添加batch维度self.register_buffer('pe', pe) # 注册为非训练参数def forward(self, x):""":param x: 输入张量 (B, T):return: 位置编码 (B, T, E)"""B, T = x.size()return self.pe[:, :T] # 截取有效长度# 3. 单向注意力机制
class SingleHeadAttention(nn.Module):def __init__(self, embed_size, head_size):"""单头注意力模块:param embed_size: 输入嵌入维度:param head_size: 头维度"""super().__init__()self.key = nn.Linear(embed_size, head_size, bias=False)self.query = nn.Linear(embed_size, head_size, bias=False)self.value = nn.Linear(embed_size, head_size, bias=False)self.dropout = nn.Dropout(0.1)# 初始化掩码矩阵(下三角)self.register_buffer('mask', torch.tril(torch.ones(1024, 1024)))def forward(self, x):""":param x: 输入张量 (B, T, E):return: 输出张量 (B, T, H)"""B, T, E = x.size()k = self.key(x) # (B, T, H)q = self.query(x) # (B, T, H)# 计算注意力分数att = (q @ k.transpose(-2, -1)) * (1.0 / torch.sqrt(torch.tensor(E)))att = att.masked_fill(self.mask[:T, :T] == 0, float('-inf'))att = torch.softmax(att, dim=-1)att = self.dropout(att)# 计算上下文向量v = self.value(x) # (B, T, H)out = att @ v # (B, T, H)return out# 4. 多头注意力模块
class MultiHeadAttention(nn.Module):def __init__(self, embed_size, num_heads):"""多头注意力模块:param embed_size: 输入嵌入维度:param num_heads: 头数"""super().__init__()self.heads = nn.ModuleList([SingleHeadAttention(embed_size, embed_size // num_heads)for _ in range(num_heads)])self.proj = nn.Linear(embed_size, embed_size)self.dropout = nn.Dropout(0.1)def forward(self, x):""":param x: 输入张量 (B, T, E):return: 输出张量 (B, T, E)"""# 多头并行计算out = torch.cat([h(x) for h in self.heads], dim=-1)out = self.proj(out)out = self.dropout(out)return out# 5. 前馈神经网络模块
class FeedForward(nn.Module):def __init__(self, embed_size):"""前馈神经网络:param embed_size: 输入维度"""super().__init__()self.net = nn.Sequential(nn.Linear(embed_size, 4 * embed_size),nn.GELU(),nn.Linear(4 * embed_size, embed_size),nn.Dropout(0.1))def forward(self, x):""":param x: 输入张量 (B, T, E):return: 输出张量 (B, T, E)"""return self.net(x)# 6. 解码块模块
class DecoderBlock(nn.Module):def __init__(self, embed_size, num_heads):"""解码块:param embed_size: 嵌入维度:param num_heads: 头数"""super().__init__()self.norm1 = nn.LayerNorm(embed_size)self.attn = MultiHeadAttention(embed_size, num_heads)self.norm2 = nn.LayerNorm(embed_size)self.ffn = FeedForward(embed_size)def forward(self, x):""":param x: 输入张量 (B, T, E):return: 输出张量 (B, T, E)"""x = x + self.attn(self.norm1(x))x = x + self.ffn(self.norm2(x))return x# 7. GPT模型主体
class GPT(nn.Module):def __init__(self, vocab_size, embed_size, num_heads, num_layers, max_len):"""GPT模型:param vocab_size: 词汇表大小:param embed_size: 嵌入维度:param num_heads: 头数:param num_layers: 解码块层数:param max_len: 最大序列长度"""super().__init__()self.token_emb = nn.Embedding(vocab_size, embed_size)self.pos_emb = PositionalEmbedding(max_len, embed_size)self.blocks = nn.Sequential(*[DecoderBlock(embed_size, num_heads) for _ in range(num_layers)])self.norm = nn.LayerNorm(embed_size)self.lm_head = nn.Linear(embed_size, vocab_size)def forward(self, idx):""":param idx: 输入索引张量 (B, T):return: 预测对数概率 (B, T, V)"""B, T = idx.size()# 嵌入层tok_emb = self.token_emb(idx) # (B, T, E)pos_emb = self.pos_emb(idx) # (B, T, E)x = tok_emb + pos_emb # (B, T, E)# 解码块x = self.blocks(x) # (B, T, E)x = self.norm(x) # (B, T, E)# 语言模型头logits = self.lm_head(x) # (B, T, V)return logits# 8. 训练函数
def train_model(model, train_loader, epochs=50, lr=1e-4):"""训练模型:param model: GPT模型实例:param train_loader: 训练数据加载器:param epochs: 训练轮数:param lr: 学习率"""device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')model.to(device)optimizer = optim.Adam(model.parameters(), lr=lr)criterion = nn.CrossEntropyLoss()for epoch in range(epochs):model.train()total_loss = 0for batch in train_loader:idx, labels = batchidx = idx.to(device)labels = labels.to(device)# 前向传播logits = model(idx)loss = criterion(logits.view(-1, logits.size(-1)), labels.view(-1))# 反向传播optimizer.zero_grad()loss.backward()optimizer.step()total_loss += loss.item()print(f"Epoch {epoch+1}/{epochs}, Loss: {total_loss/len(train_loader):.4f}")# 9. 文本生成函数
@torch.no_grad()
def generate_text(model, start_idx, max_new_tokens=100):"""生成文本:param model: GPT模型实例:param start_idx: 起始索引张量 (B, T):param max_new_tokens: 生成最大长度:return: 生成的文本索引 (B, T+max_new_tokens)"""device = next(model.parameters()).devicemodel.eval()for _ in range(max_new_tokens):logits = model(start_idx)logits = logits[:, -1, :] # 取最后一个时间步probs = torch.softmax(logits, dim=-1)idx_next = torch.multinomial(probs, num_samples=1)start_idx = torch.cat((start_idx, idx_next), dim=1)# 处理长度限制if start_idx.size(1) > 1024:start_idx = start_idx[:, -1024:]return start_idx# 主函数
if __name__ == "__main__":# 超参数设置VOCAB_SIZE = 50257EMBED_SIZE = 768NUM_HEADS = 12NUM_LAYERS = 12MAX_LEN = 1024BATCH_SIZE = 32LR = 6e-4EPOCHS = 100# 模拟数据准备texts = [torch.randint(0, VOCAB_SIZE, (100,)) for _ in range(1000)]labels = [torch.randint(0, VOCAB_SIZE, (100,)) for _ in range(1000)]dataset = TextDataset(texts, labels, VOCAB_SIZE)train_loader = DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True)# 模型初始化model = GPT(vocab_size=VOCAB_SIZE,embed_size=EMBED_SIZE,num_heads=NUM_HEADS,num_layers=NUM_LAYERS,max_len=MAX_LEN)# 训练模型train_model(model, train_loader, epochs=EPOCHS, lr=LR)# 生成文本示例start_text = torch.tensor([[1, 2, 3, 4, 5]]) # 起始词元索引generated_text = generate_text(model, start_text, max_new_tokens=200)print("Generated Text:")print(generated_text)
代码说明
-
数据集处理:
TextDataset
类处理文本数据和标签- 模拟数据生成使用随机索引,实际应用需替换为真实数据
-
位置编码:
- 使用正弦函数生成绝对位置编码
- 通过
register_buffer
注册为非训练参数
-
注意力机制:
SingleHeadAttention
实现单向自注意力MultiHeadAttention
通过多头并行计算提升表示能力
-
解码块:
- 包含层归一化、多头注意力和前馈神经网络
- 使用残差连接优化训练过程
-
模型训练:
- 使用交叉熵损失和Adam优化器
- 支持GPU加速训练
-
文本生成:
- 基于贪心采样生成文本
- 包含长度限制处理机制
相关文章:
GPT模型搭建
GPT模型搭建 1. 章节介绍 本章节聚焦于从0搭建GPT模型,通过事先准备的基础代码,引导学习者逐步构建模型。旨在让程序员、软件架构师和工程师等掌握GPT模型搭建的核心流程,理解其关键组件与技术细节,为实际应用和面试做好准备。 …...
BUUCTF-web刷题篇(8)
17.EasyCalcS 查看源码,发现有段代码有php文件,即calc.php 经过代码审计之后应该要访问calc.php文件,打开后: <?php error_reporting(0); if(!isset($_GET[num])){show_source(__FILE__); }else{$str $_GET[num];$blackli…...
AI SEO内容优化指南:如何打造AI平台青睐的高质量内容
AI SEO内容优化指南:如何打造AI平台青睐的高质量内容 在生成式AI平台(如DeepSeek、Kimi、豆包、腾讯元宝等)主导的搜索新时代,内容优化已成为企业抢占流量入口的核心策略。本文将从内容创作、分发到效果维护全链路,解…...
无需预对齐即可消除批次效应,东京大学团队开发深度学习框架STAIG,揭示肿瘤微环境中的详细基因信息
生物组织是由多种类型细胞构成的复杂网络,这些细胞通过特定的空间配置执行重要功能。近年来,10x Visium、Slide-seq、Stereo-seq 和 STARmap 等空间转录组学 (ST) 技术的进步,使得生物学家们能够在空间结构内绘制基因数据,从而各类…...
B2B2C多用户商城系统:打造新零售电商生态的创新解决方案
在当今数字化时代,电商行业正以前所未有的速度蓬勃发展,而新零售作为电商与传统零售的深度融合,正逐渐成为市场的新宠。为了满足这一变革带来的多元化需求,B2B2C多用户商城系统应运而生,为商家和消费者搭建了一个高效、…...
走向多模态AI之路(二):多模态 AI 如何工作?
目录 前言一、跨模态对齐(Cross-modal Alignment):AI 如何理解不同模态的关系二、多模态融合(Multimodal Fusion):AI 如何整合不同模态的信息三、多模态生成(Multimodal Generation)…...
MCP 实战:实现server端,并在cline调用
本文动手实现一个简单的MCP服务端的编写,并通过MCP Server 实现成绩查询的调用。 一、配置环境 安装mcp和uv, mcp要求python版本 Python >3.10; pip install mcppip install uv 二、编写并启用服务端 # get_score.py from mcp.server.fastmcp import…...
C#游戏开发【第18天】 | 深入理解队列(Queue)与栈(Stack):从基础到任务队列实战
Langchain系列文章目录 01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...
2.5路径问题专题:LeetCode 64. 最小路径和
动态规划解决最小路径和问题 1. 题目链接 LeetCode 64. 最小路径和 2. 题目描述 给定一个包含非负整数的 m x n 网格 grid,从网格的左上角出发,每次只能向右或向下移动一步,最终到达右下角。要求找到一条路径,使得路径上的数字…...
办公设备管理系统(springboot+ssm+jsp+maven)
基于springboot的办公设备管理系统(springbootssmjspmaven) 系统功能主要有: 欢迎页账号管理 管理员账号管理系统账号添加密码修改 普通管理员管理 用户管理用户添加用户查询 资产类型管理资产信息管理资产档案管理资产报表...
蓝桥杯2024JavaB组的一道真题的解析
文章目录 1.问题描述2.问题描述3.思路分析4.代码分析 1.问题描述 这个是我很久之前写的一个题目,当时研究了这个题目好久,发布了一篇题解,后来很多人点赞,我都没有意识到这个问题的严重性,我甚至都在怀疑自己…...
数据库--SQL
SQL:Structured Query Language,结构化查询语言 SQL是用于管理关系型数据库并对其中的数据进行一系列操作(包括数据插入、查询、修改删除)的一种语言 分类:数据定义语言DDL、数据操纵语言DML、数据控制语言DCL、事务处…...
SQL Server:Log Shipping 说明
目录标题 SQL Server Log Shipping与Oracle归档日志备份对比分析一、SQL Server Log Shipping的日志截断机制二、Oracle归档日志备份对比三、关键配置对比表四、最佳实践建议 如何修改和查看SQL Server默认备份配置防止自动删除?一、查看现有备份配置二、修改备份配…...
Zephyr实时操作系统初步介绍
一、概述 Zephyr是由Linux基金会托管的开源实时操作系统(RTOS),专为资源受限的物联网设备设计。其核心特性包括模块化架构、跨平台兼容性、安全性优先以及丰富的连接协议支持。基于Apache 2.0协议,Zephyr允许商业和非商业用途的自…...
【大模型系列篇】大模型基建工程:基于 FastAPI 自动构建 SSE MCP 服务器 —— 进阶篇
🔥🔥🔥 上期 《大模型基建工程:基于 FastAPI 自动构建 SSE MCP 服务器》中我们使用fastapi-mcp自动挂载fastapi到mcp工具,通过源码分析和实践,我们发现每次sse请求又转到了内部fastapi RESTful api接口&…...
深度学习deeplearn3
# Jupyter Notebook魔法命令,用于在Notebook中内联显示图表 %matplotlib inline# 导入NumPy库,用于高效的数值计算 import numpy as np# 从matplotlib_inline库导入backend_inline模块,用于设置图表显示格式 from matplotlib_inline import b…...
(九)图形管线
一图说明问题 顶点数据->顶点着色器->细分着色器->几何着色器->光栅化->片元着色器->颜色混合 创建图形管线函数放在后面位置 void MyApplication::initVulkan() { createInstance(); createSurface(); pickPhysicalDevice(); createLogicalDevice(); cre…...
7-3 逆序的三位数
程序每次读入一个正3位数,然后输出按位逆序的数字。注意:当输入的数字含有结尾的0时,输出不应带有前导的0。比如输入700,输出应该是7。 输入格式: 每个测试是一个3位的正整数。 输出格式: 输出按位逆序…...
git从历史版本创建新分支或标签
git从某个历史版本创建标签 # 查看历史版本 git log git tag tag-v1.0 780e2a7fc714faf388ba71git从某个分支的指定历史版本中创建新分支 # 查看历史版本 git log # 从历史分支创建标签 git checkout -b new-branch 780e2a7fc714faf388ba71...
HTML 音频(Audio)学习笔记
一、HTML 音频概述 在 HTML 中,音频可以通过多种方式播放,但要确保音频在不同浏览器和设备上都能正常播放,需要掌握一些技巧。HTML5 引入了 <audio> 元素,为音频播放提供了一种标准方法,但在 HTML4 中ÿ…...
五种音频器件综合对比——《器件手册--音频器件》
目录 音频器件 简述 1. 扬声器(Speakers) 2. 麦克风(Microphones) 3. 放大器(Amplifiers) 4. 音频接口(Audio Interfaces) 5. 音频处理器(Audio Processors)…...
数据结构复习(单调栈,单调队列,KMP,manacher,tire,字符串哈希)
单调栈: 介绍: 单调栈用于解决"寻找每个元素左侧/右侧第一个比它小/大的元素"类问题。栈中元素保持单调性,时间复杂度O(n)。 维护一个严格递增栈。对于每个元素a[i],不断弹出栈顶比a[i]大的元素,剩下的栈顶即…...
(学习总结32)Linux 基础 IO
Linux 基础 IO 一、什么是 " 文件 "二、C 文件接口打开文件写文件读文件其它介绍 三、系统文件 I/O传递标志位系统接口写文件系统接口读文件部分系统调用接口介绍打开文件函数 open关闭文件函数 close写入文件函数 write读取文件函数 read 文件描述符 fdfd 0 & 1…...
操作系统(一):概念及主流系统全分析
目录 一.操作系统是什么 二.操作系统的分类 2.1 按应用场景分类 2.2 按实时性分类 2.3 按内核架构分类 2.4 按用户与任务分类 三.主流操作系统比较 四.未来趋势 一.操作系统是什么 操作系统(Operating System, OS)是计算机系统的核心软件&#x…...
三、GPIO
一、GPIO简介 GPIO(General Purpose Input Output)通用输入输出口GPIO引脚电平:0V(低电平)~3.3V(高电平),部分引脚可容忍5V 容忍5V,即部分引脚输入5V的电压,…...
Ceph异地数据同步之-RBD异地同步复制(上)
#作者:闫乾苓 文章目录 前言基于快照的模式(Snapshot-based Mode)工作原理单向同步配置步骤单向同步复制测试双向同步配置步骤双向同步复制测试 前言 Ceph的RBD(RADOS Block Device)支持在两个Ceph集群之间进行异步镜…...
fastapi完全离线环境(无外网)的访问Swagger所做特殊处理
在互联网环境中,只要 启动FastAPI 服务运行在本地机器上,访问 http://localhost:8000/docs(Swagger UI)就可以访问到Swagger界面,但是在完全离线环境(无外网)下如何访问Swagger页面呢࿱…...
在网络中加入预训练的多层感知机(MLP)有什么作用?
在网络中加入预训练的多层感知机(MLP)通常是为了引入先验知识、提升特征表示能力或dropout,具体作用取决于MLP的设计和预训练任务。以下是常见的应用场景和优势: 1. 特征融合与迁移学习:预训练的MLP可以作为特征提取器࿰…...
3.2/Q2,GBD数据库最新文章解读
文章题目:Temporal trends in the burden of vertebral fractures caused by falls in China and globally from 1990 to 2021: a systematic analysis of the Global Burden of Disease Study 2021 DOI:10.1186/s13690-025-01500-y 中文标题:…...
机器学习的一百个概念(9)学习曲线
前言 本文隶属于专栏《机器学习的一百个概念》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…...
浅谈Tomcat数据源连接池
目录 为什么需要JDBC连接池 Tomcat JDBC Pool 相关参数 1. 基本配置 2. 连接池大小控制 3. 连接验证与测试 4. 空闲连接回收 5. 连接泄漏与超时 Tomcat JDBC Pool 源码分析(tomcat 8.5.3) DataSourceFactory DataSource ConnectionPool Pool…...
Techub 财报解读:Circle 冲刺 IPO,但收入增长难掩利润困局
作者:Techub 财报解读 撰文:Yangz,Techub News 4 月 1 日,Circle 向美国证券交易委员会(SEC)提交 S-1 文件,计划进行首次公开募股(IPO),股票代码为 CRCL&…...
C++中的链表操作
在C中,链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据部分和指向下一个节点的指针。C标准库(STL)中提供了std::list和std::forward_list两种链表实现,分别对应双向链表和单向链表。此外&am…...
Vue2 生命周期
文章目录 前言🔄 Vue2 生命周期流程(8个核心钩子)📝 代码中典型用法示例一、您的描述验证二、完整生命周期代码示例三、关键阶段行为说明🔍 常见问题 前言 提示:以下是本篇文章正文内容,下面案…...
2007-2022年 上市公司政府补助数据 -社科数据
上市公司政府补助数据(2007-2022年)-社科数据https://download.csdn.net/download/paofuluolijiang/90028547 https://download.csdn.net/download/paofuluolijiang/90028547 政府补助是指政府为支持企业发展,提供的资金或资源支持。对于上市…...
设计心得——状态机
一、状态机 在设计一些与硬件交互或者游戏等开发中,经常会听到状态机(State Machines)这个字眼,而在设计模式(GoF)中,又经常听到状态模式这个概念,它们之间有什么联系和不同呢&…...
python match case语法
学习路线:B站 普通的if判断 def if_traffic_light(color):if color red:return Stopelif color yellow:return Slow downelif color green:return Goelse:return Invalid colorprint(if_traffic_light(red)) # Output: Stop print(if_traffic_light(yellow)) …...
Lua中协程相关函数使用详解
目录 1. coroutine.create(f)2. coroutine.resume(co [, val1, ...])3. coroutine.yield([val1, ...])4. coroutine.status(co)5. coroutine.wrap(f)6. coroutine.running()7. coroutine.isyieldable()协程状态转换示例总结 Lua 中的协程(coroutine)提供…...
代码拟有感
最近的日子像被按了0.5倍速播放键。腱鞘炎让手腕转动时发出咯吱声,尾骨的钝痛让久坐变成酷刑,落枕的脖子和酸胀的手臂组成了“疼痛交响乐”——这些隐秘的、持续的身体抗议,让原本枯燥的代码练习变成了一场生理与意志的拉锯战。 我盯着屏幕苦…...
《实战AI智能体》MCP对Agent有哪些好处
首先MCP为Agent提供了标准化的方式来接入各种工具和数据源,无论是本地运行的工具,例如通过stdio服务器,还是远程托管的服务HTTP over SSE服务, Agent都可以通过统一的接口与它们进行交互,极大扩展了第三方工具库。 例如,在金融领域,Agent 可以接入股票分析的MCP工具。当…...
maptalks获取所有图层并把图层按照zIndex排序
maptalks获取所有图层并把图层按照zIndex排序 获取所有图层 通过调用 map.getLayers() 可以返回当前地图上所有的图层集合。此方法会返回一个数组形式的结果,其中包含了地图上的每一个图层层级对象。 图层属性中的 ZINDEX 每种图层类型(如矢量图层、…...
GUI-Guider 按钮按下 选项卡 右移动一个,到最右边停下
extern lv_ui guider_ui; // 在文件顶部添加// 在按钮事件中使用: lv_obj_t * tabview guider_ui.screen_tabview_1; // 替换为你的实际 TabView 名称 uint16_t current lv_tabview_get_tab_act(tabview); lv_tabview_set_act(tabview, current 1, LV_ANIM_ON); …...
让AI再次伟大-MCP-Client开发指南
👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理、AI应用🔥如果感觉…...
sql工具怎么选?
为什么大多数主流工具又贵又难用? 有没有一款免费好用的sql工具? 像大多人朋友常用的sql工具,应该都遇到过这种情况, 用着用着收到了来自品牌方的律师函, 或者处理数据经常卡死, 再或者不支持国产数据库…...
video标签播放mp4格式视频只有声音没有图像的问题
video标签播放mp4格式视频只有声音没有图像的问题 这是由于视频格式是hevc(H265)编码的,这种编码格式视频video播放有问题主要是由于以下两种原因导致的: 1、浏览器没有开启硬加速模式: 开启方法(以谷歌浏览器为例)&a…...
问题解决:glog中的LOG(INFO)与VLOG无法打印
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。 文章目录 MotivationProcess glog版本为:https://github.com/google/glog/archive/…...
【第2月 day16】Matplotlib 散点图与柱状图
好的!以下是针对初学者的 Matplotlib 散点图与柱状图 学习内容,用简单易懂的语言和示例讲解: 一、散点图(Scatter Plot) 作用:展示两个变量之间的关系(如相关性、分布等)。 1. 核心…...
汽车 HMI 设计的发展趋势与设计要点
一、汽车HMI设计的发展历程与现状 汽车人机交互界面(HMI)设计经历了从简单到复杂、从单一到多元的演变过程。2012年以前,汽车HMI主要依赖物理按键进行操作,交互方式较为单一。随着特斯拉Model S的推出,触控屏逐渐成为…...
Vue 3 中按照某个字段将数组分成多个数组
方法一:使用 reduce 方法 const originalArray [{ id: 1, category: A, name: Item 1 },{ id: 2, category: B, name: Item 2 },{ id: 3, category: A, name: Item 3 },{ id: 4, category: C, name: Item 4 },{ id: 5, category: B, name: Item 5 }, ];const grou…...
06-Spring 中的事件驱动机制
Spring 中的事件驱动机制(ApplicationEvent 源码解析) 本小结主要总结Spring的事件,如果对于观察者模式比较熟悉的话,理解这个应该不难。 这块涉及的面试题相对简单,主要还是以日常使用为主。 另外在Spring的源码中也运…...