基于Transformer的诗句生成

news2025/1/12 9:45:04

基于Transformer的诗句生成

  • 前言
  • 相关介绍
      • Transformer
        • 一、基本原理与结构
        • 二、关键技术
        • 三、应用领域
        • 四、优缺点
      • Transformer应用:诗句生成
        • 优缺点
  • 前提条件
  • 实验环境
  • 基于Transformer的诗句生成
    • 准备数据集
    • 读取数据集
    • 分割数据集
    • 设置相关参数
    • 创建自己DataSet对象
    • 定义网络模型和损失函数
    • 定义优化器
    • 训练模型
    • 查看损失变化
    • 保存模型
    • 测试模型
  • 参考文献

在这里插入图片描述

前言

  • 由于本人水平有限,难免出现错漏,敬请批评改正。
  • 更多精彩内容,可点击进入Python日常小操作专栏、OpenCV-Python小应用专栏、YOLO系列专栏、自然语言处理专栏或我的个人主页查看
  • 基于DETR的人脸伪装检测
  • YOLOv7训练自己的数据集(口罩检测)
  • YOLOv8训练自己的数据集(足球检测)
  • YOLOv10训练自己的数据集(交通标志检测)
  • YOLO11训练自己的数据集(吸烟、跌倒行为检测)
  • YOLOv5:TensorRT加速YOLOv5模型推理
  • YOLOv5:IoU、GIoU、DIoU、CIoU、EIoU
  • 玩转Jetson Nano(五):TensorRT加速YOLOv5目标检测
  • YOLOv5:添加SE、CBAM、CoordAtt、ECA注意力机制
  • YOLOv5:yolov5s.yaml配置文件解读、增加小目标检测层
  • Python将COCO格式实例分割数据集转换为YOLO格式实例分割数据集
  • YOLOv5:使用7.0版本训练自己的实例分割模型(车辆、行人、路标、车道线等实例分割)
  • 使用Kaggle GPU资源免费体验Stable Diffusion开源项目

相关介绍

Transformer是一个用来替代RNN和CNN的新的网络结构,它能够直接获取全局的信息,而不像RNN需要逐步递归才能获得全局信息,也不像CNN只能获取局部信息。Transformer本质上就是一个Attention结构,并且其能够进行并行运算,要比RNN快上很多倍。

  • 论文地址:https://arxiv.org/abs/1706.03762
    在这里插入图片描述

Transformer

Transformer是一种基于自注意力机制的深度学习模型,它在自然语言处理领域取得了巨大的成功。

一、基本原理与结构

Transformer的核心是自注意力机制,它允许模型在处理每个输入元素时,能够关注到序列中的所有其他元素,从而捕捉到长距离依赖关系。这种机制使得Transformer在处理自然语言任务时,能够更准确地理解文本的含义和上下文。

Transformer的结构包括两个主要部分:编码器和解码器。编码器由多个相同的层组成,每个层又包括一个多头自注意力子层和一个全连接层。解码器也由多个相同的层组成,但还包括一个额外的多头自注意力子层,用于捕捉编码器输出的信息。解码器的最后一层是一个全连接层,用于将解码器的输出转换成一个特定任务所需的形式。

二、关键技术
  1. 位置编码:为了使模型能够理解输入序列中的位置信息,Transformer在输入序列中添加了位置编码。这种编码可以使得模型更好地理解输入序列中的词语顺序和语义信息。
  2. 自注意力机制:这是Transformer的核心技术之一,它可以自动地捕捉输入序列中的长距离依赖关系。在自注意力机制中,每个词语都可以通过与其他词语的交互来获得一个新的表示形式。
  3. 残差连接和层归一化:为了缓解深度神经网络中的梯度消失问题,Transformer在模型的每个层之后添加了残差连接,并进行了层归一化。
三、应用领域

Transformer在自然语言处理领域取得了广泛的应用,包括但不限于:

  1. 语言建模:根据上下文预测下一个词语。
  2. 机器翻译:将一种语言翻译成另一种语言。
  3. 文本分类:将给定的文本分为不同的类别。
  4. 问答系统:自动地回答问题。

