点击AladdinEdu,同学们用得起的【H卡】算力平台”,注册即送-H卡级别算力80G大显存按量计费灵活弹性顶级配置学生更享专属优惠


引言:破除神秘感,拥抱核心思想

在人工智能的浪潮中,Transformer模型无疑是一颗最璀璨的明珠。从GPT系列到BERT,从翻译到对话,它的身影无处不在。然而,对于许多初学者而言,Transformer常常被冠以“复杂”、“晦涩难懂”的标签,厚厚的论文和错综复杂的结构图让人望而却步。

今天,我们的目标就是亲手撕掉这层神秘的面纱。我们将不使用任何高级的深度学习框架(如Hugging Face的Transformers库),而是仅借助PyTorch提供的基础张量操作和神经网络模块,从零开始,一行代码一行代码地构建一个完整的Transformer模型。最终,我们会在一个小型数据集上训练它,让它成为一个能进行简单对话的迷你ChatBot。

相信我,当你跟着本文完成整个流程,并看到你的模型开始生成回复时,你会对Self-Attention、位置编码等核心概念有一种“顿悟”般的感觉。这不仅是一次编程练习,更是一次深入理解现代AI核心架构的绝佳旅程。

让我们开始吧!


第一部分:Transformer架构总览

在深入代码之前,我们快速回顾一下Transformer的核心设计。其最初在论文《Attention Is All You Need》中提出,完全基于Attention机制,摒弃了传统的循环和卷积结构。

一个典型的Transformer包含一个编码器(Encoder)和一个解码器(Decoder)。对于我们的聊天机器人任务,编码器负责理解输入的问句,解码器则负责生成输出的答句。

  • 编码器:由N个(原文是6个)相同的层堆叠而成。每层包含两个子层:

    1. 多头自注意力机制(Multi-Head Self-Attention)
    2. 前馈神经网络(Position-wise Feed-Forward Network)
      每个子层周围都有一个残差连接(Residual Connection)层归一化(Layer Normalization)
  • 解码器:同样由N个相同的层堆叠而成。每层包含三个子层:

    1. 掩码多头自注意力机制(Masked Multi-Head Self-Attention):确保解码时只能看到当前位置之前的信息,防止“偷看”未来答案。
    2. 多头编码器-解码器注意力机制(Multi-Head Encoder-Decoder Attention):帮助解码器关注输入序列中的相关信息。
    3. 前馈神经网络
      同样,每个子层也都有残差连接和层归一化。

此外,模型最开始有输入嵌入层位置编码,最后有输出线性层Softmax

我们的代码实现将严格遵循这个结构。我们将自底向上地构建它。


第二部分:核心模块代码实现

我们首先实现最核心、最关键的几个模块。

1. Self-Attention 与 Scaled Dot-Product Attention

Self-Attention是Transformer的灵魂。它的目的是让序列中的任何一个字都能够与序列中的所有其他字进行交互,从而更好地捕捉上下文信息。

Scaled Dot-Product Attention的计算公式如下:
Attention(Q,K,V)=softmax(QKTdk)VAttention(Q, K, V) = softmax(\frac{QK^T}{\sqrt{d_k}})VAttention(Q,K,V)=softmax(dkQKT)V

其中:

  • Q (Query):查询矩阵,代表当前要关注的词。
  • K (Key):键矩阵,代表序列中所有待被查询的词。
  • V (Value):值矩阵,代表序列中所有词的实际信息。
  • d_k:Key向量的维度,缩放因子dk\sqrt{d_k}dk用于防止点积过大导致softmax梯度消失。
