用变压器实现德-英语言翻译【02/8】: 位置编码

一、说明

        本文是“用变压器实现德-英语言翻译”系列的第二篇。它从头开始引入位置编码。然后,它解释了 PyTorch 如何实现位置编码。接下来是变压器实现。

二、技术背景

        位置编码用于为序列中的每个标记或单词提供相对位置。阅读句子时,每个单词都依赖于它周围的单词。例如,某些单词在不同的上下文中具有不同的含义,因此模型应该能够理解这些变体以及每个单词所依赖的上下文。一个例子是“树干”。在一个例子中,它可以用来指大象用它的鼻子喝水。在另一种情况下,它可能是指树干被照明击中。

        由于该模型使用长度d_model的嵌入向量来表示每个单词,因此任何位置编码都必须兼容。使用整数似乎很自然,第一个令牌接收 0,第二个令牌接收 1,依此类推。但是,这个数字会迅速增长,并且不容易添加到嵌入矩阵中。相反,为每个位置创建一个位置编码向量,这意味着可以创建一个位置编码矩阵来表示单词可以采取的所有可能位置。

        为了确保每个位置都有唯一的表示,“注意力是你所需要的一切”的作者使用正弦和余弦函数为序列中的每个位置生成一个唯一的向量。虽然这看起来很奇怪,但它有用有几个原因。首先,正弦和余弦的输出在 [-1, 1] 中,归一化。它不会像整数那样增长到无法管理的大小。其次,无需进行额外的培训,因为每个职位都会生成独特的表示形式。

 

        用于生成独特编码的方程看起来令人生畏,但它们只是正弦和余弦的修改版本。嵌入中的最大位置数或向量将由 L 表示:

         这实质上是说,对于每个位置编码向量,对于每两个元素,将偶数元素设置为等于 PE(k,2i),并将奇数元素设置为等于 PE(k, 2i+1)。然后,重复直到向量中有d_model个元素。

        每个编码向量具有与嵌入向量相同的维度(d_model)。这允许对它们求和。表示位置,从 0 开始到 L-1可以设置为的最大数字是 d_model除以 2,因为方程对嵌入中的每个元素交替。n可以设置为任何值,但原始论文建议10,000。在下图中,以下参数用于计算 6 标记序列的位置编码向量:

  • n = 10,000
  • L = 6
  • d_model = 4

         此图显示了最大值 如何设置为 1,正弦和余弦都使用它。k 随嵌入矩阵中的每一行而变化,从 0 开始到 5,这是最大长度 6。每个向量有 d_model = 4 个元素。

三、基本实现

 

        要了解这些独特的位置编码向量如何与嵌入向量一起工作,最好使用嵌入层文章中的示例。

        此实现将直接基于上一篇文章中的实现构建。下面的输出嵌入了三个序列,d_model为 4。

# set the output to 2 decimal places without scientific notation
torch.set_printoptions(precision=2, sci_mode=False)# tokenize the sequences
tokenized_sequences = [tokenize(seq) for seq in sequences]# index the sequences 
indexed_sequences = [[stoi[word] for word in seq] for seq in tokenized_sequences]# convert the sequences to a tensor
tensor_sequences = torch.tensor(indexed_sequences).long()# vocab size
vocab_size = len(stoi)# embedding dimensions
d_model = 4# create the embeddings
lut = nn.Embedding(vocab_size, d_model) # look-up table (lut)# embed the sequence
embeddings = lut(tensor_sequences)embeddings
tensor([[[-0.27, -0.82,  0.33,  1.39],[ 1.72, -0.63, -1.13,  0.10],[-0.23, -0.07, -0.28,  1.17],[ 0.61,  1.46,  1.21,  0.84],[-2.05,  1.77,  1.51, -0.21],[ 0.86, -1.81,  0.55,  0.98]],[[ 0.06, -0.34,  2.08, -1.24],[ 1.44, -0.64,  0.78, -1.10],[ 1.78,  1.22,  1.12, -2.35],[-0.48, -0.40,  1.73,  0.54],[ 1.28, -0.18,  0.52,  2.10],[ 0.34,  0.62, -0.45, -0.64]],[[-0.22, -0.66, -1.00, -0.04],[-0.23, -0.07, -0.28,  1.17],[ 1.44, -0.64,  0.78, -1.10],[ 1.78,  1.22,  1.12, -2.35],[-0.48, -0.40,  1.73,  0.54],[ 0.70, -1.35,  0.15, -1.44]]], grad_fn=<EmbeddingBackward0>)

        下一步是通过位置编码对每个序列中每个单词的位置进行编码。下面的函数遵循上面的定义。唯一值得一提的变化是 L 被标记为max_length。它通常设置为千中的极大值,以确保几乎每个序列都可以正确编码。这确保了相同的位置编码矩阵可以用于不同长度的序列。在添加之前可以将其切成适当的长度。