此外,Transformer还被应用于图像处理、时间序列分析等其他领域的序列建模任务。

四、优缺点

优点

  1. 长距离依赖关系建模:通过自注意力机制,Transformer能够有效捕捉长距离依赖关系,适用于处理长序列和涉及远距离语义关系的任务。
  2. 并行计算能力:多头注意力机制的并行计算特性极大提高了训练和推理效率,支持更大规模的模型和更长序列的处理。
  3. 通用性:Transformer的架构不仅适用于自然语言处理领域,还适用于图像处理、时间序列分析等其他领域的序列建模任务。

缺点

  1. 高计算成本:复杂的模型结构导致训练和推理过程中需要大量计算资源,尤其是在处理大规模数据集时。
  2. 优化难度:模型的复杂性和超参数数量增加了解决方案的难度,需要仔细调整学习率、批量大小等参数以获得最佳性能。
  3. 对长文本处理挑战:在处理长文本时,可能因位置编码和注意力机制的限制而受到内存限制和效率影响。
  4. 对特定任务需要大量数据:对于某些复杂语义关系和细粒度分类任务,Transformer可能需要大量标注数据才能发挥最佳性能。

综上所述,Transformer作为一种重要的深度学习模型,在自然语言处理领域取得了显著的成功。然而,它也存在一些挑战和限制,需要在实际应用中根据具体任务和数据特点进行选择和优化。

Transformer应用:诗句生成

基于Transformer的诗句生成是自然语言处理领域中的一个创新应用,它利用Transformer模型的强大能力,实现了自动化、高质量的诗歌创作。

  1. 模型背景

    • Transformer模型是近年来自然语言处理领域的重大突破,它通过自注意力机制,能够高效捕捉序列中不同位置之间的依赖关系,实现上下文感知。
    • 在诗歌生成任务中,Transformer模型能够利用大规模古诗词数据集进行训练,学习诗歌的韵律结构、文学风格等特征,从而生成符合传统格式和要求的诗句。
  2. 模型架构

    • 基于Transformer的诗句生成模型通常包括嵌入层、多头自注意力层、前馈神经网络层等关键组件。
    • 嵌入层将输入的词语转化为向量表示,捕捉词与词之间的语义关联。
    • 多头自注意力层用于捕捉词语间的依赖关系,特别是长距离依赖,这是Transformer模型的核心机制。
    • 前馈神经网络层则对注意力层的输出进行进一步处理,生成最终的诗句。
  3. 训练过程

    • 数据集准备:收集大规模的古诗词数据集,进行预处理,如分词、编码、归一化等步骤。
    • 模型训练:利用预处理后的数据集对Transformer模型进行训练,通过优化损失函数来提高模型的生成能力。
    • 微调与优化:根据具体任务需求,对模型进行微调,以进一步提高生成诗句的质量和文学性。
  4. 应用场景

    • 基于Transformer的诗句生成模型可以应用于多种场景,如自动化诗歌创作、诗歌风格转换、诗歌推荐等。
    • 通过输入关键词或主题,模型可以生成相关的诗句作品,为用户提供便捷的创作体验。
优缺点
  1. 优点

    • 高效性:Transformer模型采用并行计算方式,提高了处理速度,适用于大规模数据集的训练和应用。
    • 上下文感知:通过自注意力机制,Transformer模型能够捕捉序列中不同位置之间的依赖关系,实现上下文感知,从而生成更符合逻辑和语境的诗句。
    • 泛化能力强:通过大规模的无监督预训练和微调过程,Transformer模型可以学习到丰富的语言知识和模式,提高了模型的泛化能力。
  2. 缺点

    • 数据要求高:Transformer模型需要大量的数据和计算资源来进行预训练和微调。在诗歌生成任务中,需要收集大规模的古诗词数据集,并进行精细的预处理工作。
    • 解释性差:由于Transformer模型的内部结构比较复杂,难以解释和理解其生成诗句的具体过程和依据。这在一定程度上限制了模型在某些领域的应用。
    • 长距离依赖关系捕捉能力有限:虽然Transformer模型能够捕捉长距离依赖关系,但随着序列长度的增加,模型的性能可能会受到一定影响。在诗歌生成任务中,这可能导致生成的诗句在逻辑和语境上存在一定的不连贯性。