import torch
import torch.nn as nn
import torch.nn.functional as F
import mathclass ScaledDotProductAttention(nn.Module):"""Scaled Dot-Product Attention"""def __init__(self, dropout_rate=0.1):super(ScaledDotProductAttention, self).__init__()self.dropout = nn.Dropout(dropout_rate)def forward(self, Q, K, V, attn_mask=None):# Q, K, V 的形状: [batch_size, n_heads, seq_len, d_k or d_v]# d_k = d_model / n_headsd_k = K.size()[-1]# 计算注意力分数 QK^T / sqrt(d_k)scores = torch.matmul(Q, K.transpose(-1, -2)) / math.sqrt(d_k)# 如果提供了注意力掩码,应用它(将mask为1的位置置为一个极小的值,如-1e9)if attn_mask is not None:scores = scores.masked_fill(attn_mask == 1, -1e9)# 对最后一维(seq_len维)进行softmax,得到注意力权重attn_weights = F.softmax(scores, dim=-1)# 可选:应用dropoutattn_weights = self.dropout(attn_weights)# 将注意力权重乘以V,得到最终的输出output = torch.matmul(attn_weights, V) # [batch_size, n_heads, seq_len, d_v]return output, attn_weights

2. Multi-Head Attention

多头注意力机制将模型分为多个“头”,让每个头去关注序列中不同的方面(例如,有的头关注语法关系,有的头关注语义关系),最后将各头的输出合并起来。

class MultiHeadAttention(nn.Module):"""Multi-Head Attention mechanism"""def __init__(self, d_model, n_heads, dropout_rate=0.1):super(MultiHeadAttention, self).__init__()assert d_model % n_heads == 0, "d_model must be divisible by n_heads"self.d_model = d_modelself.n_heads = n_headsself.d_k = d_model // n_heads # 每个头的维度self.d_v = d_model // n_heads# 线性投影层,用于生成Q, K, Vself.W_Q = nn.Linear(d_model, d_model)self.W_K = nn.Linear(d_model, d_model)self.W_V = nn.Linear(d_model, d_model)self.W_O = nn.Linear(d_model, d_model) # 输出投影层self.attention = ScaledDotProductAttention(dropout_rate)self.dropout = nn.Dropout(dropout_rate)self.layer_norm = nn.LayerNorm(d_model)def forward(self, Q, K, V, attn_mask=None):# 残差连接residual = Qbatch_size = Q.size(0)# 线性投影并分头# (batch_size, seq_len, d_model) -> (batch_size, seq_len, n_heads, d_k) -> (batch_size, n_heads, seq_len, d_k)q_s = self.W_Q(Q).view(batch_size, -1, self.n_heads, self.d_k).transpose(1, 2)k_s = self.W_K(K).view(batch_size, -1, self.n_heads, self.d_k).transpose(1, 2)v_s = self.W_V(V).view(batch_size, -1, self.n_heads, self.d_v).transpose(1, 2)# 如果需要,扩展attn_mask以匹配多头形状if attn_mask is not None:attn_mask = attn_mask.unsqueeze(1) # [batch_size, 1, seq_len, seq_len] 广播到所有头# 应用ScaledDotProductAttentioncontext, attn_weights = self.attention(q_s, k_s, v_s, attn_mask=attn_mask)# 将各头的输出拼接起来# (batch_size, n_heads, seq_len, d_v) -> (batch_size, seq_len, n_heads * d_v) = (batch_size, seq_len, d_model)context = context.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)# 输出投影output = self.W_O(context)output = self.dropout(output)# 残差连接和层归一化output = self.layer_norm(output + residual)return output, attn_weights

3. Position-wise Feed-Forward Network

这是一个简单的前馈神经网络,对每个位置(词)的特征进行独立变换。它通常包含两个线性层和一个ReLU激活函数。

class PositionWiseFFN(nn.Module):"""Position-wise Feed-Forward Network"""def __init__(self, d_model, d_ff, dropout_rate=0.1):super(PositionWiseFFN, self).__init__()self.w_1 = nn.Linear(d_model, d_ff)self.w_2 = nn.Linear(d_ff, d_model)self.dropout = nn.Dropout(dropout_rate)self.layer_norm = nn.LayerNorm(d_model)def forward(self, x):residual = xx = self.w_1(x)x = F.relu(x)x = self.dropout(x)x = self.w_2(x)x = self.dropout(x)# 残差连接和层归一化x = self.layer_norm(x + residual)return x

4. Positional Encoding(位置编码)