def gen_pe(max_length, d_model, n):# generate an empty matrix for the positional encodings (pe)pe = np.zeros(max_length*d_model).reshape(max_length, d_model) # for each positionfor k in np.arange(max_length):# for each dimensionfor i in np.arange(d_model//2):# calculate the internal value for sin and costheta = k / (n ** ((2*i)/d_model))       # even dims: sin   pe[k, 2*i] = math.sin(theta) # odd dims: cos               pe[k, 2*i+1] = math.cos(theta)return pe# maximum sequence length
max_length = 10
n = 100
encodings = gen_pe(max_length, d_model, n)

        编码的输出包含 10 个位置编码向量。

array([[ 0.    ,  1.    ,  0.    ,  1.    ],[ 0.8415,  0.5403,  0.0998,  0.995 ],[ 0.9093, -0.4161,  0.1987,  0.9801],[ 0.1411, -0.99  ,  0.2955,  0.9553],[-0.7568, -0.6536,  0.3894,  0.9211],[-0.9589,  0.2837,  0.4794,  0.8776],[-0.2794,  0.9602,  0.5646,  0.8253],[ 0.657 ,  0.7539,  0.6442,  0.7648],[ 0.9894, -0.1455,  0.7174,  0.6967],[ 0.4121, -0.9111,  0.7833,  0.6216]])

        如前所述,max_length设置为 10。虽然这超出了要求,但它确保如果另一个序列的长度为 7、8、9 或 10,则可以使用相同的位置编码矩阵。它只需要被切成适当的长度。下面,嵌入的seq_length为 <>,因此可以相应地对编码进行切片。

# select the first six tokens
seq_length = embeddings.shape[1]
encodings[:seq_length]
tensor([[ 0.00,  1.00,  0.00,  1.00],[ 0.84,  0.54,  0.10,  1.00],[ 0.91, -0.42,  0.20,  0.98],[ 0.14, -0.99,  0.30,  0.96],[-0.76, -0.65,  0.39,  0.92],[-0.96,  0.28,  0.48,  0.88]])

        由于所有三个序列的序列长度相同,因此只需要一个位置编码矩阵,并且可以使用 PyTorch 在所有三个序列上广播。此示例中的嵌入批处理的形状为 (3, 6, 4),位置编码在切片为 (10, 4) 之前形状为 (6, 4)。然后广播该矩阵以创建图像中看到的(3,6,4)编码矩阵。有关广播的更多信息,请阅读广播简单简介。

        这允许添加两个矩阵而不会出现任何问题。

embedded_sequence + encodings[:seq_length] # encodings[:6]

将位置编码添加到嵌入时,输出与部分开头的图像相同。

tensor([[[-0.27,  0.18,  0.33,  2.39],[ 2.57, -0.09, -1.03,  1.09],[ 0.68, -0.49, -0.08,  2.15],[ 0.75,  0.47,  1.50,  1.80],[-2.80,  1.12,  1.90,  0.71],[-0.10, -1.53,  1.03,  1.86]],[[ 0.06,  0.66,  2.08, -0.24],[ 2.28, -0.10,  0.88, -0.10],[ 2.69,  0.80,  1.32, -1.37],[-0.34, -1.39,  2.03,  1.50],[ 0.52, -0.83,  0.91,  3.02],[-0.62,  0.90,  0.03,  0.23]],[[-0.22,  0.34, -1.00,  0.96],[ 0.61,  0.47, -0.18,  2.16],[ 2.35, -1.06,  0.98, -0.12],[ 1.92,  0.23,  1.41, -1.40],[-1.24, -1.06,  2.12,  1.46],[-0.26, -1.06,  0.63, -0.56]]], grad_fn=<AddBackward0>)

        此输出将传递到模型的下一层,即下一篇文章将介绍的多头注意力。

        但是,由于此基本实现使用嵌套循环,因此效率不高,尤其是在使用较大的 d_model 和 max_length 值时。相反,可以使用更以 PyTorch 为中心的方法。

