【自然语言处理(NLP)】深度学习架构:Transformer 原理及代码实现

news2025/2/2 21:18:50

文章目录

  • 介绍
  • Transformer
    • 核心组件
    • 架构图
      • 编码器(Encoder)
      • 解码器(Decoder)
    • 优点
    • 应用
    • 代码实现
      • 导包
      • 基于位置的前馈网络
      • 残差连接后进行层规范化
      • 编码器 Block
      • 编码器
      • 解码器 Block
      • 解码器
      • 训练
      • 预测

个人主页:道友老李
欢迎加入社区:道友老李的学习社区

介绍

**自然语言处理(Natural Language Processing,NLP)**是计算机科学领域与人工智能领域中的一个重要方向。它研究的是人类(自然)语言与计算机之间的交互。NLP的目标是让计算机能够理解、解析、生成人类语言,并且能够以有意义的方式回应和操作这些信息。

NLP的任务可以分为多个层次,包括但不限于:

  1. 词法分析:将文本分解成单词或标记(token),并识别它们的词性(如名词、动词等)。
  2. 句法分析:分析句子结构,理解句子中词语的关系,比如主语、谓语、宾语等。
  3. 语义分析:试图理解句子的实际含义,超越字面意义,捕捉隐含的信息。
  4. 语用分析:考虑上下文和对话背景,理解话语在特定情境下的使用目的。
  5. 情感分析:检测文本中表达的情感倾向,例如正面、负面或中立。
  6. 机器翻译:将一种自然语言转换为另一种自然语言。
  7. 问答系统:构建可以回答用户问题的系统。
  8. 文本摘要:从大量文本中提取关键信息,生成简短的摘要。
  9. 命名实体识别(NER):识别文本中提到的特定实体,如人名、地名、组织名等。
  10. 语音识别:将人类的语音转换为计算机可读的文字格式。

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(dk QKT)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_hiddens
        self.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_weights
        return 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 = i
        self.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 = X
        else:
            # 预测: 预测需要把前面时刻预测得到的信息和当前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.shape
            dec_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_hiddens
        self.num_layers = num_layers
        self.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_weights
            self._attention_weights[1][i] = blk.attention2.attention.attention_weights
        return self.dense(X), state
    
    @property
    def 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

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

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

相关文章

【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、交通、订票、住宿指南 四、总结 前言 随着信息技术的飞速发展&…

使用Pygame制作“吃豆人”游戏

本篇博客展示如何使用 Python Pygame 编写一个简易版的“吃豆人&#xff08;Pac-Man&#xff09;” 风格游戏。这里我们暂且命名为 Py-Man。玩家需要控制主角在一个网格地图里移动、吃掉散布在各处的豆子&#xff0c;并躲避在地图中巡逻的幽灵。此示例可帮助你理解网格地图、角…

SQL入门到精通 理论+实战 -- 在 MySQL 中学习SQL语言

目录 一、环境准备 1、MySQL 8.0 和 Navicat 下载安装 2、准备好的表和数据文件&#xff1a; 二、SQL语言简述 1、数据库基础概念 2、什么是SQL 3、SQL的分类 4、SQL通用语法 三、DDL&#xff08;Data Definition Language&#xff09;&#xff1a;数据定义语言 1、操…

x86-64数据传输指令

关于汇编语言一些基础概念的更详细的介绍&#xff0c;可移步MIPS指令集&#xff08;一&#xff09;基本操作_mips指令 sw-CSDN博客 该指令集中一个字2字节。 该架构有16个64位寄存器&#xff0c;名字都以%r开头&#xff0c;每个寄存器的最低位字节&#xff0c;低1~2位字节&…

【ESP32】ESP-IDF开发 | WiFi开发 | TCP传输控制协议 + TCP服务器和客户端例程

1. 简介 TCP&#xff08;Transmission Control Protocol&#xff09;&#xff0c;全称传输控制协议。它的特点有以下几点&#xff1a;面向连接&#xff0c;每一个TCP连接只能是点对点的&#xff08;一对一&#xff09;&#xff1b;提供可靠交付服务&#xff1b;提供全双工通信&…

算法基础学习——快排与归并(附带java模版)