由于Transformer没有循环和卷积结构,它无法感知序列的顺序。因此,我们需要手动注入位置信息。这里我们使用论文中的正弦和余弦函数编码。

class PositionalEncoding(nn.Module):"""Implement the PE function."""def __init__(self, d_model, max_seq_len=5000):super(PositionalEncoding, self).__init__()# 创建一个足够长的位置编码矩阵pe = torch.zeros(max_seq_len, d_model)position = torch.arange(0, max_seq_len, dtype=torch.float).unsqueeze(1) # [max_seq_len, 1]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, max_seq_len, d_model]# 注册为一个缓冲区(buffer),它将是模型的一部分,但不被视为可训练参数self.register_buffer('pe', pe)def forward(self, x):# x 的形状: [batch_size, seq_len, d_model]x = x + self.pe[:, :x.size(1), :]return x

第三部分:组装编码器与解码器层

有了上面的积木,我们现在可以搭建编码器层和解码器层了。

1. 编码器层(Encoder Layer)

一个编码器层包含一个多头自注意力子层和一个前馈网络子层。

class EncoderLayer(nn.Module):"""A single layer of the encoder."""def __init__(self, d_model, n_heads, d_ff, dropout_rate=0.1):super(EncoderLayer, self).__init__()self.self_attn = MultiHeadAttention(d_model, n_heads, dropout_rate)self.ffn = PositionWiseFFN(d_model, d_ff, dropout_rate)def forward(self, enc_input, enc_self_attn_mask=None):# 自注意力子层enc_output, attn_weights = self.self_attn(enc_input, enc_input, enc_input, attn_mask=enc_self_attn_mask)# 前馈网络子层enc_output = self.ffn(enc_output)return enc_output, attn_weights

2. 解码器层(Decoder Layer)

一个解码器层包含三个子层:掩码自注意力、编码器-解码器注意力和前馈网络。

class DecoderLayer(nn.Module):"""A single layer of the decoder."""def __init__(self, d_model, n_heads, d_ff, dropout_rate=0.1):super(DecoderLayer, self).__init__()self.self_attn = MultiHeadAttention(d_model, n_heads, dropout_rate)self.enc_dec_attn = MultiHeadAttention(d_model, n_heads, dropout_rate)self.ffn = PositionWiseFFN(d_model, d_ff, dropout_rate)def forward(self, dec_input, enc_output, dec_self_attn_mask=None, dec_enc_attn_mask=None):# 掩码自注意力子层dec_output, self_attn_weights = self.self_attn(dec_input, dec_input, dec_input, attn_mask=dec_self_attn_mask)# 编码器-解码器注意力子层# Q 来自解码器,K, V 来自编码器输出dec_output, enc_dec_attn_weights = self.enc_dec_attn(dec_output, enc_output, enc_output, attn_mask=dec_enc_attn_mask)# 前馈网络子层dec_output = self.ffn(dec_output)return dec_output, self_attn_weights, enc_dec_attn_weights

第四部分:构建完整的Transformer模型

现在,我们将嵌入层、位置编码、编码器栈、解码器栈以及最终的输出层组合在一起。

class Transformer(nn.Module):"""The complete Transformer model."""def __init__(self, src_vocab_size, tgt_vocab_size, d_model, n_heads, n_layers, d_ff, max_seq_len, dropout_rate=0.1):super(Transformer, self).__init__()self.d_model = d_model# 输入和输出嵌入层,共享权重通常效果更好,但这里我们先分开self.enc_embedding = nn.Embedding(src_vocab_size, d_model)self.dec_embedding = nn.Embedding(tgt_vocab_size, d_model)self.pos_encoding = PositionalEncoding(d_model, max_seq_len)# 编码器和解码器堆叠self.encoder_layers = nn.ModuleList([EncoderLayer(d_model, n_heads, d_ff, dropout_rate) for _ in range(n_layers)])self.decoder_layers = nn.ModuleList([DecoderLayer(d_model, n_heads, d_ff, dropout_rate) for _ in range(n_layers)])# 最终的线性层和softmaxself.linear = nn.Linear(d_model, tgt_vocab_size)self.dropout = nn.Dropout(dropout_rate)def forward(self, src_input, tgt_input, src_mask=None, tgt_mask=None):# 编码器部分enc_output = self.enc_embedding(src_input) * math.sqrt(self.d_model)enc_output = self.pos_encoding(enc_output)enc_output = self.dropout(enc_output)for layer in self.encoder_layers:enc_output, _ = layer(enc_output, enc_self_attn_mask=src_mask)# 解码器部分dec_output = self.dec_embedding(tgt_input) * math.sqrt(self.d_model)dec_output = self.pos_encoding(dec_output)dec_output = self.dropout(dec_output)for layer in self.decoder_layers:dec_output, _, _ = layer(dec_output, enc_output, dec_self_attn_mask=tgt_mask)# 输出投影output = self.linear(dec_output)# Softmax在损失函数中计算,这里直接返回logitsreturn output

