【python、nlp、transformer】transformer学习部分

注:

此博文仅为了解transformer架构,如果使用,建议直接调用库就行了

Transformer的优势

相比之前占领市场的LSTM和GRU模型,Transformer有两个显著的优势:

1. Transformer能够利用分布式GPU进行并行训练,提升模型训练效率。

2. 在分析预测更长的文本时,捕捉间隔较长的语义关联效果更好.

认识Transformer架构

Transformer模型的作用:

基于seq2seq架构的transformer模型可以完成NLP领域研究的典型任务,如机器翻译,文本生成等.同时又可以构建预训练语言模型,用于不同任务的迁移学习.

声明:

在接下来的架构分析中,我们将假设使用Transformer模型架构处理从一种语言文本到另一种语言文本的翻译工作,因此很多命名方式遵循NLP中的规则.比如:Embeddding层将称作文本嵌入层,Embedding层产生的张量称为词嵌入张量,它的最后一维将称作词向量等

Transformer总体架构可分为四个部分:

输入部分

源文本嵌入层及其位置编码器

文本嵌入层的作用:无论是源文本嵌入还是目标文本嵌入,都是为了将文本中词汇的数字表示转变为向量表示,希望在这样的高维空间捕捉词汇间的关系.

位置编码器的作用:因为在Transformer的编码器结构中,并没有针对词汇位置信息的处理,因此需要在Embedding层后加入位置编码器,将词汇位置不同可能会产生不同语义的信息加入到词嵌入张量中,以弥补位置信息的缺失.

# 构建Embedding类实现文本嵌入层代码
import torch
import torch.nn as nn
import math
from torch.autograd import Variableclass Embeddings(nn.Module):def __init__(self, d_model, vocab):"""类的初始化Args:d_model (_type_): 词嵌入的维度vocab (_type_): 词表的大小"""super(Embeddings, self).__init__()self.lut = nn.Embedding(vocab, d_model)self.d_model = d_modeldef forward(self, x):"""前向传播函数Args:x (_type_): 输入的索引张量,形状为 (L, N)Returns:_type_: 词嵌入张量,形状为 (L, N, d_model)"""return self.lut(x) * math.sqrt(self.d_model)

文本嵌入层使用

d_model=512
vocab=1000
x=Variable(torch.LongTensor([[1,2,3,4,5],[6,7,8,9,10]]))
embedding_layer=Embeddings(d_model,vocab)
output=embedding_layer(x)
print(output)

位置编码器

# 位置编码器
class PositionalEncoding(nn.Module):def __init__(self, d_model, dropout, max_len=5000):"""位置编码器Args:d_model (_type_): 词嵌入的维度dropout (_type_): 置零的比例,让一定的神经元失效max_len (int, optional): 每个句子的最大长度. Defaults to 5000."""super(PositionalEncoding, self).__init__()self.dropout = nn.Dropout(p=dropout)# 初始化位置编码矩阵pe = torch.zeros(max_len, d_model)position = torch.arange(0, max_len).unsqueeze(1)div_term=torch.exp(torch.arange(0, d_model, 2) * (-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)self.register_buffer('pe', pe)def forward(self, x):"""_summary_Args:x (_type_): 文本序列的的词嵌入表示"""x=x+Variable(self.pe[:, :x.size(1)], requires_grad=False)return self.dropout(x)

使用 

# 绘制词汇向量中特征的分布曲线
import matplotlib.pyplot as plt
import numpy as npplt.figure(figsize=(15, 5))
pe=PositionalEncoding(20,0)
y=pe(Variable(torch.zeros(1, 100,20)))
plt.plot(np.arange(100), y[0, :, 4:8].data.numpy())
plt.legend(['dim %d'%p for p in [4, 5,  6, 7]])
# 输出效果分析:
# 每条颜色的曲线代表某一个词汇中的特征在不同位置的含义.
# 保证同一词汇随着所在位置不同它对应位置嵌入向量会发生变化.
# 正弦波和余弦波的值域范围都是1到﹣1这又很好的控制了嵌入数值的大小,有助于梯度的快速计算.
目标文本嵌入层及其位置编码器

输出部分

线性层的作用:通过对上一步的线性变化得到指定维度的输出,也就是转换维度的作用.

softInax层的作用:使最后一维的向量中的数字缩放到0-1的概率值域内,并满足他们的和为1.

