【自然语言处理(NLP)】深度学习架构:Transformer 原理及代码实现
文章目录
- 介绍
- Transformer
- 核心组件
- 架构图
- 编码器(Encoder)
- 解码器(Decoder)
- 优点
- 应用
- 代码实现
- 导包
- 基于位置的前馈网络
- 残差连接后进行层规范化
- 编码器 Block
- 编码器
- 解码器 Block
- 解码器
- 训练
- 预测
个人主页:道友老李
欢迎加入社区:道友老李的学习社区
介绍
**自然语言处理(Natural Language Processing,NLP)**是计算机科学领域与人工智能领域中的一个重要方向。它研究的是人类(自然)语言与计算机之间的交互。NLP的目标是让计算机能够理解、解析、生成人类语言,并且能够以有意义的方式回应和操作这些信息。
NLP的任务可以分为多个层次,包括但不限于:
- 词法分析:将文本分解成单词或标记(token),并识别它们的词性(如名词、动词等)。
- 句法分析:分析句子结构,理解句子中词语的关系,比如主语、谓语、宾语等。
- 语义分析:试图理解句子的实际含义,超越字面意义,捕捉隐含的信息。
- 语用分析:考虑上下文和对话背景,理解话语在特定情境下的使用目的。
- 情感分析:检测文本中表达的情感倾向,例如正面、负面或中立。
- 机器翻译:将一种自然语言转换为另一种自然语言。
- 问答系统:构建可以回答用户问题的系统。
- 文本摘要:从大量文本中提取关键信息,生成简短的摘要。
- 命名实体识别(NER):识别文本中提到的特定实体,如人名、地名、组织名等。
- 语音识别:将人类的语音转换为计算机可读的文字格式。
NLP技术的发展依赖于算法的进步、计算能力的提升以及大规模标注数据集的可用性。近年来,深度学习方法,特别是基于神经网络的语言模型,如BERT、GPT系列等,在许多NLP任务上取得了显著的成功。随着技术的进步,NLP正在被应用到越来越多的领域,包括客户服务、智能搜索、内容推荐、医疗健康等。
Transformer
Transformer是一种深度学习架构,最初在2017年的论文《Attention Is All You Need》中被提出,它在自然语言处理(NLP)等领域取得了巨大的成功,并引发了后续一系列相关研究和技术的发展。
核心组件
- 多头注意力机制(Multi-Head Attention)
- 原理:将输入的向量表示通过多个头(head)的注意力机制,并行地计算不同位置之间的依赖关系,从而捕捉到更丰富的语义信息。每个头都可以关注输入序列的不同部分,然后将这些头的结果进行拼接和线性变换,得到最终的输出。
- 公式: M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , ⋯ , h e a d h ) W O MultiHead(Q,K,V)=Concat(head_1,\cdots,head_h)W^O MultiHead(Q,K,V)=Concat(head1,⋯,headh)WO,其中 h e a d i = A t t e n t i o n ( Q W i Q , K W i K , V W i V ) head_i = Attention(QW_i^Q,KW_i^K,VW_i^V) headi=Attention(QWiQ,KWiK,VWiV), A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V)=softmax(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dkQKT)V。
- 作用:能够自适应地聚焦于输入序列中的不同位置,有效地捕捉长序列中的依赖关系,相比传统的循环神经网络(RNN)和卷积神经网络(CNN),在处理长序列数据时具有更好的性能和可并行性。
- 编码器和解码器
- 编码器:由多个堆叠的编码器层组成,每个编码器层包含多头注意力机制和前馈神经网络(Feed Forward Network,FFN),还使用了残差连接和层归一化(Layer Normalization)技术。其作用是将输入序列编码成一个固定长度的向量表示,提取输入序列中的特征。
- 解码器:同样由多个解码器层堆叠而成,与编码器类似,但在多头注意力机制部分有所不同,解码器还包含一个掩码多头注意力(Masked Multi-Head Attention)层,用于防止解码器在生成当前位置的输出时看到未来的信息。解码器的任务是根据编码器的输出和之前已经生成的输出序列,逐步生成目标序列。
架构图