第五部分:数据准备与训练

1. 选择一个迷你数据集

为了快速实验,我们使用一个非常小的对话数据集。例如,我们可以手动创建一个:

Q: Hi
A: Hello!
Q: What's your name?
A: I'm ChatBot.
Q: How are you?
A: I'm fine, thank you.
... (再多几十组)

或者使用Cornell Movie Dialogs Corpus的一小部分。我们需要构建一个词汇表,并将句子转换为ID序列。

2. 构建词汇表和DataLoader

# 伪代码:构建词汇表
# sentences = [所有Q和A的句子]
# vocab = {'<pad>':0, '<sos>':1, '<eos>':2, ...} 构建词汇字典
# src_ids = [[vocab[word] for word in sentence.split()] for sentence in src_sentences]# 使用PyTorch的DataLoader和Dataset
from torch.utils.data import Dataset, DataLoaderclass ChatDataset(Dataset):def __init__(self, src_sentences, tgt_sentences, vocab, max_len):self.src_sentences = src_sentencesself.tgt_sentences = tgt_sentencesself.vocab = vocabself.max_len = max_lendef __len__(self):return len(self.src_sentences)def __getitem__(self, idx):src_seq = self.sentence_to_ids(self.src_sentences[idx])tgt_seq = self.sentence_to_ids(self.tgt_sentences[idx])# 添加起始符<sos>和结束符<eos>tgt_input = [self.vocab['<sos>']] + tgt_seqtgt_output = tgt_seq + [self.vocab['<eos>']]# 填充到最大长度src_seq = self.pad_seq(src_seq, self.max_len)tgt_input = self.pad_seq(tgt_input, self.max_len)tgt_output = self.pad_seq(tgt_output, self.max_len)return torch.LongTensor(src_seq), torch.LongTensor(tgt_input), torch.LongTensor(tgt_output)# ... (实现sentence_to_ids和pad_seq方法)

3. 创建注意力掩码和训练循环

我们需要创建两种掩码:

  1. 填充掩码(Padding Mask):遮盖掉<pad>符号,防止注意力机制关注这些无意义的位置。
  2. 序列掩码(Sequence Mask):用于解码器的自注意力,防止解码时看到未来的信息(一个下三角矩阵)。
def create_padding_mask(seq, pad_idx):# seq: [batch_size, seq_len]return (seq == pad_idx).unsqueeze(1).unsqueeze(2) # [batch_size, 1, 1, seq_len] 便于广播def create_look_ahead_mask(seq_len):# 创建一个下三角矩阵,对角线及其以上为0,以下为1mask = torch.triu(torch.ones(seq_len, seq_len), diagonal=1).bool()return mask.unsqueeze(0).unsqueeze(0) # [1, 1, seq_len, seq_len]

训练循环 的标准流程:准备数据、计算模型输出、计算损失(带忽略<pad>的CrossEntropyLoss)、反向传播、优化器步进。