综上所述,基于Transformer的诗句生成模型具有高效性、上下文感知和泛化能力强等优点,但也存在数据要求高、解释性差和长距离依赖关系捕捉能力有限等缺点。在应用该模型时,需要根据具体任务需求和数据特点进行选择和优化。

前提条件

  • 熟悉Python

实验环境

Package                       Version
----------------------------- ------------
matplotlib                    3.3.4
numpy                         1.19.5
Pillow                        8.4.0
pip                           21.2.2
protobuf                      3.19.6
requests                      2.27.1
scikit-learn                  0.24.2
scipy                         1.5.4
sentencepiece                 0.1.91
setuptools                    58.0.4
threadpoolctl                 3.1.0
thulac                        0.2.2
tokenizers                    0.9.3
torch                         1.9.1+cu111
torchaudio                    0.9.1
torchvision                   0.10.1+cu111
tornado                       6.1
tqdm                          4.64.1
traitlets                     4.3.3
transformers                  3.5.1
urllib3                       1.26.20

基于Transformer的诗句生成

准备数据集

在这里插入图片描述

  • data_splited++.jl:该文件是预处理的诗句文本数据集文件。
  • id2w++.json:该文件是ID到词的映射文件。
  • w2id++.json:该文件是词到ID的映射文件。

读取数据集

import json
from tqdm import tqdm
import torch
import time
with open('w2id++.json', 'r') as f:
    w2id = json.load(f)
with open('id2w++.json', 'r') as f:
    id2w = json.load(f)
    
data_list = []
with open('data_splited++.jl', 'r') as f:
    for l in f:
        data_list.append(json.loads(l))

分割数据集

# 根据词数分割数据
dlx = [[] for _ in range(5)]
for d in data_list:
    dlx[len(d[0]) - 5].append(d)

设置相关参数

batch_size = 128
# data_workers = 4 # windows下不设置为0,会报页面错误
data_workers = 0
learning_rate = 0.0001
gradient_accumulation_steps = 1
max_train_epochs = 1
warmup_proportion = 0.05
weight_decay=0.01
max_grad_norm=1.0
cur_time = time.strftime("%Y-%m-%d_%H:%M:%S")
device = torch.device('cuda')

这些参数通常用于配置深度学习模型的训练过程,特别是在使用PyTorch这样的深度学习框架时。下面是对每个参数的解释:

  1. batch_size = 128:

    • 批大小(Batch Size)是指在模型训练过程中,一次迭代(iteration)所使用的数据样本数量。这里设置为128,意味着每次更新模型参数前,会使用128个样本来计算损失和梯度。较大的批大小可以加速训练,但也可能增加内存消耗并影响模型的泛化能力。
  2. data_workers = 0:

    • 数据加载工作线程数(Data Workers)是指用于并行加载数据的线程数量。设置为0意味着数据加载将在主线程上同步进行,这可能会降低数据加载的速度。通常,增加工作线程数可以加速数据加载过程,但过多的线程可能会增加系统开销。
  3. learning_rate = 0.0001:

    • 学习率(Learning Rate)是控制模型参数更新幅度的超参数。较小的学习率意味着参数更新的步长较小,训练过程可能更稳定但收敛速度较慢;较大的学习率可能导致训练过程不稳定甚至发散。这里设置为0.0001是一个相对较小的值,适用于一些精细调整的场景。
  4. gradient_accumulation_steps = 1:

    • 梯度累积步数(Gradient Accumulation Steps)是指在更新模型参数前,累积梯量的次数。设置为1意味着每次迭代都会立即更新模型参数。在内存有限但希望使用较大批大小进行训练时,可以通过增加梯度累积步数来模拟较大的批大小。
  5. max_train_epochs = 30:

    • 最大训练轮数(Max Training Epochs)是指整个训练数据集被遍历的次数。一个epoch等于整个数据集通过模型一次。这里设置为30,意味着整个数据集将被遍历30次。
  6. warmup_proportion = 0.05:

    • 预热比例(Warmup Proportion)是指在训练初期,学习率逐渐增加所占整个训练过程的比例。预热可以帮助模型在训练初期更稳定地更新参数,避免由于初始学习率过高而导致的训练不稳定。这里设置为0.05,意味着在前5%的训练轮数中,学习率会逐渐增加。
  7. weight_decay = 0.01:

    • 权重衰减(Weight Decay)是一种正则化技术,用于防止模型过拟合。它通过向损失函数添加一个与模型参数平方成正比的项来实现,鼓励模型参数保持较小值。这里设置为0.01。
  8. max_grad_norm = 1.0:

    • 最大梯度范数(Max Grad Norm)是梯度裁剪(Gradient Clipping)的一种形式,用于控制梯度的最大值。如果梯度的范数超过这个值,梯度将被缩放以确保其范数不超过这个值。这有助于防止梯度爆炸问题。这里设置为1.0。
  9. cur_time = time.strftime(“%Y-%m-%d_%H:%M:%S”):

    • 这行代码用于获取当前时间,并将其格式化为字符串,通常用于生成具有时间戳的文件名或日志,以便记录训练过程。
  10. device = torch.device(‘cuda’):

    • 这行代码指定了模型和数据应该在哪种设备上运行。'cuda'表示使用NVIDIA的CUDA技术来加速计算,通常是在具有NVIDIA GPU的计算机上。如果系统中没有可用的CUDA设备,PyTorch将回退到CPU。