编码器(Encoder)
- 嵌入层(Embedding Layer):将输入的离散符号(如单词)转换为连续的向量表示,也就是词嵌入。
- 位置编码(Positional Encoding):由于Transformer本身不具备捕捉序列顺序信息的能力,位置编码将位置信息加入到词嵌入中,以便模型能区分不同位置的元素。
- 多头注意力(Multi - Head Attention):通过多个头并行计算注意力,捕捉输入序列不同位置之间的依赖关系和语义信息。
- 逐位前馈网络(Feed - Forward Network):对多头注意力的输出进行进一步非线性变换,增强模型的表达能力。
- 加 & 规范化(Add & Normalization):采用残差连接(Add)将输入直接加到注意力或前馈网络的输出上,防止梯度消失等问题;层归一化(Normalization)对数据进行归一化处理,加速训练收敛。
解码器(Decoder)
- 嵌入层和位置编码:与编码器作用类似,处理目标序列。
- 掩码多头注意力(Masked Multi - Head Attention):在生成目标序列时,为了防止解码器提前看到未来的信息,使用掩码操作遮盖后续位置,保证生成过程符合自回归特性。
- 多头注意力:这里的多头注意力用于建立目标序列和编码器输出之间的联系,帮助解码器根据源序列信息生成目标序列。
- 逐位前馈网络和加 & 规范化:与编码器中的作用相同,进行非线性变换和归一化等操作。
- 全连接层(Fully - Connected Layer):将解码器的输出映射到目标词汇表的维度,通过softmax函数得到每个词的生成概率,用于最终的输出预测。
Transformer架构通过编码器和解码器的多层结构,利用多头注意力机制高效地捕捉序列中的依赖关系,在自然语言处理等诸多领域有着广泛且出色的应用。
优点
- 并行计算能力:Transformer可以并行计算所有位置的输出,大大提高了训练和推理的速度,相比需要顺序处理每个时间步的RNN和其变体(如LSTM、GRU),能够更高效地利用现代硬件设备(如GPU、TPU)的并行计算能力。
- 长序列建模能力:通过自注意力机制,Transformer能够直接建模输入序列中任意两个位置之间的依赖关系,而不受序列长度的限制,能够很好地处理长序列数据,避免了RNN在处理长序列时可能出现的梯度消失或爆炸问题。
- 灵活的特征提取能力:多头注意力机制可以同时关注输入序列的不同方面,能够自动学习到文本中的各种语义和句法结构,提取更丰富、更抽象的特征,对各种自然语言任务具有很强的适应性。
应用
- 自然语言处理领域
- 机器翻译:Transformer在机器翻译任务中取得了显著的成果,能够将一种语言准确地翻译成另一种语言,例如谷歌的GNMT(Google Neural Machine Translation)系统采用了Transformer架构,大大提高了翻译质量和效率。
- 文本生成:可以用于生成各种类型的文本,如对话生成、故事生成、诗歌生成等,如OpenAI的GPT系列模型基于Transformer架构,能够生成连贯、有逻辑的自然语言文本。
- 文本分类:对文本进行分类,如情感分类、新闻分类等,通过对文本的特征提取和表示学习,Transformer能够准确地判断文本所属的类别。
- 其他领域
- 计算机视觉:一些研究将Transformer应用于图像识别、目标检测、图像生成等任务中,如Vision Transformer(ViT)将图像分块后,将其视为序列输入到Transformer中,取得了与传统CNN相当甚至更好的性能。
- 语音识别:在语音识别任务中,Transformer也被用于对语音信号的特征进行建模和处理,提高语音识别的准确率。
代码实现
导包
import math
import pandas as pd
import torch
from torch import nn
import dltools
基于位置的前馈网络
class PositionWiseFFN(nn.Module):def __init__(self, ffn_num_input, ffn_num_hiddens, ffn_num_outputs, **kwargs):super().__init__(**kwargs)self.dense1 = nn.Linear(ffn_num_input, ffn_num_hiddens)self.relu = nn.ReLU()self.dense2 = nn.Linear(ffn_num_hiddens, ffn_num_outputs)def forward(self, X):return self.dense2(self.relu(self.dense1(X)))
根据经验, 传入全连接的数据一般要求是二维. 但序列数据一般是三维, ffn中就需要降维. 一般是把batch独立, 其他维度合并.这里因为序列的有效长度不相同,所以把batch_size和num_steps合并, 再做全连接。
残差连接后进行层规范化
class AddNorm(nn.Module):def __init__(self, normalized_shape, dropout, **kwargs):super().__init__(**kwargs)self.dropout = nn.Dropout(dropout)self.ln = nn.LayerNorm(normalized_shape)def forward(self, X, Y):return self.ln(self.dropout(Y) + X)
- batch normalization 和layer normalization的区别:
- bn是每个通道样本间进行归一化, LN是每个样本通道间归一化, 就相当于对一句话做norm
- 假如现在有b句话, 每句话的长度(即序列长度)len, 每个词有d个特征表示(embed_size), bn就是对所有句子所有词的某个特征做归一化.
- LN就是对某一句话所有的词的所有特征做归一化.
示例:
ln = nn.LayerNorm(2)
bn = nn.BatchNorm1d(2)
X = torch.tensor([[1, 2], [2, 3]], dtype=torch.float32)
# 计算ln和bn的结果
print('LN:', ln(X), '\n BN:', bn(X))
LN: tensor([[-1.0000, 1.0000],[-1.0000, 1.0000]], grad_fn=<NativeLayerNormBackward0>)
BN: tensor([[-1.0000, -1.0000],[ 1.0000, 1.0000]], grad_fn=<NativeBatchNormBackward0>)
一定要注意, 使用了残差结构, 输入数据的维度一定要相同!
编码器 Block
class EncoderBlock(nn.Module):def __init__(self, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, dropout, use_bias=False, **kwargs):super().__init__(**kwargs)self.attention = dltools.MultiHeadAttention(key_size, query_size, value_size, num_hiddens, num_heads, dropout, use_bias)self.addnorm1 = AddNorm(norm_shape, dropout)self.ffn = PositionWiseFFN(ffn_num_input, ffn_num_hiddens, num_hiddens)self.addnorm2 = AddNorm(norm_shape, dropout)def forward(self, X, valid_lens):Y = self.addnorm1(X, self.attention(X, X, X, valid_lens))return self.addnorm2(Y, self.ffn(Y))
使用示例:
X = torch.ones((2, 100, 24))
valid_lens = torch.tensor([3, 2])
encoder_blk = EncoderBlock(24, 24, 24, 24, [100, 24], 24, 48, 8, 0.5)
encoder_blk.eval()
encoder_blk(X, valid_lens).shape
torch.Size([2, 100, 24])
编码器
class TransformerEncoder(dltools.Encoder):def __init__(self, vocab_size, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, num_layers, dropout, use_bias=False, **kwargs):super().__init__(**kwargs)self.num_hiddens = num_hiddensself.embedding = nn.Embedding(vocab_size, num_hiddens)self.pos_encoding = dltools.PositionalEncoding(num_hiddens, dropout)self.blks = nn.Sequential()for i in range(num_layers):self.blks.add_module('block' + str(i), EncoderBlock(key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, dropout, use_bias))def forward(self, X, valid_lens, *args):# 对embedding之后的数据进行缩放, 有助于收敛X = self.pos_encoding(self.embedding(X) * math.sqrt(self.num_hiddens))self.attention_weights = [None] * len(self.blks)for i, blk in enumerate(self.blks):X = blk(X, valid_lens)self.attention_weights[i] = blk.attention.attention.attention_weightsreturn X
使用示例:
encoder = TransformerEncoder(200, 24, 24, 24, 24, [100, 24], 24, 48, 8, 2, 0.3)
encoder.eval()
X = torch.ones((2, 100), dtype=torch.long)
encoder(X, valid_lens).shape
torch.Size([2, 100, 24])
解码器 Block