四、修改 PyTorch 的位置编码公式

 

        图片来源:Chili Math

        为了利用 PyTorch 的功能,需要使用对数规则修改原始方程,特别是除数。

        除数为:

        为了修改除数,通过取其指数将 带入分子中。然后,使用规则 7 将整个方程提高为 e 的指数。然后,使用规则 3 将指数拉出日志。然后简化以获得结果。

        这很重要,因为它可用于一次生成位置编码的所有除数。下面很明显,4 维嵌入只需要两个除数,因为除数每 2i 才会变化一次,其中 是维度。这在每个位置重复:

        由于只有 可以设置为的最大数字d_model除以 2,因此可以计算一次项:

d_model = 4
n = 100div_term = torch.exp(torch.arange(0, d_model, 2) * -(math.log(n) / d_model))

        这个简短的代码片段可用于生成所需的所有除数。对于此示例,d_model设置为 4,设置为 100。输出是两个除数:

tensor([1.0000, 0.1000])

        从这里,可以利用 PyTorch 的索引功能,用几行代码创建整个位置编码矩阵。下一步是生成从 到 L-1 的每个位置。

max_length = 10# generate the positions into a column matrix
k = torch.arange(0, max_length).unsqueeze(1)      
tensor([[0],[1],[2],[3],[4],[5],[6],[7],[8],[9]])

        使用位置和除数,可以轻松计算正弦和余弦函数的内部。

        通过将 和 div_term相乘,可以计算每个位置的输入。PyTorch 将自动广播矩阵以允许乘法。请注意,这是 Hadamard 乘积而不是矩阵乘法,因为相应的元素将相互乘法:

 

k*div_term

        此计算的输出可以在上图中看到。剩下要做的就是将输入插入 cos 和 sin 函数,并将它们适当地保存在矩阵中。

        这可以通过创建适当大小的空矩阵来开始:

# generate an empty tensor
pe = torch.zeros(max_length, d_model)
tensor([[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.]])

        现在,偶数列是罪恶的,可以用 pe[:, 0::2] 选择。这告诉 PyTorch 选择每一行和每一列偶数列。对于奇数列也可以这样做,它们是 cos: pe[:, 1::2]。再一次,这告诉 PyTorch 选择每一行和每一奇数列。由于 k*div_term 的结果中存储了所有必要的输入,因此可用于计算每个奇数和偶数列。

# set the odd values (columns 1 and 3)
pe[:, 0::2] = torch.sin(k * div_term)# set the even values (columns 2 and 4)
pe[:, 1::2] = torch.cos(k * div_term)# add a dimension for broadcasting across sequences: optional       
pe = pe.unsqueeze(0)  
tensor([[[ 0.00,  1.00,  0.00,  1.00],[ 0.84,  0.54,  0.10,  1.00],[ 0.91, -0.42,  0.20,  0.98],[ 0.14, -0.99,  0.30,  0.96],[-0.76, -0.65,  0.39,  0.92],[-0.96,  0.28,  0.48,  0.88],[-0.28,  0.96,  0.56,  0.83],[ 0.66,  0.75,  0.64,  0.76],[ 0.99, -0.15,  0.72,  0.70],[ 0.41, -0.91,  0.78,  0.62]]])

        这些值与使用嵌套的 for 循环获取的值相同。回顾一下,以下是所有代码:

max_length = 10
d_model = 4
n = 100def gen_pe(max_length, d_model, n):# calculate the div_termdiv_term = torch.exp(torch.arange(0, d_model, 2) * -(math.log(n) / d_model))# generate the positions into a column matrixk = torch.arange(0, max_length).unsqueeze(1)# generate an empty tensorpe = torch.zeros(max_length, d_model)# set the even valuespe[:, 0::2] = torch.sin(k * div_term)# set the odd valuespe[:, 1::2] = torch.cos(k * div_term)# add a dimension       pe = pe.unsqueeze(0)        # the output has a shape of (1, max_length, d_model)return pe                           gen_pe(max_length, d_model, n)  

虽然它更复杂,但这是 PyTorch 使用的实现,因为它增强了机器学习的性能。

五、变压器中的位置编码

        现在所有的艰苦工作都已经完成,实施很简单。它源自注释转换器和PyTorch。请注意,的默认值为 10,000,默认max_length为 5,000。

        此实现还包含 dropout,它以给定的概率 p 随机清零其输入的某些元素。这有助于正则化并防止神经元共同适应(过度依赖彼此)。输出也按¹⁄₍₁_p₎的系数进行缩放。而不是在本文中深入讨论它。有关详细信息,请参阅有关辍学层的文章。在转向变压器模型的其余部分之前,最好现在就熟悉它,因为它几乎位于其他每一层中。