import torch.nn.functional as F
class Generator(nn.Module):def __init__(self, d_model, vocab):super(Generator, self).__init__()self.proj = nn.Linear(d_model, vocab)def forward(self, x):return F.log_softmax(self.proj(x), dim=-1)

编码器部分

由N个编码器层堆叠而成

每个编码器层由两个子层连接结构组成

第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接

第二个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接

class Encoder(nn.Module):def __init__(self, layer, N):"""_summary_Args:layer (_type_): 编码器层N (_type_): 编码器层个数"""super(Encoder, self).__init__()self.layers=clones(layer, N)self.norm=LayerNorm(layer.size)def forward(self, x, mask):for layer in self.layers:x=layer(x, mask)return self.norm(x)

解码器部分

由N个解码器层堆叠而成

每个解码器层由三个子层连接结构组成

第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接

第二个子层连接结构包括一个多头注意力子层和规范化层以及一个残差连接

第三个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接

class Decoder(nn.Module):def __init__(self, layer, N):super(Decoder, self).__init__()self.layers=clones(layer, N)self.norm=LayerNorm(layer.size)def forward(self, x, memory, src_mask, tgt_mask):for layer in self.layers:x=layer(x, memory, src_mask, tgt_mask)return self.norm(x)

组装构建各部件

class EncoderDecoder(nn.Module):def __init__(self, encoder, decoder, src_embed, tgt_embed, generator):"""编码器-解码器结构Args:encoder (_type_): 编码器对象decoder (_type_): 解码器对象src_embed (_type_): 源数据嵌入函数tgt_embed (_type_): 目标数据嵌入函数generator (_type_): 类别生成器对象"""super(EncoderDecoder, self).__init__()self.encoder = encoderself.decoder = decoderself.src_embed = src_embedself.tgt_embed = tgt_embedself.generator = generatordef forward(self, src, tgt, src_mask, tgt_mask):"""_summary_Args:src (_type_): 源数据tgt (_type_): 目标数据src_mask (_type_): 源数据掩码张量tgt_mask (_type_): 目标数据掩码张量"""return self.decode(self.encode(src, src_mask), src_mask,tgt, tgt_mask)def encode(self, src, src_mask):"""编码函数Args:src (_type_): _description_src_mask (_type_): _description_"""return self.encoder(self.src_embed(src), src_mask)def decode(self, memory, src_mask, tgt, tgt_mask):"""解码函数Args:memory (_type_): _description_src_mask (_type_): _description_tgt (_type_): _description_tgt_mask (_type_): _description_"""return self.decoder(self.tgt_embed(tgt), memory, src_mask, tgt_mask)
def make_model(src_vocab, tgt_vocab, N=6, d_model=512, d_ff=2048, head=8, dropout=0.1):"""_summary_Args:src_vocab (_type_): 源数据词汇总数tgt_vocab (_type_): 目标数据词汇总数N (int, optional): 子层堆叠数量. Defaults to 6.d_model (int, optional): 词向量维度. Defaults to 512.d_ff (int, optional): 前馈全连接网络的变换矩阵维度. Defaults to 2048.head (int, optional): 多头注意力的多头数. Defaults to 8.dropout (float, optional): 置零比率. Defaults to 0.1."""c=copy.deepcopyattn=MultiHeadedAttention(head,d_model)ff=PositionwiseFeedForward(d_model,d_ff,dropout)position=PositionalEncoding(d_model,dropout)model=EncoderDecoder(Encoder(EncoderLayer(d_model,c(attn),c(ff),dropout),N),Decoder(DecoderLayer(d_model,c(attn),c(attn),c(ff),dropout),N),nn.Sequential(Embeddings(d_model,src_vocab),c(position)),nn.Sequential(Embeddings(d_model,tgt_vocab),c(position)),Generator(d_model,tgt_vocab))for p in model.parameters():if p.dim()>1:nn.init.xavier_uniform_(p)return model

copy任务

任务描述:针对数字序列进行学习,学习的最终目标是使输出与输入的序列相同

任务意义: copy任务在模型基础测试中具有重要意义,因为copy操作对于模型来讲是一条明显规律,因此模型能否在短时间内,小数据集中学会它,可以帮助我们断定模型所有过程是否正常,是否已具备基本学习能力