class DecoderBlock(nn.Module):def __init__(self, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, dropout, i, **kwargs):super().__init__(**kwargs)self.i = iself.attention1 = dltools.MultiHeadAttention(key_size, query_size, value_size, num_hiddens, num_heads, dropout)self.addnorm1 = AddNorm(norm_shape, dropout)self.attention2 = dltools.MultiHeadAttention(key_size, query_size, value_size, num_hiddens, num_heads, dropout)self.addnorm2 = AddNorm(norm_shape, dropout)self.ffn = PositionWiseFFN(ffn_num_input, ffn_num_hiddens, num_hiddens)self.addnorm3 = AddNorm(norm_shape, dropout)def forward(self, X, state):enc_outputs, enc_valid_lens = state[0], state[1]if state[2][self.i] is None:key_values = Xelse:# 预测: 预测需要把前面时刻预测得到的信息和当前block的输出得到的信息拼到一起. key_values = torch.cat((state[2][self.i], X), axis=1)state[2][self.i] = key_values# 在训练的时候需要对真实值进行遮蔽if self.training:# (batch_size, num_steps), 每一行是[1, 2, ..., num_steps]batch_size, num_steps, _ = X.shapedec_valid_lens = torch.arange(1, num_steps + 1, device=X.device).repeat(batch_size, 1)else:dec_valid_lens = None# 自注意力X2 = self.attention1(X, key_values, key_values, dec_valid_lens)Y = self.addnorm1(X, X2)Y2 = self.attention2(Y, enc_outputs, enc_outputs, enc_valid_lens)Z = self.addnorm2(Y, Y2)return self.addnorm3(Z, self.ffn(Z)), state
使用示例:
decoder_blk = DecoderBlock(24, 24, 24, 24, [100, 24], 24, 48, 8, 0.5, 0)
decoder_blk.eval()
X = torch.ones((2, 100, 24))
state = [encoder_blk(X, valid_lens), valid_lens, [None]]
result1, result2 = decoder_blk(X, state)
result1.shape
torch.Size([2, 100, 24])
解码器
class TransformerDecoder(dltools.AttentionDecoder):def __init__(self, vocab_size, key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, num_layers, dropout, **kwargs):super().__init__(**kwargs)self.num_hiddens = num_hiddensself.num_layers = num_layersself.embedding = nn.Embedding(vocab_size, num_hiddens)self.pos_embedding = dltools.PositionalEncoding(num_hiddens, dropout)self.blks = nn.Sequential()for i in range(num_layers):self.blks.add_module('block' + str(i), DecoderBlock(key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, dropout, i))self.dense = nn.Linear(num_hiddens, vocab_size)def init_state(self, enc_outputs, enc_valid_lens, *args):return [enc_outputs, enc_valid_lens, [None]*self.num_layers]def forward(self, X, state):X = self.pos_embedding(self.embedding(X) * math.sqrt(self.num_hiddens))self._attention_weights = [[None] * len(self.blks) for _ in range(2)]for i, blk in enumerate(self.blks):X, state = blk(X, state)self._attention_weights[0][i] = blk.attention1.attention.attention_weightsself._attention_weights[1][i] = blk.attention2.attention.attention_weightsreturn self.dense(X), state@propertydef attention_weights(self):return self._attention_weights
训练
num_hiddens, num_layers, dropout, batch_size, num_steps = 32, 2, 0.1, 64, 10
lr, num_epochs, device = 0.005, 200, dltools.try_gpu()
ffn_num_input, ffn_num_hiddens, num_heads = 32, 64, 4
key_size, query_size, value_size = 32, 32, 32
norm_shape = [32]train_iter, src_vocab, tgt_vocab = dltools.load_data_nmt(batch_size, num_steps)encoder = TransformerEncoder(len(src_vocab), key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, num_layers, dropout)
decoder = TransformerDecoder(len(tgt_vocab), key_size, query_size, value_size, num_hiddens, norm_shape, ffn_num_input, ffn_num_hiddens, num_heads, num_layers, dropout)
net = dltools.EncoderDecoder(encoder, decoder)
dltools.train_seq2seq(net, train_iter, lr, num_epochs, tgt_vocab, device)