class PositionalEncoding(nn.Module):def __init__(self, d_model: int, dropout: float = 0.1, max_length: int = 5000):"""Args:d_model:      dimension of embeddingsdropout:      randomly zeroes-out some of the inputmax_length:   max sequence length"""# inherit from Modulesuper().__init__()     # initialize dropout                  self.dropout = nn.Dropout(p=dropout)      # create tensor of 0spe = torch.zeros(max_length, d_model)    # create position column   k = torch.arange(0, max_length).unsqueeze(1)  # calc divisor for positional encoding div_term = torch.exp(                                 torch.arange(0, d_model, 2) * -(math.log(10000.0) / d_model))# calc sine on even indicespe[:, 0::2] = torch.sin(k * div_term)    # calc cosine on odd indices   pe[:, 1::2] = torch.cos(k * div_term)  # add dimension     pe = pe.unsqueeze(0)          # buffers are saved in state_dict but not trained by the optimizer                        self.register_buffer("pe", pe)                        def forward(self, x: Tensor):"""Args:x:        embeddings (batch_size, seq_length, d_model)Returns:embeddings + positional encodings (batch_size, seq_length, d_model)"""# add positional encoding to the embeddingsx = x + self.pe[:, : x.size(1)].requires_grad_(False) # perform dropoutreturn self.dropout(x)

        前向传递

        要执行正向传递,可以使用与之前相同的嵌入式序列。

embeddings
tensor([[[-0.27, -0.82,  0.33,  1.39],[ 1.72, -0.63, -1.13,  0.10],[-0.23, -0.07, -0.28,  1.17],[ 0.61,  1.46,  1.21,  0.84],[-2.05,  1.77,  1.51, -0.21],[ 0.86, -1.81,  0.55,  0.98]],[[ 0.06, -0.34,  2.08, -1.24],[ 1.44, -0.64,  0.78, -1.10],[ 1.78,  1.22,  1.12, -2.35],[-0.48, -0.40,  1.73,  0.54],[ 1.28, -0.18,  0.52,  2.10],[ 0.34,  0.62, -0.45, -0.64]],[[-0.22, -0.66, -1.00, -0.04],[-0.23, -0.07, -0.28,  1.17],[ 1.44, -0.64,  0.78, -1.10],[ 1.78,  1.22,  1.12, -2.35],[-0.48, -0.40,  1.73,  0.54],[ 0.70, -1.35,  0.15, -1.44]]], grad_fn=<EmbeddingBackward0>)

        嵌入序列后,可以创建位置编码矩阵。dropout 设置为 0.0 以便轻松查看嵌入和位置编码之间的相加。这些值与从头开始实现不同,因为 的默认值为 10,000 而不是 100。

d_model = 4
max_length = 10
dropout = 0.0# create the positional encoding matrix
pe = PositionalEncoding(d_model, dropout, max_length)# preview the values
pe.state_dict()
OrderedDict([('pe',tensor([[[ 0.00,  1.00,  0.00,  1.00],[ 0.84,  0.54,  0.01,  1.00],[ 0.91, -0.42,  0.02,  1.00],[ 0.14, -0.99,  0.03,  1.00],[-0.76, -0.65,  0.04,  1.00],[-0.96,  0.28,  0.05,  1.00],[-0.28,  0.96,  0.06,  1.00],[ 0.66,  0.75,  0.07,  1.00],[ 0.99, -0.15,  0.08,  1.00],[ 0.41, -0.91,  0.09,  1.00]]]))])

        在添加它们之前,序列的形状为 (batch_size、seq_length、d_model),即 (3, 6, 4)。位置编码在切片和广播后具有相同的大小,因此前向传递的输出大小为 (batch_size、seq_length、d_model),仍然是 (3, 6, 4)。这表示嵌入在 3 维空间中的 6 个序列,每个序列 4 个令牌,带有位置编码以指示它们在序列中的位置。