from pyitcast.transformer_utils import Batchdef data_generator(V,batch,nbatches):"""数据集生成器Args:V (_type_): 随机生成数字的最大值+1batch (_type_): 放入多少数据集后一次更新nbatches (_type_): 一共要输入多少次batch"""for i in range(nbatches):data=torch.from_numpy(np.random.randint(1,V,size=(batch,10)))data[:,0]=1source=Variable(data,requires_grad=False)target=Variable(data,requires_grad=False)yield Batch(source,target,10)

专用名词

掩码张量

什么是掩码张量?

掩代表遮掩,码就是我们张量中的数值,它的尺寸不定,里面一般只有1和0的元素,代表位置被遮掩或者不被遮掩,至于是0位置被遮掩还是1位置被遮掩可以自定义,因此它的作用就是让另外一个张量中的一些数值被遮掩,也可以说被替换,它的表现形式是一个张量。

掩码张量的作用:

在transformer中,掩码张量的主要作用在应用attention(将在下一小节讲解)时,有一些生成的attention张量中的值计算有可能已知了未来信息而得到的,未来信息被看到是因为训练时会把整个输出结果都一次性进行Embedding,但是理论上解码器的的输出却不是一次就能产生最终结果的,而是一次次通过上一次结果综合得出的,因此,未来的信息可能被提前利用.所以,我们会进行遮掩。

def subsquest_mask(size):"""生成掩码张量代码Args:size (_type_): 掩码张量最后两个维度的大小,它的最后两维形成一个方阵"""attn_shape=(1, size, size)subsquest_mask=np.triu(np.ones(attn_shape), k=1).astype('uint8')return torch.from_numpy(1-subsquest_mask)

注意力机制

什么是注意力?

我们观察事物时,之所以能够快速判断一种事物(当然允许判断是错误的), 是因为我们大脑能够很快把注意力放在事物最具有辨识度的部分从而作出判断,而并非是从头到尾的观察一遍事物后,才能有判断结果.正是基于这样的理论,就产生了注意力机制.

注意力计算规则:

它需要三个指定的输入Q(query), K(key), V(value), 然后通过公式得到注意力的计算结果,这个结果代表query在key和value作用下的表示.而这个具体的计算规则有很多种,我这里只介绍我们用到的这一种.

什么是注意力机制:

注意力机制是注意力计算规则能够应用的深度学习网络的载体,除了注意力计算规则外,还包括一些必要的全连接层以及相关张量处理,使其与应用网络融为一体.使用自注意力计算规则的注意力机制称为自注意力机制.

注意力机制的计算规则 

import torch.nn.functional as Fdef attention(query, key, value, mask=None, dropout=None):"""注意力机制的实现代码Args:query (_type_): 查询向量,是一段准备被概括的文本key (_type_): 键向量,是给出的提示value (_type_): 值向量,是大脑中的对提示K的延伸mask (_type_, optional): 掩码张量. Defaults to None.dropout (_type_, optional): 丢弃率. Defaults to None.Returns:_type_: 注意力机制的输出"""d_k=query.size(-1)scores=torch.matmul(query, key.transpose(-2, -1))/math.sqrt(d_k)if mask is not None:scores=scores.masked_fill(mask==0, -1e9)p_attn=F.softmax(scores, dim=-1)if dropout is not None:p_attn=dropout(p_attn)return torch.matmul(p_attn, value), p_attn

多头注意力机制

只有使用了一组线性变化层,即三个变换张量对Q,K,V分别进行线性变换,这些变换不会改变原有张量的尺寸,因此每个变换矩阵都是方阵。

得到输出结果后,多头的作用才开始显现,每个头开始从词义层面分割输出的张量,也就是每个头都想获得一组Q,K,V 进行注意力机制的计算,但是句子中的每个词的表示只获得一部分,也就是只分割了最后一维的词嵌入向量,这就是所谓的多头。

将每个头的获得的输入送到注意力机制中,就形成多头注意力机制.

多头注意力机制的作用:这种结构设计能让每个注意力机制去优化每个词汇的不同特征部分,从而均衡同一种注意力机制可能产生的偏差,让词义拥有来自更多元的表达,实验表明可以从而提升模型效果。