这些参数共同决定了模型训练的具体配置,包括训练速度、模型性能以及训练过程中的稳定性等。

创建自己DataSet对象

class MyDataSet(torch.utils.data.Dataset):
    def __init__(self, examples):
        self.examples = examples
    def __len__(self):
        return len(self.examples)
    def __getitem__(self, index):
        example = self.examples[index]
        s1 = example[0]
        s2 = example[1]
        return s1, s2, index
def str2id(s):
    ids = []
    for ch in s:
        if ch in w2id:
            ids.append(w2id[ch])
        else:
            ids.append(0)
    return ids
def the_collate_fn(batch):
    s1x = []
    s2x = []
    for b in batch:
        s1 = str2id(b[0])
        s2 = str2id(b[1])
        s1x.append(s1)
        s2x.append(s2)
    indexs = [b[2] for b in batch]
    s1 = torch.LongTensor(s1x)
    s2 = torch.LongTensor(s2x)
    return s1, s2, indexs

dldx = []
for d in dlx:
    ds = MyDataSet(d)
    dld = torch.utils.data.DataLoader(
        ds,
        batch_size=batch_size,
        shuffle = True,
        num_workers=data_workers,
        collate_fn=the_collate_fn,
    )
    dldx.append(dld)

定义网络模型和损失函数

import math
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn import TransformerEncoder, TransformerEncoderLayer

