入门pytorch-Transformer
前言
虽然Transformer
是2017年由Google推出,如果按照读论文只读近两年的思路看,那它无疑是过时的,但可惜的是,目前很多论文的核心依然是Transformer
,或者由其进行改进的,故本文使用pytorch
来搭建一下Transformer
这个模型
全局分析
首先,我们要从整个模型架构入手,从大的层面看这块内容,然后再开始编写代码。欧克,这里默认大家掌握了一些基础知识,Transformer
是由Google于2017年的Attention Is All You Need论文上所提出来的。如下图,则是论文中所提出的整个框架,可以很清晰的看出具体所使用的组件
总的来看,两个模块,编码器、解码器,特别有自编码器的思想(换句话说,Transformer
借鉴了seq2sqe
,而seq2sqe
天然就是自编码器的思想),下面引用了论文当中的话.
-
Encoder: 编码器由 N = 6 N = 6 N=6 个相同层的堆叠组成。每一层有两个子层。第一个是多头自注意机制,第二个是一个简单的,位置全连接前馈网络。我们在两个子层中的每一个周围使用残差连接,随后进行层归一化。也就是说,每个子层的输出是 L a y e r N o r m ( x + S u b l a y e r ( x ) ) LayerNorm(x + Sublayer(x)) LayerNorm(x+Sublayer(x)),其中 S u b l a y e r ( x ) Sublayer(x) Sublayer(x) 是由子层本身实现的函数。为了促进这些剩余连接,模型中的所有子层以及嵌入层产生维度 d m o d e l = 512 d_{model} = 512 dmodel=512 的输出。
-
Decoder: 解码器也由 N = 6 N = 6 N=6 个相同层的堆栈组成。除了每个编码器层中的两个子层之外,解码器还插入第三子层,该第三子层对编码器堆栈的输出执行多头注意。与编码器类似,我们在每个子层周围使用残差连接,然后进行层归一化。我们还修改了解码器堆栈中的自注意子层,以防止位置注意到后续位置。该掩蔽与输出嵌入偏移一个位置的事实相结合,确保了位置i的预测可以仅依赖于小于 i i i 的位置处的已知输出。
好了,我们了解了整个大的框架,开始接触小的组件,由上图,我们可以进行拆分,其整个框架是由嵌入层、位置编码层、(掩码)多头注意力层、前馈神经网络层、残差连接+归一化层;接下来我们分别实现这些神经网络块(层),并将其堆叠在一起,其实就是Transformer了。
好了,接下来我们就开始编写代码吧
位置编码层
下面的就是位置编码。在这里打个比方,就比如机器翻译问题上,我们需要将一句话翻译成另一句话,即A --> B,那么A和B必然是长度随机的编码,这里输入的就是(想要翻译几句话,几个单词,每个单词的特征编码)
P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 2 i / d m o d e l ) PE_{(pos,2i)} = sin(pos/10000^{2i/d_{model}}) PE(pos,2i)=sin(pos/100002i/dmodel)
P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1000 0 2 i / d m o d e l ) PE_{(pos,2i+1)} = cos(pos/10000^{2i/d_{model}}) PE(pos,2i+1)=cos(pos/100002i/dmodel)
# 位置编码
class PositionalEncoding(nn.Module):'''num_hiddens: 神经元数量(嵌入维度数量)dropout: 神经元的丢弃概率max_len: 序列最大长度'''def __init__(self, num_hiddens, dropout, max_len=1000):super(PositionalEncoding, self).__init__()self.dropout = nn.Dropout(dropout)self.P = torch.zeros((1, max_len, num_hiddens))# 等差数列X = (torch.arange(max_len, dtype=torch.float32).reshape(-1, 1)/ torch.pow(10000, torch.arange(0, num_hiddens, 2, dtype=torch.float32) / num_hiddens))self.P[:, :, 0::2] = torch.sin(X)self.P[:, :, 1::2] = torch.cos(X)def forward(self, X): # X = (批次,序列长度,特征)X = X + self.P[:, :X.shape[1], :].to(X.device)return self.dropout(X)
残差连接+归一化层
欧克,接下来我们先来看一下简单理解的层。残差连接可以理解为防止梯度消失问题,以及加快收敛的一个有效的方法。而归一化就是防止梯度爆炸的问题
# 残差连接 + 归一化层
class AddNorm(nn.Module):'''normalized_shape: 形状大小dropout: 神经元的丢弃概率'''def __init__(self, normalized_shape, dropout):super(AddNorm, self).__init__()self.drop = nn.Dropout(dropout) # 丢弃层self.layer = nn.LayerNorm(normalized_shape) # 对输入的小批量应用层规范化def forward(self, X, Y):return self.layer(self.drop(Y) + X)
前馈神经网络层
这块也比较简单,就是两层的感知机而已。
F F N ( x ) = m a x ( 0 , x W 1 + b 1 ) W 2 + b 2 FFN(x) = max(0, xW_1 + b_1)W_2 + b_2 FFN(x)=max(0,xW1+b1)W2+b2
# 前馈神经网络
class PostionWiseFFN(nn.Module):'''num_input: 输入形状num_hiddens: 隐藏层形状num_ouput: 输出层形状'''def __init__(self, num_input, num_hiddens, num_ouput):super(PostionWiseFFN, self).__init__()self.liner1 = nn.Linear(num_input, num_hiddens) # 线性层1self.relu = nn.ReLU() # 激活函数self.liner2 = nn.Linear(num_hiddens, num_ouput) # 线性层2def forward(self, X):return self.liner2(self.relu(self.liner1(X)))
点积注意力机制
这里给出点积注意力机制的公式
A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d ) V Attention(Q,K,V) = softmax(\frac{QK^T}{\sqrt{d}})V Attention(Q,K,V)=softmax(dQKT)V
其中Q为查询矩阵,K键矩阵,V值矩阵,它们的维度是 ( n , d k ) (n,d_k) (n,dk), ( m , d k ) (m,d_k) (m,dk), ( m , d v ) (m,d_v) (m,dv),m是键值对的数量, d k d_k dk是键矩阵和查询矩阵的特征维度, d v d_v dv是值矩阵的特征维度。而除于 d \sqrt{d} d是为了避免梯度消失问题
class DotProductAttention(nn.Module):'''dropout: 神经元的丢弃概率'''def __init__(self, dropout):super(DotProductAttention, self).__init__()self.dropout = nn.Dropout(dropout)def sequence_mask(self, X, valid_lens, value=0): # 根据valid_lens生成掩码'''X: (批量, 最大序列长度, 特征)valid_lens: 有效长度value: 填充数据'''maxlen = X.size(1)mask = torch.arange((maxlen), dtype=torch.float32,device=X.device)[None, :] < valid_lens[:, None]X[~mask] = valuereturn Xdef masked_softmax(self, X, valid_lens):if valid_lens is None:return nn.functional.softmax(X, dim=-1)else:shape = X.shapeif valid_lens.dim == 1:valid_lens = valid_lens.repeat_interleave(valid_lens, shape[1])else:valid_lens = valid_lens.reshape(-1)X = self.sequence_mask(X, valid_lens)return nn.functional.softmax(X.reshape(shape), dim=-1)def forward(self, Q, K, V, valid_lens=None):d = Q.shape[-1]scores = torch.bmm(Q, K.transpose(1, 2)) / math.sqrt(d) # 点积获取注意力分数self.attention_weights = self.masked_softmax(scores, valid_lens) # 获取注意力权重return torch.bmm(self.dropout(self.attention_weights), V) # 注意力权重 * 值V
到这里,我们由此便可以提出自注意力机制,而自注意力机制对上面做出了一个很简单的改变,就是 Q = K = V Q = K = V Q=K=V,换句话说Q、K、V同源
多头注意力
所谓多头注意力机制,就是有多个自注意力机制并行,然后将输出进行拼接送到线性层进一步整合
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 w h e r e 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 ) MultiHead(Q,K,V) = Concat(head_1,...,head_h)W^O\\ where \ head_i = Attention(QW_i^Q,KW_i^K,VW_i^V) MultiHead(Q,K,V)=Concat(head1,...,headh)WOwhere headi=Attention(QWiQ,KWiK,VWiV)
# 多头注意力
class MultiHeadAttention(nn.Module):'''key_size: K值形状大小query_size: Q值形状大小value_size: V值形状大小num_hiddens: 隐藏层神经元数量num_heads: 头数dropout: 神经元的丢弃概率bias: 是否学习加性偏差,默认不学习'''def __init__(self, key_size, query_size, value_size, num_hiddens,num_heads, dropout, bias=False):super(MultiHeadAttention, self).__init__()assert num_hiddens % num_heads == 0self.num_heads = num_headsself.attention = DotProductAttention(dropout) # 这里使用到了点积注意力机制self.W_q = nn.Linear(query_size, num_hiddens, bias=bias) # Q矩阵权重self.W_k = nn.Linear(key_size, num_hiddens, bias=bias) # K矩阵权重self.W_v = nn.Linear(value_size, num_hiddens, bias=bias) # V矩阵权重self.W_o = nn.Linear(num_heads, num_hiddens, bias=bias) # 输出线性层def forward(self, Q, K, V, valid_lens): # valid_lens 有效长度Q = transpose_qkv(self.W_q(Q), self.num_heads)K = transpose_qkv(self.W_k(K), self.num_heads)V = transpose_qkv(self.W_v(V), self.num_heads)if valid_lens is not None:valid_lens = torch.repeat_interleave(valid_lens, repeats=self.num_heads, dim=0)output = self.attention(Q, K, V, valid_lens)output_concat = transpose_output(output, self.num_heads)return self.W_o(output_concat)
这里我们通过transpose_qkv
和transpose_output
函数来将数据进行改造,以此来进行并行操作
def transpose_qkv(X, num_heads):"""为了多注意力头的并行计算而变换形状"""# 输入X的形状:(batch_size,查询或者“键-值”对的个数,num_hiddens)# 输出X的形状:(batch_size,查询或者“键-值”对的个数,num_heads,num_hiddens/num_heads)X = X.reshape(X.shape[0], X.shape[1], num_heads, -1)X = X.permute(0, 2, 1, 3)return X.reshape(-1, X.shape[2], X.shape[3])
def transpose_output(X, num_heads):"""逆转transpose_qkv函数的操作"""X = X.reshape(-1, num_heads, X.shape[1], X.shape[2])X = X.permute(0, 2, 1, 3)return X.reshape(X.shape[0], X.shape[1], -1)
编码器
如下则是编码器的代码
class EncoderBlock(nn.Module):'''K_size, Q_size, V_size: 键值对和查询的大小num_hiddens: 中间隐藏层神经元num_heads: 头数norm_shape: 残差连接+归一化层的输入形状num_input: FFN的输入形状ffn_num_hiddens: FFN隐藏层神经元dropout: 神经元的丢弃概率'''def __init__(self, K_size, Q_size, V_size, num_hiddens, num_heads,norm_shape, num_input, ffn_num_hiddens, dropout, bias=False):super(EncoderBlock, self).__init__()self.attention = MultiHeadAttention(K_size, Q_size, V_size, num_hiddens, num_heads, dropout, bias) # 多头注意力机制 self.addnorm1 = AddNorm(norm_shape, dropout) # 归一化+残差连接self.ffn = PostionWiseFFN(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))
接下来我们需要将位置编码层、嵌入层、残差连接+归一化层、前馈神经网络、编码器等封装起来
class TransformerEncoder(nn.Module):'''vocab_size: 词典大小K_size, Q_size, V_size: 键值对和查询的大小num_hiddens: 中间隐藏层神经元num_heads: 头数norm_shape: 残差连接+归一化层的输入形状num_input: FFN的输入形状ffn_num_hiddens: FFN隐藏层神经元num_layers: 编码器的层数dropout: 神经元的丢弃概率'''def __init__(self, vocab_size, K_size, Q_size, V_size, num_hiddens, num_heads,norm_shape, num_input, ffn_num_hiddens, num_layers, dropout, bias=False):super(TransformerEncoder, self).__init__()self.num_hiddens = num_hiddens# num_embeddings: 嵌入词典的大小 embedding_dim: 每个嵌入向量的尺寸self.embedding = nn.Embedding(num_embeddings=vocab_size, embedding_dim=num_hiddens) # 嵌入层self.pos_encoding = PositionalEncoding(num_hiddens, dropout) # 位置编码层self.blks = nn.Sequential()for i in range(num_layers):self.blks.add_module("block" + str(i),EncoderBlock(K_size, Q_size, V_size, num_hiddens, num_heads, norm_shape, num_input, ffn_num_hiddens, dropout, bias))def forward(self, X, valid_lens):# 输入 X (句子个数,单词个数)# 输出 ret (句子个数,单词个数,单词特征)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
解码器
class DecodeBlock(nn.Module):'''K_size, Q_size, V_size: 键值对和查询的大小num_hiddens: 中间隐藏层神经元num_heads: 头数norm_shape: 残差连接+归一化层的输入形状num_input: FFN的输入形状ffn_num_hiddens: FFN隐藏层神经元dropout: 神经元的丢弃概率i:'''def __init__(self, K_size, Q_size, V_size, num_hiddens, num_heads,norm_shape, num_input, ffn_num_hiddens, dropout, i):super(DecodeBlock, self).__init__()self.i = iself.attention1 = MultiHeadAttention(K_size, Q_size, V_size, num_hiddens, num_heads, dropout) # 多头注意力机制self.addnorm1 = AddNorm(norm_shape, dropout)self.attention2 = MultiHeadAttention(K_size, Q_size, V_size, num_hiddens, num_heads, dropout) # 多头注意力机制self.addnorm2 = AddNorm(norm_shape, dropout)self.ffn = PostionWiseFFN(num_input, ffn_num_hiddens, num_hiddens)self.addnorm3 = AddNorm(norm_shape, dropout)def forward(self, X, state):# state [编码器输入,编码器有效长度,中间状态用于记录]enc_outputs, enc_valid_lens = state[0], state[1]if state[2][self.i] is None:K = Xelse:K = torch.cat((state[2][self.i], X), axis=1)state[2][self.i] = Kif self.training:batch_size, num_steps, _ = X.shapedec_valid_lens = torch.arange(1, batch_size + 1, device=X.device)else:dec_valid_lens = NoneX2 = self.attention1(X, K, K, 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
封装
class TransformerDecoder(nn.Module):'''vocab_size: 词典大小K_size, Q_size, V_size: 键值对和查询的大小num_hiddens: 中间隐藏层神经元num_heads: 头数norm_shape: 残差连接+归一化层的输入形状num_input: FFN的输入形状ffn_num_hiddens: FFN隐藏层神经元num_layers: 编码器的层数dropout: 神经元的丢弃概率'''def __init__(self, vocab_size, K_size, Q_size, V_size, num_hiddens, num_heads,norm_shape, num_input, ffn_num_hiddens, num_layers, dropout):super(TransformerDecoder, self).__init__()self.num_hiddens = num_hiddensself.num_layers = num_layersself.embedding = nn.Embedding(num_embeddings=vocab_size, embedding_dim=num_hiddens)self.pos_encoding = PositionalEncoding(num_hiddens, dropout)self.blks = nn.Sequential()for i in range(num_layers):self.blks.add_module("block" + str(i),DecodeBlock(K_size, Q_size, V_size, num_hiddens, num_heads, norm_shape, num_input, ffn_num_hiddens, dropout, i))self.linear = nn.Linear(num_hiddens, vocab_size)def init_state(self, enc_outputs, enc_valid_lens):return [enc_outputs, enc_valid_lens, [None] * self.num_layers]def forward(self, X, state):X = self.pos_encoding(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.linear(X), self._attention_weights@propertydef attention_weights(self):return self._attention_weights
Transformer
最后整合一下
class EncoderDecoder(nn.Module):"""编码器-解码器架构的基类"""def __init__(self, encoder, decoder, **kwargs):super(EncoderDecoder, self).__init__(**kwargs)self.encoder = encoderself.decoder = decoderdef forward(self, enc_X, dec_X, *args):enc_outputs = self.encoder(enc_X, *args)dec_state = self.decoder.init_state(enc_outputs, *args)return self.decoder(dec_X, dec_state)
Transformer以三种不同的方式使用多头注意力:(引自论文)
- 在 “encoder-decoder attention” 层中,查询 Q Q Q来自先前的解码器层,并且存储器键 K K K和值 V V V来自编码器的输出。这使得解码器中的每个位置都能处理输入序列中的所有位置。这模拟了序列到序列模型中的典型编码器-解码器注意机制。
- 编码器包含自我注意层。在自关注层中,所有的键、值和查询都来自同一个地方,在这种情况下,是编码器中前一层的输出。编码器中的每个位置都可以处理编码器的前一层中的所有位置。
- 类似地,解码器中的自关注层允许解码器中的每个位置关注解码器中的直到并且包括该位置的所有位置。我们需要防止解码器中的冗余信息流,以保持自回归特性。我们通过屏蔽(设置为 − ∞ -\infty −∞) s o f t m a x softmax softmax 输入中对应于非法连接的所有值来实现这一点。
最后,大家再来回顾一下Transformer
模型整体架构
相关文章:

入门pytorch-Transformer
前言 虽然Transformer是2017年由Google推出,如果按照读论文只读近两年的思路看,那它无疑是过时的,但可惜的是,目前很多论文的核心依然是Transformer,或者由其进行改进的,故本文使用pytorch来搭建一下Trans…...

泛型编程--
auto自动推导数据类型 函数模板 定义和调用 函数模板具体化 函数模板通用版本之外的一个特殊版本 函数模板 具体化函数 ,它们的声明和定义都可以分开写。 声明 定义 函数模板写变量 模板参数缺省 类成员函数作为函数模板 类构造函数是函数模板 函数模板重载 函数模…...

【大语言模型】LangChain 核心模块介绍(Agents)
【大语言模型】LangChain 核心模块介绍(Agents) 一、简介二、Agents 的核心概念三、实战案例3.1、需求说明3.2、实现思路3.3、完整源码 一、简介 我们都知道四肢的绝大部分动作都是由大脑决定的,大脑通过中枢神经下发自己的操作指令…...

19C-RAC 环境mgmtca.trc.1过大
客户监控告警/u01使用率超过80%,通过一层层目录查看,发现是mgmtca.trc.1过大导致的告警 [rootgsdb1 ~]# du -sh /u01/app/grid/cfgtoollogs/mgmtca/mgmtca.trc.1 103G /u01/app/grid/cfgtoollogs/mgmtca/mgmtca.trc.1 查看MOS文档:Huge …...

基于Spring Boot的同城宠物照看系统的设计与实现
一、摘要 在快节奏的现代生活中,宠物已成为许多家庭不可或缺的一部分。然而,宠物照看服务的需求也随之增长。为了满足这一需求,我们设计并实现了一款同城宠物照看系统,该系统利用Java技术和MySQL数据库,为用户提供一个…...

爬虫学习案例5
爬取b站一个视频 罗翔老师某一个视频很刑 单个完整代码: 安装依赖库 pip install lxml requests import osimport requests import re from lxml import etree import json # 格式化展开输出 from pprint import pprint # 导入进程模块 import subprocess head…...

视频监控汇聚平台方案设计:Liveweb视频智能监管系统方案技术特点与应用
随着科技的发展,视频监控平台在各个领域的应用越来越广泛。然而,当前的视频监控平台仍存在一些问题,如视频质量不高、监控范围有限、智能化程度不够等。这些问题不仅影响了监控效果,也制约了视频监控平台的发展。 为了解决这些问…...

ansible自动化运维(三)jinja2模板roles角色管理
相关文章ansible自动化运维(一)简介及清单,模块-CSDN博客ansible自动化运维(二)playbook模式详解-CSDN博客ansible自动化运维(四)运维实战-CSDN博客 三.Ansible jinja2模板 Jinja2是Python的全功能模板引…...

队列+宽搜_429. N 叉树的层序遍历_二叉树最大宽度
429. N 叉树的层序遍历 定义一个队列q,将一层的节点入队,并记录节点个数。根据节点的个数,出队列,并将其孩子入队列。出完队列,队列当前剩余节点的个数就是下次出队列的次数。直到队列为空 /* // Definition for a Nod…...

Windows11安装及使用nvm
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Windows11安装nvm 前言一、简介二、下载三、安装1、双击运行,同意协议,点击Next2、选择nvm安装路径,此路径也是环境变量NVM_HOME的路径&am…...
(一)机器学习 - 入门
数据集 数据集是一组数据的集合,这些数据可以是数值型、文本型、图形型等多种形式。数据集通常用于统计分析、机器学习、科学研究、商业智能等领域,以发现数据中的模式、趋势和关联性。 数据集的组成: 变量(Variables)…...

【解决】k8s使用kubeadm初始化集群失败问题整理
执行提示命令,查看报错信息 journalctl -xeu kubelet1、错误:running with swap on is no 报错 "command failed" err"failed to run Kubelet: running with swap on is no 解决: swap未禁用,需要禁用swap&…...
apache-dubbo
dubbo 文档地址 dubbo 官方文档地址 https://dubbo.apache.org/zh-cn/docs/user/references/api.html nacos 官方文档地址 https://nacos.io/zh-cn/docs/quick-start.html nacos下载地址 https://github.com/alibaba/nacos/releases/download/2.3.0/nacos-server-2.3.0.…...

ECharts柱状图-柱图2,附视频讲解与代码下载
引言: 在数据可视化的世界里,ECharts凭借其丰富的图表类型和强大的配置能力,成为了众多开发者的首选。今天,我将带大家一起实现一个柱状图图表,通过该图表我们可以直观地展示和分析数据。此外,我还将提供…...

【新人系列】Python 入门(十六):正则表达式
✍ 个人博客:https://blog.csdn.net/Newin2020?typeblog 📝 专栏地址:https://blog.csdn.net/newin2020/category_12801353.html 📣 专栏定位:为 0 基础刚入门 Python 的小伙伴提供详细的讲解,也欢迎大佬们…...

HTML综合
一.HTML的初始结构 <!DOCTYPE html> <html lang"en"><head><!-- 设置文本字符 --><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><!-- 设置网页…...
孚盟云 MailAjax.ashx SQL注入漏洞复现
0x01 产品简介 上海孚盟软件有限公司是一家外贸SaaS服务提供商,也是专业的外贸行业解决方案专业提供商。 全新的孚盟云产品,让用户可以用云模式实现信息化管理,让用户的异地办公更加流畅,大大降低中小企业在信息化上成本,用最小的投入享受大型企业级别的信息化服务,主要…...

解决“VMware虚拟机报Intel VT-x”错误
今天,在windows系统上,打开VMware WorkStation v15软件里的虚拟机,弹出"Intel VT-x处于禁用状态"错误,如图(1)所示: 图(1) 虚拟机报"Intel VT-x"错误 问题原因:当前电脑的BIOS没有开启…...
NiceGUI `ui.table` 基础
NiceGUI ui.table 基础 ui.table 是 NiceGUI 提供的一个组件,用于在页面上展示数据表格 基本概念 官方简介 A table based on Quasar’s QTable component. 参数参考rows:list of row objects; 行对象列表columns:list of column objects (defaults to the colu…...

分布式 Raft算法 总结
前言 相关系列 《分布式 & 目录》《分布式 & Raft算法 & 总结》《分布式 & Raft算法 & 问题》 参考文献 《Raft一致性算法论文译文》《深入剖析共识性算法 Raft》 简介 Raft 木筏是一种基于日志复制实现的分布式容错&一致性算法。在Raft算法…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...