import copydef clones(module, N):"""用于生成相同的网络层Args:module (_type_): 要克隆的目标网络层N (_type_): 需要克隆的数量"""return nn.ModuleList([copy.deepcopy(module) for _ in range(N)])class MultiHeadedAttention(nn.Module):def __init__(self, head, embedding_dim, dropout=0.1):"""多头注意力机制的实现代码Args:head (_type_): 头数embedding_dim (_type_): 词嵌入维度dropout (_type_, optional): 丢弃率. Defaults to 0.1."""super(MultiHeadedAttention, self).__init__()# 保证d_model是头数的整数倍assert embedding_dim%head==0self.d_k=embedding_dim // headself.head=headself.embedding_dim=embedding_dimself.linears=clones(nn.Linear(embedding_dim, embedding_dim), 4)self.attn=Noneself.dropout=nn.Dropout(p=dropout)def forward(self, query, key, value, mask=None):"""前向逻辑结构Args:query (_type_): _description_key (_type_): _description_value (_type_): _description_mask (_type_, optional): _description_. Defaults to None."""if mask is not None:mask=maskbatch_size=query.size(0)query, key, value = [model(x).view(batch_size, -1, self.head, self.d_k).transpose(1, 2) for model, x in zip(self.linears, (query, key, value))]x, self.attn = attention(query, key, value, mask, self.dropout)x = x.transpose(1, 2).contiguous().view(batch_size, -1, self.head * self.d_k)return self.linears[-1](x)

前馈全连接层

在Transformer中前馈全连接层就是具有两层线性层的全连接网络.

前馈全连接层的作用:

考虑注意力机制可能对复杂过程的拟合程度不够,通过增加两层网络来增强模型的能力.

class PositionwiseFeedForward(nn.Module):def __init__(self, d_model, d_ff, dropout=0.1):"""_summary_Args:d_model (_type_): _description_d_ff (_type_): 词嵌入的维度dropout (float, optional): _description_. Defaults to 0.1."""super(PositionwiseFeedForward, self).__init__()self.w1=nn.Linear(d_model, d_ff)self.w2=nn.Linear(d_ff, d_model)self.dropout=nn.Dropout(dropout)def forward(self, x):return self.w2(self.dropout(torch.relu(self.w1(x))))

规范化层

规范化层的作用:

它是所有深层网络模型都需要的标准网络层,因为随着网络层数的增加,通过多层的计算后参数可能开始出现过大或过小的情况,这样可能会导致学习过程出现异常,模型可能收敛非常的慢.因此都会在一定层数后接规范化层进行数值的规范化,使其特征数值在合理范围内.

class LayerNorm(nn.Module):def __init__(self, features, eps=1e-6):"""_summary_Args:features (_type_): 词嵌入维度eps (_type_, optional): 防止分母为0. Defaults to 1e-6."""super(LayerNorm, self).__init__()self.a2=nn.Parameter(torch.ones(features))self.b2=nn.Parameter(torch.zeros(features))self.eps=epsdef forward(self, x):"""_summary_Args:x (_type_): 上一层的输出"""mean=x.mean(-1, keepdim=True)std=x.std(-1, keepdim=True)return self.a2*(x-mean)/(std+self.eps)+self.b2

子层连接结构

输入到每个子层以及规范化层的过程中,还使用了残差链接(跳跃连接),因此我们把这一部结构整体叫做子层连接(代表子层及其链接结构),在每个编码器层中,都有两个子层,这两个子层加上周围的链接结构就形成了两个子层连接结构.

class SublayerConnection(nn.Module):def __init__(self, size, dropout):"""_summary_Args:size (_type_): 词嵌入维度dropout (_type_): 随机抑制比率"""super(SublayerConnection, self).__init__()self.norm=LayerNorm(size)self.dropout=nn.Dropout(dropout)def forward(self, x, sublayer):return x+self.dropout(sublayer(self.norm(x)))

编码器层

编码器层的作用:作为编码器的组成单元,每个编码器层完成一次对输入的特征提取过程,即编码过程

class EncoderLayer(nn.Module):def __init__(self, size, self_attn, feed_forward, dropout):"""_summary_Args:size (_type_): 词维度大小self_attn (_type_): 多头注意力层feed_forward (_type_): 实例化的前馈全连接层dropout (_type_): _description_"""super(EncoderLayer, self).__init__()self.self_attn=self_attnself.feed_forward=feed_forwardself.sublayer=clones(SublayerConnection(size, dropout),2)self.size=sizedef forward(self, x, mask):x=self.sublayer[0](x, lambda x:self.self_attn(x, x, x, mask))return self.sublayer[1](x, self.feed_forward)