class PositionalEncoding(nn.Module):

    def __init__(self, d_model, dropout=0.1, max_len=5000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(p=dropout)

        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(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).transpose(0, 1)
        self.register_buffer('pe', pe)

    def forward(self, x):
        x = x + self.pe[:x.size(0), :]
        return self.dropout(x)


class TransformerModel(nn.Module):

    def __init__(self, ntoken, ninp, nhead, nhid, nlayers, dropout=0.5):
        super(TransformerModel, self).__init__()
        self.pos_encoder = PositionalEncoding(ninp, dropout)
        encoder_layers = TransformerEncoderLayer(ninp, nhead, nhid, dropout)
        self.transformer_encoder = TransformerEncoder(encoder_layers, nlayers)
        self.encoder = nn.Embedding(ntoken, ninp)
        self.ninp = ninp
        self.decoder = nn.Linear(ninp, ntoken)
        self.init_weights()

    def init_weights(self):
        initrange = 0.1
        self.encoder.weight.data.uniform_(-initrange, initrange)
        self.decoder.bias.data.zero_()
        self.decoder.weight.data.uniform_(-initrange, initrange)

    def forward(self, s1, s2=None):
        batch_size, length = s1.shape[:2]
        s1 = self.encoder(s1) * math.sqrt(self.ninp)
        s1 = self.pos_encoder(s1)
        output = self.transformer_encoder(s1)
        output = self.decoder(output)
        output = F.log_softmax(output, dim=2)
        if s2 is not None:
            criterion = nn.NLLLoss()
            loss = criterion(output.view(batch_size*length, -1), s2.view(batch_size*length))
            return loss
        return output
ntokens = len(w2id)
emsize = 300 # embedding dimension
nhid = 256 # the dimension of the feedforward network model in nn.TransformerEncoder
nlayers = 4 # the number of nn.TransformerEncoderLayer in nn.TransformerEncoder
nhead = 4 # the number of heads in the multiheadattention models
dropout = 0.2 # the dropout value
model = TransformerModel(ntokens, emsize, nhead, nhid, nlayers, dropout).to(device)

这段代码是在初始化一个基于Transformer模型的实例,用于自然语言处理(NLP)或其他序列到序列的任务。下面是对各个参数的解释:

  1. ntokens (len(w2id)): 这个参数表示词汇表的大小,即模型能够处理的唯一单词或标记的数量。w2id很可能是一个字典,将每个单词映射到一个唯一的ID。因此,len(w2id)就是这个字典中键值对的数量,也就是词汇表的大小。

  2. emsize (300): 这是嵌入层的维度大小,也称为嵌入向量的大小。每个单词或标记都会被转换成一个固定大小的向量(这里是300维),这个向量能够捕捉到单词的语义信息。

  3. nhid (256): 这个参数指的是Transformer模型中前馈神经网络(Feedforward Neural Network)的隐藏层大小。在Transformer的每个编码器层和解码器层中,都有一个前馈神经网络,它的输入和输出大小由这个参数决定(虽然中间层可能会有更大的大小,但这里的256通常指的是输入和输出的维度)。

  4. nlayers (4): 这个参数指定了Transformer模型中编码器或解码器层的数量。在这个例子中,模型有4个Transformer层,每个层都包含多头自注意力机制和前馈神经网络。

  5. nhead (4): 这个参数指定了多头注意力机制中“头”的数量。在多头注意力中,模型会并行地学习输入序列的不同表示(每个头学习一种),然后将这些表示合并起来。在这个例子中,有4个头,意味着输入会被分割成4个部分,每个部分独立地通过一个注意力机制进行处理。

  6. dropout (0.2): 这个参数指定了在训练过程中应用dropout的比例。Dropout是一种正则化技术,通过在训练过程中随机丢弃网络的一部分连接,来防止模型过拟合。这里的0.2意味着有20%的连接会被随机丢弃。

  7. model: 这是通过提供的参数初始化的Transformer模型实例。.to(device)是一个PyTorch的方法,用于将模型移动到指定的设备上(如CPU或GPU),以便进行训练或推理。

总的来说,这些参数共同定义了Transformer模型的结构和大小,以及训练过程中使用的正则化技术。通过调整这些参数,可以影响模型的性能、训练速度和所需的计算资源。

定义优化器

from transformers import AdamW, get_linear_schedule_with_warmup

t_total = len(data_list) // gradient_accumulation_steps * max_train_epochs + 1
num_warmup_steps = int(warmup_proportion * t_total)

print('warmup steps : %d' % num_warmup_steps)

no_decay = ['bias', 'LayerNorm.weight'] # no_decay = ['bias', 'LayerNorm.bias', 'LayerNorm.weight']
param_optimizer = list(model.named_parameters())
optimizer_grouped_parameters = [
    {'params':[p for n, p in param_optimizer if not any(nd in n for nd in no_decay)],'weight_decay': weight_decay},
    {'params':[p for n, p in param_optimizer if any(nd in n for nd in no_decay)],'weight_decay': 0.0}
]
optimizer = AdamW(optimizer_grouped_parameters, lr=learning_rate)
scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=num_warmup_steps, num_training_steps=t_total)

训练模型