pe(embeddings)
 tensor([[[-0.27,  0.18,  0.33,  2.39],[ 2.57, -0.09, -1.12,  1.10],[ 0.68, -0.49, -0.26,  2.17],[ 0.75,  0.47,  1.24,  1.84],[-2.80,  1.12,  1.55,  0.79],[-0.10, -1.53,  0.60,  1.98]],[[ 0.06,  0.66,  2.08, -0.24],[ 2.28, -0.10,  0.79, -0.10],[ 2.69,  0.80,  1.14, -1.35],[-0.34, -1.39,  1.76,  1.54],[ 0.52, -0.83,  0.56,  3.10],[-0.62,  0.90, -0.40,  0.35]],[[-0.22,  0.34, -1.00,  0.96],[ 0.61,  0.47, -0.27,  2.17],[ 2.35, -1.06,  0.80, -0.10],[ 1.92,  0.23,  1.15, -1.35],[-1.24, -1.06,  1.77,  1.54],[-0.26, -1.06,  0.20, -0.44]]], grad_fn=<AddBackward0>)

本系列的下一篇文章是多头注意力层。

请不要忘记点赞和关注更多!:)

引用

  1. 辍学层
  2. 位置编码概述
  3. PyTorch 的位置编码实现
  4. 带注释的变压器
  5. 变压器的位置编码

附录

可视化位置编码的唯一性

在得出结论之前,验证位置编码的唯一性并了解它们如何与更大的序列一起工作将是有益的。

使用 matplotlib,可以轻松地将向量相互比较。

def visualize_pe(max_length, d_model, n):plt.imshow(gen_pe(max_length, d_model, n), aspect="auto")plt.title("Positional Encoding")plt.xlabel("Encoding Dimension")plt.ylabel("Position Index")# set the tick marks for the axesif d_model < 10:plt.xticks(torch.arange(0, d_model))if max_length < 20:plt.yticks(torch.arange(max_length-1, -1, -1))plt.colorbar()plt.show()# plot the encodings
max_length = 10
d_model = 4
n = 100visualize_pe(max_length, d_model, n)

 

        每行表示一个位置编码向量,每列表示与嵌入组合时将添加到的相应维度。

        这也可以在较大的值 nd_model 和 max_length 中看到:

# plot the encodings
max_length = 1000
d_model = 512
n = 10000visualize_pe(max_length, d_model, n)

参考资源:Positional Encoding. This article is the second in The… | by Hunter Phillips | Medium

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

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

相关文章

git 操作

merge操作 git checkout -b bugFix git commit //在bugFix branch上操作&#xff0c;并且commit git checkout main git commit //在main上操作&#xff0c;并且commit git merge bugFix //此时on main branch&#xff0c;如果在bugFix branch执行merge bugFix&#…

fastadmin think-queue supervisor配置

起因是微信支付回调需要同时做发货处理&#xff0c;但是发货接口不能影响,需要队列进行异步处理1. 1.fastadmin 后台购买queue插件(基于think-queue消息队列) 2.代码 2.1 添加文件&#xff1a;application---->extra--->queue.php 内容&#xff1a;我这里用的数据库做…

leetcode 42. 接雨水

2023.8.29 本题可以用双指针做&#xff0c;求出每一列能盛的雨水&#xff0c;再相加即可。不过暴力法会超时&#xff0c;需要优化。 双指针&#xff08;暴力&#xff09;&#xff1a; class Solution { public:int trap(vector<int>& height) {int ans 0;for(int …

(牛客周赛 9)C.小美的01串翻转

题目&#xff1a; 样例&#xff1a; 输入 10001 输出 8 思路&#xff1a; 这里是连续的找子串&#xff0c;权值的意思是 我们取反操作了多少次&#xff0c; 我们有假设长度是 5 &#xff0c;字符串是 10001 那么相邻不一样的字符串有两种情况 01010 或者 10101&#xf…

高等职业学校物联网实训室建设方案

一、概述 1.1专业背景 物联网&#xff08;Internet of Things&#xff09;被称为继计算机、互联网之后世界信息产业第三次浪潮&#xff0c;它并非一个全新的技术领域&#xff0c;而是现代信息技术发展到一定阶段后出现的一种聚合性应用与技术提升&#xff0c;是随着传感网、通…

耐世特Nexteer EDI解决方案

耐世特Nexteer曾经为美国通用汽车全资子公司&#xff0c;是一家集研发、制造、销售于一体的全球化集团公司。耐世特汽车系统公司是转向系统及相关先进技术的全球供应商。该公司为60多家汽车制造商设计、制造、销售电动助力转向器、液压助力转向器、转向管柱和传动轴产品&#x…

GNU make系列之写Makefile文件(1)