# 初始化模型、优化器、损失函数
model = Transformer(src_vocab_size, tgt_vocab_size, d_model=512, n_heads=8, n_layers=6, d_ff=2048, max_seq_len=100)
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4, betas=(0.9, 0.98), eps=1e-9)
criterion = nn.CrossEntropyLoss(ignore_index=pad_idx) # 忽略padding位置的损失for epoch in range(num_epochs):model.train()for batch in dataloader:src, tgt_in, tgt_out = batchsrc_mask = create_padding_mask(src, pad_idx)# 解码器掩码:填充掩码 + 序列掩码tgt_padding_mask = create_padding_mask(tgt_in, pad_idx)tgt_look_ahead_mask = create_look_ahead_mask(tgt_in.size(1))tgt_mask = torch.logical_or(tgt_padding_mask, tgt_look_ahead_mask) # 组合掩码optimizer.zero_grad()output = model(src, tgt_in, src_mask, tgt_mask)# output: [batch_size, tgt_len, tgt_vocab_size]# tgt_out: [batch_size, tgt_len]loss = criterion(output.view(-1, output.size(-1)), tgt_out.view(-1))loss.backward()optimizer.step()# ... 每个epoch结束后可以打印损失或进行验证

第六部分:推理与对话生成

训练完成后,我们使用贪心搜索(Greedy Search)来生成回复。

def predict(model, src_sentence, vocab, inv_vocab, max_len, device):model.eval()with torch.no_grad():# 将源句子转换为IDsrc_ids = sentence_to_ids(src_sentence, vocab)src_tensor = torch.LongTensor(src_ids).unsqueeze(0).to(device) # [1, src_len]# 初始化目标输入,起始为<sos>tgt_ids = [vocab['<sos>']]for i in range(max_len):tgt_tensor = torch.LongTensor(tgt_ids).unsqueeze(0).to(device) # [1, current_tgt_len]# 创建掩码src_mask = create_padding_mask(src_tensor, pad_idx)tgt_mask = create_look_ahead_mask(len(tgt_ids))# 预测下一个词output = model(src_tensor, tgt_tensor, src_mask, tgt_mask)next_word_logits = output[0, -1, :] # 最后一个位置的输出next_word_id = torch.argmax(next_word_logits, dim=-1).item()tgt_ids.append(next_word_id)if next_word_id == vocab['<eos>']:break# 将ID序列转换回句子,忽略<sos>和<eos>predicted_sentence = ids_to_sentence(tgt_ids[1:-1], inv_vocab)return predicted_sentence# 示例用法
# vocab: 词汇表,inv_vocab: 反向词汇表(id到word)
# response = predict(model, "Hello there", vocab, inv_vocab, max_len=20, device='cpu')
# print(response)

总结与展望

恭喜你!你已经从零开始实现并训练了一个Transformer模型。这个过程无疑充满挑战,但它极大地深化了你对Self-Attention、位置编码、掩码等核心概念的理解。

我们的迷你ChatBot虽然简单,但它已经具备了Transformer架构的所有精髓。你可以通过以下方式进一步提升它:

  1. 使用更大更高质量的数据集
  2. 调整超参数d_model, n_heads, n_layers, d_ff等。
  3. 实现更高级的解码策略:如Beam Search。
  4. 尝试预训练:在海量文本上先进行无监督预训练,再在我们的对话数据上进行微调。
  5. 加入更多技巧:如标签平滑、学习率预热等。

希望这次“手撕”Transformer的经历让你不再觉得它神秘莫测。它只是一个精心设计的神经网络,其力量源于对序列数据中复杂依赖关系的强大建模能力。现在,你已经掌握了它的蓝图,可以自由地去探索、修改和创新了!

(注意:由于篇幅和可运行性限制,本文代码为示例性质,可能需要一些调试和修改才能完全运行。建议在Jupyter Notebook或Colab中分模块逐步测试。)


点击AladdinEdu,同学们用得起的【H卡】算力平台”,注册即送-H卡级别算力80G大显存按量计费灵活弹性顶级配置学生更享专属优惠

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

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

相关文章

【20期】沪深指数《实时交易数据》免费获取股票数据API:PythonJava等5种语言调用实例演示与接口API文档说明