def t2s(t):
    l = t.cpu().tolist()
    r = [id2w[x] for x in l[0]]
    return ''.join(r)

def get_next(s):
    ids = torch.LongTensor(str2id(s))
    print(s)
    ids = ids.unsqueeze(0).to(device)
    with torch.no_grad():
        r = model(ids)
        r = r.argmax(dim=2)
        return t2s(r)
def print_cases():
    print(get_next('好好学习') + '\n')
    print(get_next('白日依山尽') + '\n')
    print(get_next('学而时习之') + '\n')
    print(get_next('人之初性本善') + '\n')

loss_list = []
for e in range(max_train_epochs):
    print(e)
    loss_sum = 0
    c = 0
    xxx = [x.__iter__() for x in dldx]
    j = 0
    for i in tqdm(range((len(data_list)//batch_size) + 5)):
        if len(xxx) == 0:
            break
        j = j % len(xxx)
        try:
            batch = xxx[j].__next__()
        except StopIteration:
            xxx.pop(j)
            continue
        j += 1
        s1, s2, index = batch
        s1 = s1.to(device)
        s2 = s2.to(device)
        loss = model(s1, s2)
        loss_sum += loss.item()
        c += 1
        loss.backward()
        optimizer.step()
        scheduler.step() 
        optimizer.zero_grad()
    print_cases()
    print(loss_sum / c)
    loss_list.append(loss_sum / c)
warmup steps : 3350217
0
100%|██████████████████████████████████████████████████████████████████████████████| 8729/8729 [03:14<00:00, 44.90it/s]
好好学习
疃如颐钞

白日依山尽
郯疚毳察葩

学而时习之
匙彻察谩堪

人之初性本善
轸麻胶邵洁廛

8.991864916192085

......

58
100%|██████████████████████████████████████████████████████████████████████████████| 8729/8729 [03:18<00:00, 43.99it/s]
好好学习
时时为迟

白日依山尽
不年无日多

学而时习之
此无日不之

人之初性本善
我之无心不不

6.59523827047266

查看损失变化

from matplotlib import pyplot as plt
plt.figure(figsize=(9,6))
plt.plot([i for i in range(len(loss_list))], loss_list)

在这里插入图片描述

保存模型

torch.save(model.state_dict(), 'transform_model_parameter.pkl')
torch.save(model, 'transform_model.pkl')

测试模型

model = torch.load('transform_model.pkl')
model.load_state_dict(torch.load('transform_model_parameter.pkl'))

print_cases()
好好学习
时时为迟

白日依山尽
不年无日多

学而时习之
此无日不之

人之初性本善
我之无心不不

参考文献

[1] Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Lukasz Kaiser, Illia Polosukhin. Attention Is All You Need. 2023.
[2] https://blog.csdn.net/m0_47779101/article/details/128087403
[3] https://zhuanlan.zhihu.com/p/338817680
[4] https://zhuanlan.zhihu.com/p/407012757
[5] https://blog.csdn.net/FriendshipTang/article/details/132032019
[6] 论文地址:https://arxiv.org/abs/1706.03762

  • 由于本人水平有限,难免出现错漏,敬请批评改正。
  • 更多精彩内容,可点击进入Python日常小操作专栏、OpenCV-Python小应用专栏、YOLO系列专栏、自然语言处理专栏或我的个人主页查看
  • 基于DETR的人脸伪装检测
  • YOLOv7训练自己的数据集(口罩检测)
  • YOLOv8训练自己的数据集(足球检测)
  • YOLOv10训练自己的数据集(交通标志检测)
  • YOLO11训练自己的数据集(吸烟、跌倒行为检测)
  • YOLOv5:TensorRT加速YOLOv5模型推理
  • YOLOv5:IoU、GIoU、DIoU、CIoU、EIoU
  • 玩转Jetson Nano(五):TensorRT加速YOLOv5目标检测
  • YOLOv5:添加SE、CBAM、CoordAtt、ECA注意力机制
  • YOLOv5:yolov5s.yaml配置文件解读、增加小目标检测层
  • Python将COCO格式实例分割数据集转换为YOLO格式实例分割数据集
  • YOLOv5:使用7.0版本训练自己的实例分割模型(车辆、行人、路标、车道线等实例分割)
  • 使用Kaggle GPU资源免费体验Stable Diffusion开源项目

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

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

相关文章

双十一速购清单!如何才能挑到性价比高的宠物空气净化器

对于很多上班族而言&#xff0c;平时都不敢大手大脚的花钱&#xff0c;甚至很想将一份钱掰成两份来用&#xff0c;所以双十一是很多人都不会错过的购物狂欢节。 当然&#xff0c;我这个996的社畜也一样&#xff0c;而且我还养了一只爱掉毛的猫咪&#xff0c;每天下班回去都看到…

光路科技TSN交换机和电力专用交换机即将亮相第31届中国国际电力设备及技术展览会

在全球能源领域正经历深刻转型之际&#xff0c;可再生能源技术的飞跃进步正为电力行业的未来开辟新径。太阳能、风能等绿色能源&#xff0c;凭借其无可比拟的优势&#xff0c;正稳步取代化石燃料&#xff0c;成为电力行业的主流趋势。多国政府积极响应&#xff0c;出台多项政策…

日均千万订单的交易平台设计稿

业务背景 平台主要售卖电子商品和少量特定的实物商品。 经营模式&#xff0c;主要分为平台商家和自营店&#xff0c;自营店的流量占整个平台业务的50%以上&#xff0c;我负责自营店交易履约相关业务。 以前的架构&#xff0c;平台交易和履约中心是所有流量共享&#xff0c;在…

day01-Qt5入门

day01-Qt5入门 1.下载Qtcreate 官网地址&#xff1a;http://qt-project.org/downloads 2.配置环境变量 将类似于 D:\Qt\Qt5.1.1\5.1.1\mingw48_32\bin 的目录添加到环境变量中 3.创建一个新项目 输入自己的项目名称&#xff0c;后面默认下一部 4.运行第一个项目 在窗口…

计算机网络:数据链路层 —— PPP 点对点协议

文章目录 PPP 帧PPP帧的格式PPP帧的透明传输面向字节的异步链路面向比特的同步链路 PPP帧的差错检测 PPP 的工作状态 点对点协议&#xff08;Point-to-Point Protocol&#xff0c;PPP&#xff09;是目前使用最广泛的点对点数据链路层协议&#xff0c;用于在两个节点之间进行数据…

10.12面试题

代理模式 为什么需要代理模式&#xff1f; 1.中介隔离 客户类不想或者不能直接引用委托对象&#xff0c;需要使用代理类作为中介&#xff0c;需要代理类和委托对象都实现同一接口 2.满足开闭原则 若客户类需要委托对象新增某些功能&#xff0c;就需要代理类在调用委托对象…

【ProtoBuf】基础使用与编译

文章目录 ProtoBuf的使用基本使用指定proto3语法package声明符定义消息(message)定义消息字段字段唯一编号 编译序列化与反序列化序列化与反序列化使用 ProtoBuf的使用 流程如下&#xff1a; 编写 .proto文件&#xff0c;定义结构对象(message)及属性内容使用 protoc 编译器编…

常用类(二)--String类的简单总结

文章目录 1.基本介绍1.1创建对象1.2找到对应下标的字符1.3找到对应字符的下标1.4指定位置开始遍历1.5反向进行遍历1.6大小写之间的转换1.7字符串转换为数组1.8元素的替换1.9字符串的分割1.10字符串的截取 2.StringBuilder和StringBuffer2.1 StringBuilder的引入2.2面试题目 1.基…

拆解学习【无线充,EMMC,锂电池电量计,OTA】(二)

主要学习到了&#xff1a;无线充&#xff0c;EMMC&#xff0c;手表CPU方案&#xff0c;锂电池电量计&#xff0c;OTA。 无线充电功能是产品的核心卖点之一&#xff0c;充电头网通过拆解发现&#xff0c;手表内部使用恒玄BES2500BP智能手表单芯片解决方案&#xff0c;内置四核C…

BetterZip怎么导入文件进行压缩?苹果解压软件怎么用?

BetterZip作为苹果系统常用的压缩文件软件之一&#xff0c;具有使用方便、压缩导出格式多、兼容性强等特点。我们要使用BetterZip进行文件压缩时&#xff0c;首先需要将文件导入到BetterZip才可以。 关于BetterZip的文件导入方式&#xff0c;主要有几种&#xff0c;今天我来给…

垂直AI大模型行业全景分析及发展趋势研究报告

2024-10-12调研咨询机构环洋市场咨询出版的【全球垂直AI大模型行业总体规模、主要厂商及IPO上市调研报告&#xff0c;2024-2030】只要调研全球垂直AI大模型总体规模&#xff0c;主要地区规模&#xff0c;主要企业规模和份额&#xff0c;主要产品分类规模&#xff0c;下游主要应…

每日一题|3158. 求出出现两次数字的 XOR 值|哈希

题目给的范围很小&#xff0c;50以内&#xff0c;所以什么数据结构都可以。 这里采用set来维护访问过的数字&#xff0c;利用哈希来提升时间效率。 class Solution:def duplicateNumbersXOR(self, nums: List[int]) -> int:visited set()l []res 0for i in nums:if i i…

游戏如何应对薅羊毛问题

在大众眼里&#xff0c;“薅羊毛”是指在电商领域&#xff0c;“羊毛党”利用平台、商家的促销规则&#xff0c;低价获取商品和服务的行为。如前不久“小天鹅被一夜薅走7000万”的案例震惊全网。 然而实际上&#xff0c;“薅羊毛”现象不仅存在于电商场景&#xff0c;在游戏中…

【Unity】TextMeshPro 3.0.9无法显示emoji表情问题

需要下载TextMeshPro 3.2.x-pre.xxx版本&#xff0c;重新生成Sprite Asset文件解决 注意&#xff1a;若Package Manager没有搜到pre版本&#xff0c;那么可以去github下载到本地&#xff0c;再解压后&#xff0c;将文件夹移动到工程Packages文件夹下&#xff0c;然后打开Packa…

基于SpringBoot的体育商城购物系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

React复习

文章目录 常用的HooksuseStateuseReduceruseRefuseContextuseMemouseCallbackuseEffect 组件通信Props&#xff08;属性&#xff09;Ref&#xff08;引用&#xff09;Context&#xff08;上下文&#xff09;State&#xff08;状态&#xff09;回调函数Event Bus&#xff08;事件…

Python WebSocket 的原理及其应用

Python WebSocket 的原理及其应用 在现代 Web 开发中&#xff0c;实时通信成为了越来越多应用的重要组成部分。尤其是像聊天应用、实时数据更新、在线游戏等场景&#xff0c;服务器与客户端之间的即时数据传输需求非常迫切。在传统的 HTTP 协议中&#xff0c;通信往往是基于请…

在docker的容器内如何查看Ubuntu系统版本

文章目录 写在前面一、问题描述二、解决方法参考链接 写在前面 自己的测试环境&#xff1a; docker 一、问题描述 由于 lsb_release -a 只能查看自己电脑&#xff08;宿主机&#xff09;的系统版本&#xff0c;如果在docker的容器内又应该如何查看Ubuntu系统版本呢&#xff…

GoPro 解决方案:恢复 GoPro 数据、GoPro 重置为出厂设置

在本文中&#xff0c;我们将向您展示如何轻松将 GoPro 相机重置为出厂设置以及如何从已重置为出厂设置的 GoPro 中恢复丢失的数据。 第 1 部分&#xff1a;将 GoPro 重置为出厂设置后恢复丢失的数据。 ​在将 GoPro 重置为出厂设置之前&#xff0c;最好对视频进行完整备份。但…

URDF统一机器人建模语言

统一机器人建模语言 URDF&#xff08;Unified Robot Description Format&#xff09;统一机器人描述格式&#xff0c;URDF使用XML格式描述机器人文件。 我们从下面四个方面介绍URDF&#xff1a; URDF的组成介绍 URDF-Link介绍 URDF-Joint介绍 创建一个简单的URDF…