一.欢迎来到我的酒馆 在本章节介绍如何写Makefile文件。 目录 一.欢迎来到我的酒馆二.Makefile包含了什么三.引入其它的Makefile文件四.MAKEFILES变量 二.Makefile包含了什么 2.1 Makefile包含了5种类型&#xff1a;显式的规则&#xff0c;隐式的规则&#xff0c;变量的定义&am…

数据结构:八种数据结构大全

数据结构 1.1 数据结构概述 数据结构是计算机存储、组织数据的方式&#xff1b;通常情况下&#xff0c;精心选择的数据结构可以带来更高的运行或者存储效率。数据结构的优良将直接影响着我们程序的性能&#xff1b;常用的数据结构有&#xff1a;数组&#xff08;Array&#xff…

【Qt学习】05:自定义封装界面类

OVERVIEW 自定义封装界面类1.QListWidget2.QTreeWidget3.QTableWidget4.StackedWidget5.Others6.自定义封装界面类-显示效果&#xff08;1&#xff09;添加设计师界面类&#xff08;2&#xff09;在ui中设计自定义界面&#xff08;3&#xff09;在需要使用的界面中添加&#xf…

面试题(三)

目录 一.Spring 1.Spring IOC & AOP 2.Spring bean (1) 作用域 (2) Spring 中的 bean ⽣命周期 (3) Spring 框架中⽤到了哪些设计模式 二.Mybatis 1.标签 2.Dao接口 3.返回与映射 4.延迟加载 三.Kafka 四.设计模式 1.IO 设计模式 2.Spring 中的设计模式详解…

【前端】常用功能合集

目录 js跳转到新标签打开PDF文件js每十个字符换行 es6用表达式或变量名作为对象的属性名 vuev-for插值、:style、:class父组件加载完后再加载子组件keep-alive缓存跨域请求第三方接口跨域请求之callback&#xff08;不建议&#xff09;读取本地文件浏览器播放提示音audio jquer…

Lora升级!ReLoRa!最新论文 High-Rank Training Through Low-Rank Updates

目录 摘要1 引言2 相关工作3 方法4 实验5 结果6 结论7 局限性和未来工作 关注公众号TechLead&#xff0c;分享AI与云服务技术的全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕&#xff0c;复旦机器人智能实验室成员&#xff0…

1、[春秋云镜]CVE-2022-32991

文章目录 一、相关信息二、解题思路&#xff08;手注&#xff09;三、通关思路&#xff08;sqlmap&#xff09; 一、相关信息 靶场提示&#xff1a;该CMS的welcome.php中存在SQL注入攻击。 NVD关于漏洞的描述&#xff1a; 注入点不仅在eid处&#xff01;&#xff01;&#xff…

路由器的简单概述(详细理解+实例精讲)

系列文章目录 华为数通学习&#xff08;4&#xff09; 目录 系列文章目录 华为数通学习&#xff08;4&#xff09; 前言 一&#xff0c;网段间通信 二&#xff0c;路由器的基本特点 三&#xff0c;路由信息介绍 四&#xff0c;路由表 五&#xff0c;路由表的来源有哪些…

新能源汽车动力总成系统及技术

需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer 拆车邦 需要动力系统总成的请联&#xff1a;shbinzer …

k3s or RKE2 helm安装报错dial tcp 127.0.0.1:8080: connect: connection refused

1.报错&#xff1a; Error: INSTALLATION FAILED: Kubernetes cluster unreachable: Get "http://127.0.0.1:8080/version": dial tcp 127.0.0.1:8080: connect: connection refused 2.问题原因&#xff1a; 1.因为helm默认使用k8s的配置文件&#xff0c;默…

uniapp 配置网络请求并使用请求轮播图

由于平台的限制&#xff0c;小程序项目中不支持 axios&#xff0c;而且原生的 wx.request() API 功能较为简单&#xff0c;不支持拦截器等全局定制的功能。因此&#xff0c;建议在 uni-app 项目中使用 escook/request-miniprogram 第三方包发起网络数据请求。 官方文档&#xf…

宏观经济和风电预测误差分析(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

springboot1.5.12升级至2.6.15

首先&#xff0c;加入springboot升级大版本依赖&#xff0c;会在升级过程中打印出错日志提示&#xff08;升级完毕可去除&#xff09; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-properties-migrator</art…

基于龙格-库塔算法优化的BP神经网络(预测应用) - 附代码

基于龙格-库塔算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于龙格-库塔算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.龙格-库塔优化BP神经网络2.1 BP神经网络参数设置2.2 龙格-库塔算法应用 4.测试结果&#xff…