解码器层

class DecoderLayer(nn.Module):def __init__(self, size, self_attn, src_attn, feed_forward, dropout):"""_summary_Args:size (_type_): 词维度大小self_attn (_type_): 注意力机制,自注意力src_attn (_type_): 非自注意力机制feed_forward (_type_): 前馈全连接层dropout (_type_): _description_"""super(DecoderLayer, self).__init__()self.size=sizeself.self_attn=self_attnself.src_attn=src_attnself.feed_forward=feed_forwardself.sublayer=clones(SublayerConnection(size, dropout), 3)def forward(self, x, memory, src_mask, tgt_mask):"""_summary_Args:x (_type_): 上一层输入memory (_type_): 来自编码器层语义储存变量src_mask (_type_): 源数据掩码张量tgt_mask (_type_): 目标数据掩码张量"""m=memoryx=self.sublayer[0](x, lambda x: self.self_attn(x, x, x, tgt_mask))x=self.sublayer[1](x, lambda x: self.src_attn(x, m, m, src_mask))return self.sublayer[2](x, self.feed_forward)

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

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

相关文章

小朋友来自多少小区 - 华为OD统一考试(C卷)

OD统一考试(C卷) 分值: 100分 题解: Java / Python / C 题目描述 幼儿园组织活动,老师布置了一个任务: 每个小朋友去了解与自己同一个小区的小朋友还有几个。 我们将这些数量汇总到数组 garden 中。 请…

数据库-第四/五章 数据库安全性和完整性【期末复习|考研复习】

前言 总结整理不易,希望大家点赞收藏。 给大家整理了一下计数据库系统概论中的重点概念,以供大家期末复习和考研复习的时候使用。 参考资料是王珊老师和萨师煊老师的数据库系统概论(第五版)。 文章目录 前言4 第四章 数据库安全性4.1 数据库安全性定义4.…

学生宿舍管理小程序|基于微信小程序的学生宿舍管理系统设计与实现(源码+数据库+文档)

学生宿舍管理小程序目录 目录 基于微信小程序的学生宿舍管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员模块的实现 (1)学生信息管理 (2)公告信息管理 (3)宿舍信息管理 &am…

git clone http/https 报错 10054/443 问题

文章目录 错误解决方案1 关闭http和https代理2 设置自己的代理 错误 错误 Failed to connect to github.com port 443: Timed out OpenSSL SSL_read: Connection was reset, errno 10054 一般都是网络问题 解决方案 1 关闭http和https代理 git config --global --unset htt…

《系统架构设计师教程(第2版)》第5章-软件工程基础知识-05-净室软件工程(CSE)

文章目录 1. 概述2. 理论基础2.1 函数理论2.2 抽样理论 3. 技术手段3.1 增量式开发3.2 基于函数的规范与设计3.3 正确性验证3.4 统计测试 (Statistically Based Testing) 和软件认证 4. 应用与缺点1)太理论化2)缺少传统模块测试3)带有传统软件…

UE学习笔记--解决滚轮无法放大蓝图、Panel等

我们发现有时候创建蓝图之后,右上角的缩放是1:1 但是有时候我们可能需要放的更大一点。 发现一直用鼠标滚轮像上滚动,都没有效果。 好像最大只能 1:1. 那是因为 UE 做了限制。如果希望继续放大,我们可以按住 Ctrl 再去…

StarRocks实战——携程酒店实时数仓

目录 一、实时数仓 二、实时数仓架构介绍 2.1 Lambda架构 2.2 Kappa架构 三、携程酒店实时数仓架构 3.1 架构选型 3.2 实时计算引擎选型 3.3 OLAP选型 四、携程酒店实时订单 4.1 数据源 4.2 ETL数据处理 4.3 应用效果 4.4 总结 原文大佬的这篇实时数仓建设案例有借…

【计算机网络_应用层】TCP应用与相关API守护进程

需要云服务器等云产品来学习Linux的同学可以移步/–>腾讯云<–/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;优惠多多。&#xff08;联系我有折扣哦&#xff09; 文章目录 1. 相关使用接口2. 代码实现2.1 日志组件2.2 Server端2.3 Client端2.3 bug解决 3. 守…

什么是依赖注入(Dependency Injection)?它在 C++ 中是如何实现的?