快速排序和归并排序是两种速度较快的排序方式&#xff0c;是最应该掌握的两种排序算法&#xff0c; &#xff08;一&#xff09;快速排序&#xff08;不稳定的&#xff09; 基本思想&#xff1a;分治 平均时间复杂度&#xff1a;O(nlogn) / 最慢O(n^2) / 最快O(n) 步骤&…

指针的进化—sizeof和strlen对比(字符串和字符数组的区分)

1.前言 如果你对各个数组的内容存放是什么没有个清晰的概念&#xff0c;对指针偏移之后的数量算不出来或者模棱两可&#xff0c;那么本篇就来详细介绍sizeof和strlen来具象化的显示数组的内容存放了多少内容&#xff0c;偏移量变化后的变化&#xff0c;这个数组进行运算后会不会…

TensorFlow简单的线性回归任务

如何使用 TensorFlow 和 Keras 创建、训练并进行预测 1. 数据准备与预处理 2. 构建模型 3. 编译模型 4. 训练模型 5. 评估模型 6. 模型应用与预测 7. 保存与加载模型 8.完整代码 1. 数据准备与预处理 我们将使用一个简单的线性回归问题&#xff0c;其中输入特征 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引用传递

先看一段代码&#xff1a; public static void add(String a) {a "new";System.out.println("add: " a); // 输出内容&#xff1a;add: new}public static void main(String[] args) {String a null;add(a);System.out.println("main: " a);…

925.长按键入

目录 一、题目二、思路三、解法四、收获 一、题目 你的朋友正在使用键盘输入他的名字 name。偶尔&#xff0c;在键入字符 c 时&#xff0c;按键可能会被长按&#xff0c;而字符可能被输入 1 次或多次。 你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字&am…

【Rust自学】15.2. Deref trait Pt.1:什么是Deref、解引用运算符*与实现Deref trait

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 15.2.1. 什么是Deref trait Deref的全写是Dereference&#xff0c;就是引用的英文reference加上"de"这个反义前缀&#xff0c…

吴恩达深度学习——超参数调试

内容来自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;仅为本人学习所用。 文章目录 超参数调试调试选择范围 Batch归一化公式整合 Softmax 超参数调试 调试 目前学习的一些超参数有学习率 α \alpha α&#xff08;最重要&#xff09;、动量梯度下降法 β \bet…

【赵渝强老师】K8s中Pod探针的ExecAction

在K8s集群中&#xff0c;当Pod处于运行状态时&#xff0c;kubelet通过使用探针&#xff08;Probe&#xff09;对容器的健康状态执行检查和诊断。K8s支持三种不同类型的探针&#xff0c;分别是&#xff1a;livenessProbe&#xff08;存活探针&#xff09;、readinessProbe&#…

如何对系统调用进行扩展?

扩展系统调用是操作系统开发中的一个重要任务。系统调用是用户程序与操作系统内核之间的接口,允许用户程序执行内核级操作(如文件操作、进程管理、内存管理等)。扩展系统调用通常包括以下几个步骤: 一、定义新系统调用 扩展系统调用首先需要定义新的系统调用的功能。系统…

安卓(android)订餐菜单【Android移动开发基础案例教程(第2版)黑马程序员】

一、实验目的&#xff08;如果代码有错漏&#xff0c;可查看源码&#xff09; 1.掌握Activity生命周的每个方法。 2.掌握Activity的创建、配置、启动和关闭。 3.掌握Intent和IntentFilter的使用。 4.掌握Activity之间的跳转方式、任务栈和四种启动模式。 5.掌握在Activity中添加…

Python安居客二手小区数据爬取(2025年)

目录 2025年安居客二手小区数据爬取观察目标网页观察详情页数据准备工作&#xff1a;安装装备就像打游戏代码详解&#xff1a;每行代码都是你的小兵完整代码大放送爬取结果 2025年安居客二手小区数据爬取 这段时间需要爬取安居客二手小区数据&#xff0c;看了一下相关教程基本…

happytime

happytime 一、查壳 无壳&#xff0c;64位 二、IDA分析 1.main 2.cry函数 总体&#xff1a;是魔改的XXTEA加密 在main中可以看到被加密且分段的flag在最后的循环中与V6进行比较&#xff0c;刚好和上面v6数组相同。 所以毫无疑问密文是v6. 而与flag一起进入加密函数的v5就…