预测
engs = ['go .', 'i lost .', 'he\'s calm .', 'i\'m home .']
fras = ['va !', 'j\'ai perdu .', 'il est calme .', 'je suis chez moi .']
for eng, fra in zip(engs, fras):translation = dltools.predict_seq2seq(net, eng, src_vocab, tgt_vocab, num_steps, device)print(f'{eng} => {translation}, bleu {dltools.bleu(translation[0], fra, k=2):.3f}')
go . => ('va !', []), bleu 1.000
i lost . => ("j'ai perdu .", []), bleu 1.000
he's calm . => ('il est calme .', []), bleu 1.000
i'm home . => ('je suis chez moi .', []), bleu 1.000
相关文章:
【自然语言处理(NLP)】深度学习架构:Transformer 原理及代码实现
文章目录 介绍Transformer核心组件架构图编码器(Encoder)解码器(Decoder) 优点应用代码实现导包基于位置的前馈网络残差连接后进行层规范化编码器 Block编码器解码器 Block解码器训练预测 个人主页:道友老李 欢迎加入社…...
【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(二)
目录 1 -> HML语法 1.1 -> 页面结构 1.2 -> 数据绑定 1.3 -> 普通事件绑定 1.4 -> 冒泡事件绑定5 1.5 -> 捕获事件绑定5 1.6 -> 列表渲染 1.7 -> 条件渲染 1.8 -> 逻辑控制块 1.9 -> 模板引用 2 -> CSS语法 2.1 -> 尺寸单位 …...
当WebGIS遇到智慧文旅-以长沙市不绕路旅游攻略为例
目录 前言 一、旅游数据组织 1、旅游景点信息 2、路线时间推荐 二、WebGIS可视化实现 1、态势标绘实现 2、相关位置展示 三、成果展示 1、第一天旅游路线 2、第二天旅游路线 3、第三天旅游路线 4、交通、订票、住宿指南 四、总结 前言 随着信息技术的飞速发展&…...
《大数据时代“快刀”:Flink实时数据处理框架优势全解析》
在数字化浪潮中,数据呈爆发式增长,实时数据处理的重要性愈发凸显。从金融交易的实时风险监控,到电商平台的用户行为分析,各行业都急需能快速处理海量数据的工具。Flink作为一款开源的分布式流处理框架,在这一领域崭露头…...
【机器学习理论】朴素贝叶斯网络
基础知识: 先验概率:对某个事件发生的概率的估计。可以是基于历史数据的估计,可以由专家知识得出等等。一般是单独事件概率。 后验概率:指某件事已经发生,计算事情发生是由某个因素引起的概率。一般是一个条件概率。 …...
使用Pygame制作“吃豆人”游戏
本篇博客展示如何使用 Python Pygame 编写一个简易版的“吃豆人(Pac-Man)” 风格游戏。这里我们暂且命名为 Py-Man。玩家需要控制主角在一个网格地图里移动、吃掉散布在各处的豆子,并躲避在地图中巡逻的幽灵。此示例可帮助你理解网格地图、角…...
使用 Docker(Podman) 部署 MongoDB 数据库及使用详解
在现代开发环境中,容器化技术(如 Docker 和 Podman)已成为部署和管理应用程序的标准方式。本文将详细介绍如何使用 Podman/Docker 部署 MongoDB 数据库,并确保其他应用程序容器能够通过 Docker 网络成功连接到 MongoDB。我们将逐步…...
SQL入门到精通 理论+实战 -- 在 MySQL 中学习SQL语言
目录 一、环境准备 1、MySQL 8.0 和 Navicat 下载安装 2、准备好的表和数据文件: 二、SQL语言简述 1、数据库基础概念 2、什么是SQL 3、SQL的分类 4、SQL通用语法 三、DDL(Data Definition Language):数据定义语言 1、操…...
Electricity Market Optimization 探索系列(一)
本文参考链接:Linear Programming Mini Example 先从一个线性规划的例子说起: 问题背景: 现在需要使用两台发电机满足用户的用电需求,发电机一的发电功率上限是 6MW,发电机二的发电功率上限是 4MW,发电…...
x86-64数据传输指令
关于汇编语言一些基础概念的更详细的介绍,可移步MIPS指令集(一)基本操作_mips指令 sw-CSDN博客 该指令集中一个字2字节。 该架构有16个64位寄存器,名字都以%r开头,每个寄存器的最低位字节,低1~2位字节&…...
【ESP32】ESP-IDF开发 | WiFi开发 | TCP传输控制协议 + TCP服务器和客户端例程
1. 简介 TCP(Transmission Control Protocol),全称传输控制协议。它的特点有以下几点:面向连接,每一个TCP连接只能是点对点的(一对一);提供可靠交付服务;提供全双工通信&…...
算法基础学习——快排与归并(附带java模版)
快速排序和归并排序是两种速度较快的排序方式,是最应该掌握的两种排序算法, (一)快速排序(不稳定的) 基本思想:分治 平均时间复杂度:O(nlogn) / 最慢O(n^2) / 最快O(n) 步骤&…...
指针的进化—sizeof和strlen对比(字符串和字符数组的区分)
1.前言 如果你对各个数组的内容存放是什么没有个清晰的概念,对指针偏移之后的数量算不出来或者模棱两可,那么本篇就来详细介绍sizeof和strlen来具象化的显示数组的内容存放了多少内容,偏移量变化后的变化,这个数组进行运算后会不会…...
TensorFlow简单的线性回归任务
如何使用 TensorFlow 和 Keras 创建、训练并进行预测 1. 数据准备与预处理 2. 构建模型 3. 编译模型 4. 训练模型 5. 评估模型 6. 模型应用与预测 7. 保存与加载模型 8.完整代码 1. 数据准备与预处理 我们将使用一个简单的线性回归问题,其中输入特征 x 和标…...
【memgpt】letta 课程1/2:从头实现一个自我编辑、记忆和多步骤推理的代理
llms-as-operating-systems-agent-memory llms-as-operating-systems-agent-memory内存 操作系统的内存管理...
6-图像金字塔与轮廓检测
文章目录 6.图像金字塔与轮廓检测(1)图像金字塔定义(2)金字塔制作方法(3)轮廓检测方法(4)轮廓特征与近似(5)模板匹配方法6.图像金字塔与轮廓检测 (1)图像金字塔定义 高斯金字塔拉普拉斯金字塔 高斯金字塔:向下采样方法(缩小) 高斯金字塔:向上采样方法(放大)…...
深入理解Java引用传递
先看一段代码: public static void add(String a) {a "new";System.out.println("add: " a); // 输出内容:add: new}public static void main(String[] args) {String a null;add(a);System.out.println("main: " a);…...
925.长按键入
目录 一、题目二、思路三、解法四、收获 一、题目 你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。 你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字&am…...
【Rust自学】15.2. Deref trait Pt.1:什么是Deref、解引用运算符*与实现Deref trait
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 15.2.1. 什么是Deref trait Deref的全写是Dereference,就是引用的英文reference加上"de"这个反义前缀,…...
图书管理系统 Axios 源码__新增图书
目录 功能介绍 核心代码解析 源码:新增图书功能 总结 本项目基于 HTML、Bootstrap、JavaScript 和 Axios 开发,实现了图书的增删改查功能。以下是新增图书的功能实现,适合前端开发学习和项目实践。 功能介绍 用户可以通过 模态框…...
吴恩达深度学习——超参数调试
内容来自https://www.bilibili.com/video/BV1FT4y1E74V,仅为本人学习所用。 文章目录 超参数调试调试选择范围 Batch归一化公式整合 Softmax 超参数调试 调试 目前学习的一些超参数有学习率 α \alpha α(最重要)、动量梯度下降法 β \bet…...
【赵渝强老师】K8s中Pod探针的ExecAction
在K8s集群中,当Pod处于运行状态时,kubelet通过使用探针(Probe)对容器的健康状态执行检查和诊断。K8s支持三种不同类型的探针,分别是:livenessProbe(存活探针)、readinessProbe&#…...
如何对系统调用进行扩展?
扩展系统调用是操作系统开发中的一个重要任务。系统调用是用户程序与操作系统内核之间的接口,允许用户程序执行内核级操作(如文件操作、进程管理、内存管理等)。扩展系统调用通常包括以下几个步骤: 一、定义新系统调用 扩展系统调用首先需要定义新的系统调用的功能。系统…...
ChatGPT与GPT的区别与联系
ChatGPT 和 GPT 都是基于 Transformer 架构的语言模型,但它们有不同的侧重点和应用。下面我们来探讨一下它们的区别与联系。 1. GPT(Generative Pre-trained Transformer) GPT 是一类由 OpenAI 开发的语言模型,基于 Transformer…...
安卓(android)订餐菜单【Android移动开发基础案例教程(第2版)黑马程序员】
一、实验目的(如果代码有错漏,可查看源码) 1.掌握Activity生命周的每个方法。 2.掌握Activity的创建、配置、启动和关闭。 3.掌握Intent和IntentFilter的使用。 4.掌握Activity之间的跳转方式、任务栈和四种启动模式。 5.掌握在Activity中添加…...
Python安居客二手小区数据爬取(2025年)
目录 2025年安居客二手小区数据爬取观察目标网页观察详情页数据准备工作:安装装备就像打游戏代码详解:每行代码都是你的小兵完整代码大放送爬取结果 2025年安居客二手小区数据爬取 这段时间需要爬取安居客二手小区数据,看了一下相关教程基本…...
happytime
happytime 一、查壳 无壳,64位 二、IDA分析 1.main 2.cry函数 总体:是魔改的XXTEA加密 在main中可以看到被加密且分段的flag在最后的循环中与V6进行比较,刚好和上面v6数组相同。 所以毫无疑问密文是v6. 而与flag一起进入加密函数的v5就…...
深度学习 DAY3:NLP发展史
NLP发展史 NLP发展脉络简要梳理如下: (远古模型,上图没有但也可以算NLP) 1940 - BOW(无序统计模型) 1950 - n-gram(基于词序的模型) (近代模型) 2001 - Neural language models&am…...
前端知识速记:节流与防抖
前端知识速记:节流与防抖 什么是防抖? 防抖是一种控制事件触发频率的方法,通常用于处理用户频繁触发事件的场景。防抖的核心思想是将多个连续触发事件合并为一个事件,以减少执行次数。它在以下场景中特别有效: 输入…...
家居EDI:Hom Furniture EDI需求分析
HOM Furniture 是一家成立于1977年的美国家具零售商,总部位于明尼苏达州。公司致力于提供高品质、时尚的家具和家居用品,满足各种家庭和办公需求。HOM Furniture 以广泛的产品线和优质的客户服务在市场上赢得了良好的口碑。公司经营的产品包括卧室、客厅…...