什么是依赖注入&#xff08;Dependency Injection&#xff09;&#xff1f;它在 C 中是如何实现的&#xff1f; 依赖注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;是一种设计模式&#xff0c;用于减少软件组件之间的耦合度&#xff0c;提高代码的可测试性、…

JVM类加载机制以及双亲委派模型的介绍

目录 1.类加载介绍 2.具体步骤 2.1加载 2.2验证 2.3准备 2.4解析 2.5初始化 3.加载过程中的策略-双亲委派模型 1.类加载介绍 类加载,指的是Java进程在运行的时候,把.class文件从硬盘读取到内存,并进行一系列校验解析的过程. .class文件>类对象.硬盘>内村 类加载…

spring-boot自定义网站头像(favicon.ico文件)

一、将ico文件存放到resources目录的static中的favicon下。 二、在application.properties文件中增加配置 spring.mvc.favicon.enabledfalse 三、如需页面引用如下&#xff1a; <link rel"icon" type"image/x-icon" ref"${request.contextPat…

智能驾驶规划控制理论学习03-基于采样的规划方法

目录 一、基于采样的规划方法概述 二、概率路图&#xff08;PRM&#xff09; 1、核心思想 2、实现流程 3、算法描述 4、节点连接处理 5、总结 三、快速搜索随机树&#xff08;RRT&#xff09; 1、核心思想 2、实现流程 3、总结 4、改进RRT算法 ①快速搜索随机图&a…

【计算机网络实践】在windows上配置Xshell和Xftp连接Ubuntu系统

hebut的课下作业&#xff0c;学习使用Xshell和Xftp连接Linux系统 1. 软件需求 Windows10/11、已安装VM虚拟机的ubuntu系统、Xshell、Xftp。 Xshell和Xftp在家庭/学校免费 - NetSarang Website (xshell.com)里面可以下载到&#xff0c;上面需要的两个软件都在&#xff0c;官网免…

运筹学_1.1.2 线性规划问题-图解法

1.1.2 线性规划问题-图解法 一、图解法求解步骤&#xff08;只适用于两个决策变量问题&#xff09;二、图解法作图实例三、图解法分析线性规划几种解的情况1、唯一最优解2、无穷多最优解3、无界解4、无解或无可行解 四、图解法的几点启示 一、图解法求解步骤&#xff08;只适用…

C++sort排序

前言&#xff1a; C语言的sort函数是一类用于数组排序的函数以下是其简单的使用&#xff1a; 1.头文件&#xff1a; #include<algorithm> 2.使用命名空间&#xff1a; using namespace std; 3.函数形式&#xff1a; sort(数组名,数组名元素个数,排序函数); 默认排…

深入浅出Redis(一):对象与数据结构

引言 Redis是一款基于键值对的数据结构存储系统&#xff0c;它的特点是基于内存操作、单线程处理命令、IO多路复用模型处理网络请求、键值对存储与简单丰富的数据结构等等 这篇文章主要围绕Redis中的对象与数据结构来详细说明键值对存储与简单丰富的数据结构这两大特点 Redi…

运筹学_1.1.4 线性规划问题-解的概念

1.1.4 线性规划问题-解的概念 一、可行解与最优解二、基的概念三、基变量、基向量&#xff1b;非基变量、非基向量&#xff1b;基解、基可行解&#xff1b;四、最优解与可行解、基可行解的关系五、用例题&#xff08;枚举法&#xff09;巩固基解、基可行解、最优解三个概念1、例…

flyway实战

flyway是一款用来管理数据库版本的工具框架 一, 添加依赖 <dependency><groupId>org.flywaydb</groupId><artifactId>flyway-core</artifactId> </dependency> <dependency><groupId>org.springframework</groupId>&l…

第十一届蓝桥杯省赛第一场C++ A组 / B组《网络分析》(c++)

1.题目说明 小明正在做一个网络实验。 他设置了 n 台电脑&#xff0c;称为节点&#xff0c;用于收发和存储数据。 初始时&#xff0c;所有节点都是独立的&#xff0c;不存在任何连接。 小明可以通过网线将两个节点连接起来&#xff0c;连接后两个节点就可以互相通信了。 两…

代码随想录算法训练营第二十五天 | 216.组合总和III 17.电话号码的字母组合

216.组合总和III https://programmercarl.com/0216.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CIII.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC class Solution:def combinationSum3(self, k: int, n: int) -> List[List[int]]:result [] # 存放结果集sel…