​ 随着量化投资在金融市场的快速发展&#xff0c;高质量数据源已成为量化研究的核心基础设施。本文将系统介绍股票量化分析中的数据获取解决方案&#xff0c;涵盖实时行情、历史数据及基本面信息等关键数据类型。 本文将重点演示这些接口在以下技术栈中的实现&#xff1a; P…

RabbitMQ如何保障消息的可靠性

文章目录什么是消息可靠性&#xff1f;RabbitMQ消息可靠性的三个维度1. 生产者到Exchange的可靠性2. Exchange到Queue的可靠性3. Queue到消费者的可靠性核心机制详解Publisher Confirm机制消息持久化Mandatory参数消费者确认机制&#xff08;ACK&#xff09;最佳实践建议1. 合理…

二十、DevOps落地:Jenkins基础入门(一)

二十、DevOps落地&#xff1a;Jenkins基础入门&#xff08;一&#xff09; 文章目录二十、DevOps落地&#xff1a;Jenkins基础入门&#xff08;一&#xff09;1、DevOps初识1.1 什么是DevOps1.2 DevOps相关工具链1.3 什么是CICD&#xff1f;1.4 持续集成CI介绍1.5 持续交付和持…

简单易实现的数据校验方法Checksum

简单易实现的数据校验方法Checksum 在数据传输中&#xff0c;Checksum&#xff08;校验和&#xff09; 扮演着 “数据完整性哨兵” 的角色。它的主要作用是 快速检测数据在传输过程中是否发生了错误 。 下面我将详细解释它的作用、工作原理、优缺点以及典型应用。 核心作用&…

再次深入学习深度学习|花书笔记1

我已经两年没有碰过深度学习了&#xff0c;写此文记录学习过程&#xff0c;加深理解。 深度学习再次深入学习深度学习|花书笔记1信息论第四节 数值计算中的问题上溢出 和 下溢出病态条件优化法再次深入学习深度学习|花书笔记1 这本书说的太繁琐了&#xff0c;如果是想要基于这…

DeerFlow实践:华为LTC流程的评审智能体设计

目录 一、机制设计核心逻辑 二、4 个评审点智能体机制详解 &#xff08;一&#xff09;立项决策&#xff08;ATI&#xff09;智能体机制 1. 知识调用与匹配 2. 评审校验流程 3. 异常处理 &#xff08;二&#xff09;投标决策&#xff08;ATB&#xff09;智能体机制 1. …

C++与Lua交互:从原理到实践指南

核心原理&#xff1a;Lua虚拟栈机制 C与Lua能够高效交互的核心在于Lua虚拟栈的设计&#xff0c;这是一个精巧的中立通信区&#xff0c;解决了两种语言间的本质差异&#xff1a;特性对比CLua语言类型静态编译型动态解释型数据管理明确内存布局虚拟机统一管理类型系统编译时确定运…

CSS 编码规范

CSS 编码规范1 CSS1.1 编码规范1.1.1 【强制】所有声明必须以分号结尾1.1.2 【推荐】使用 2 个空格缩进1.1.3 【推荐】选择器与 { 之间保留一个空格1.1.4 【推荐】属性值规范1.1.5 【推荐】组合器规范1.1.6 【推荐】逗号分隔规范1.1.7 【推荐】注释规范1.1.8 【推荐】右大括号规…

ORA-12514:TNS:监听程序当前无法识别连接描述符中请求的服务

已经不止一次自己本机电脑安装的Oracle使用plsqldev软件登入提示这个了.一般前一天还好好的&#xff0c;今天就不行了.好好总结一下吧&#xff0c;也共大家一起借鉴.主要原因还是数据的归档日志因为内部内存已经耗尽&#xff0c;不能在进行归档导致数据库启动异常&#xff0c;没…

Spring框架的JDBC模板技术和事务管理

SpringJDBCJDBC模板技术概述JDBC的模板类的使用Spring框架的事务管理配置文件方式半注解的方式纯注解的方式JDBC模板技术概述 什么是 JDBC 模板技术&#xff1f; JDBC 模板技术是 Spring 框架为简化持久层&#xff08;数据库操作&#xff09;编程而提供的一种封装机制&#xf…

将文件部署到受管主机

目录 1.ansible.builtin中用于创建、更新或删除多行文本块的模块是什么 2.copy模块的作用 3.fetch模块的作用 4.file模块的作用 5.lineinfile模块的作用 6.stat模块的作用 7.要确保受管主机上存在文件&#xff0c;类似touch命令功能&#xff0c;还能设置权限等的模块及操作是怎…

Dell PowerEdge R620 服务器内存和硬盘罢工了

文章目录前言调查原因查找解决方案硬盘问题内存问题总结前言 月黑风高夜&#xff0c;服务宕机时。做服务端技术的&#xff0c;谁还没半夜遇到个服务挂掉的情况&#xff0c;而像我这种半兼职网管的工作&#xff0c;遇到机器问题的概率也就更大了&#xff0c;本来周五晚上写完总…

2025:SourceTree 启用/禁用Mercurial 或 Git,像素级细节

最近使用Git管理工具的时候&#xff0c;发现还是SourceTree好用些&#xff0c;但是使用SourceTree带来一个问题&#xff1a;就是每次在重新打开SourceTree的时候&#xff0c;都会重新下载Mercurial.zip文件&#xff0c;查了一下&#xff0c;一般情况下我们是不需要使用Mercuria…

安卓 Google Maps 的使用和开发步骤

文章目录1. main2. Android 谷歌地图3. 源码Reference1. main 在国内选择的SDK可以是高德、百度、腾讯、xxxx等&#xff0c;但在国外&#xff0c;你首选是谷歌&#xff0c;因此要进行Google地图的开发你首先要解决下面三个问题 VPN Google账号 信用卡American Express&#x…

Linux -- 应用层协议Http

1.HTTP背景知识 HTTP协议&#xff1a;HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;的本质是运行在 TCP/IP 协议族之上的 “应用层协议”&#xff0c;核心作用是定义客户端&#xff08;如浏览器、APP&#xff09;与服务器之间的 “数据…

R 语言本身并不直接支持 Python 中 f“{series_matrix}.txt“ 这样的字符串字面量格式化(f-string)语法 glue函数

R 语言本身并不直接支持 Python 中 f"{series_matrix}.txt" 这样的字符串字面量格式化&#xff08;f-string&#xff09;语法。 在 R 中&#xff0c;要实现字符串拼接或格式化&#xff0c;你需要使用其他方法。下表对比了 Python f-string 和 R 中常见对应方法的主要…

【AI智能体】亮数据MCP Server × Dify:AI智能体获取实时影音数据就是这么简单

文章目录一、引言&#xff1a;AI 应用与实时影音数据的融合价值1、传统采集方式的痛点2、MCP Server 的创新价值二、亮数据 MCP Server 概览1、什么是 MCP Server&#xff1f;2、支持的影音平台和API接口3、产品特色亮点三、业务场景示例设计1、选定场景&#xff1a;竞品分析与…

从《Attention Is All You Need》深入理解Transformer

2017年的《Attention Is All You Need》论文提出的Transformer架构&#xff0c;不仅彻底改变了自然语言处理的格局&#xff0c;更为现代人工智能的发展奠定了坚实基础。本文将带你深入解析这一划时代模型的核心思想、技术细节及其深远影响。&#x1f504; 一、背景与动机&#…

【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡

【08】AI辅助编程完整的安卓二次商业实战-修改消息聊天框背景色-触发聊天让程序异常终止bug牵涉更多聊天消息发送优化处理-优雅草卓伊凡引言本次二开布局没有变&#xff0c;但是下一次整体布局会有变&#xff0c;不过本次开发发现朋友圈跳转功能的流程步骤也做了一定的变化。原…

心理调适与情绪管理实训室:支撑康养旅游人才心理能力培养

在康养休闲旅游服务专业的教学体系中&#xff0c;心理调适与情绪管理实训室作为关键教学场所&#xff0c;承担着培养学生心理服务能力、情绪疏导技能和人际沟通素养的重要任务。随着社会对康养旅游服务质量要求的提升&#xff0c;具备心理调适与情绪管理能力的专业人才日益受到…