深度学习中的注意力机制一(Pytorch 15)

一 简介

灵长类动物的视觉系统接受了大量的感官输入,这些感官输入远远超过了大脑能够完全处理的程度。然而, 并非所有刺激的影响都是相等的。意识的聚集和专注使灵长类动物能够在复杂的视觉环境中将注意力引向感 兴趣的物体,例如猎物和天敌。只关注一小部分信息的能力对进化更加有意义,使人类得以生存和成功。

自19世纪以来,科学家们一直致力于研究认知神经科学领域的注意力。首先回顾一个经典注意力框架,解释如何在视觉场景中展开注意力。受此框架中的 注意力提示(attention cues) 的启发,我们将设计能够利用这些注意力提示的模型。1964年的Nadaraya‐Waston核回归(kernel regression) 正是具有注意力机制(attention mechanism)的机器学习的简单演示。

然后继续介绍的是 注意力函数,它们在深度学习的注意力模型设计中被广泛使用。具体来说,我们将展示如何使用这些函数来设计Bahdanau注意力。Bahdanau注意力是深度学习中的具有突破性价值的注意力模型,它双向对齐并且可以微分。

最后将描述仅仅基于注意力机制的 Transformer架构,该架构中使用了 多头注意力(multi‐head attention)和 自注意力(self‐attention)。自2017年横空出世,Transformer一直都普遍存在于现代的深度学习应用中,例如 语言视觉语音强化学习 领域。
 

二  注意力机制

自经济学研究稀缺资源分配以来,人们正处在“注意力经济”时代,即 人类的注意力被视为可以交换的、有限的、有价值的且稀缺的商品。许多商业模式也被开发出来去利用这一点:在音乐或视频流媒体服务上,人 们要么消耗注意力在广告上,要么付钱来隐藏广告;为了在网络游戏世界的成长,人们要么消耗注意力在游 戏战斗中,从而帮助吸引新的玩家,要么付钱立即变得强大。总之,注意力不是免费的。

注意力机制通过注意力汇聚将查询(自主性提示)和键(非自主性提示)结合在一起,实现对值(感官输入)的选择倾向

2.1 注意力的可视化

平均汇聚层可以被视为输入的加权平均值,其中各输入的权重是一样的。实际上,注意力汇聚得到的是加权平均的总和值,其中权重是在给定的查询和不同的键之间计算得出的。

为了 可视化注意力权重,需要定义一个show_heatmaps函数。其输入matrices的形状是(要显示的行数,要显 示的列数,查询的数目,键的数目)。

import torch
from d2l import torch as d2l#@save
def show_heatmaps(matrices, xlabel, ylabel, titles=None, figsize=(2.5, 2.5), cmap='Reds'):"""显示矩阵热图"""d2l.use_svg_display()num_rows, num_cols = matrices.shape[0], matrices.shape[1]fig, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize,sharex=True, sharey=True, squeeze=False)for i, (row_axes, row_matrices) in enumerate(zip(axes, matrices)):for j, (ax, matrix) in enumerate(zip(row_axes, row_matrices)):pcm = ax.imshow(matrix.detach().numpy(), cmap=cmap)if i == num_rows - 1:ax.set_xlabel(xlabel)if j == 0:ax.set_ylabel(ylabel)if titles:ax.set_title(titles[j])fig.colorbar(pcm, ax=axes, shrink=0.6)

下面使用一个例子进行演示。在本例子中,仅当查询和键相同时,注意力权重为1,否则为0。

attention_weights = torch.eye(10).reshape((1, 1, 10, 10))
show_heatmaps(attention_weights, xlabel='Keys', ylabel='Queries')

小结:

  • 人类的注意力是有限的、有价值和稀缺的资源
  • 受试者使用非自主性和自主性提示 有选择性地引导注意力前者基于突出性,后者则依赖于意识
  • 注意力机制 与全连接层或者汇聚层的 区别 源于增加的 自主提示
  • 由于 包含了自主性提示,注意力机制与全连接的层或汇聚层不同。
  • 注意力机制通过注意力汇聚使选择 偏向于值(感官输入),其中包含查询(自主性提示)和键(非自主 性提示)。键和值是成对的
  • 可视化查询和键之间的注意力权重 是可行的。

2.2 注意力汇聚 

2.2.1 生成数据集

根据下面的非线性函数生成一个人工数据集:

        y_i = 2sin(x_i) + x_i^{0.8} + \epsilon

其中 ϵ服从均值为0和标准差为0.5的正态分布。在这里生成了50个训练样本和50个测试样本。为了更好地可视 化之后的注意力模式,需要将训练样本进行排序。

import torch
from torch import nn
from d2l import torch as d2ln_train = 50 # 训练样本数
x_train, _ = torch.sort(torch.rand(n_train) * 5) # 排序后的训练样本def f(x):return 2 * torch.sin(x) + x**0.8y_train = f(x_train) + torch.normal(0.0, 0.5, (n_train,)) # 训练样本的输出
x_test = torch.arange(0, 5, 0.1) # 测试样本
y_truth = f(x_test) # 测试样本的真实输出
n_test = len(x_test) # 测试样本数
n_test  # 50

下面的函数将绘制所有的训练样本(样本由圆圈表示),不带噪声项的真实数据生成函数f(标记为“Truth”), 以及学习得到的预测函数(标记为“Pred”)。

2.2.2 平均汇聚

先使用最简单的估计器来解决回归问题。基于平均汇聚来计算所有训练样本输出值的平均值。

def plot_kernel_reg(y_hat):d2l.plot(x_test, [y_truth, y_hat], 'x', 'y', legend=['Truth', 'Pred'],xlim=[0, 5], ylim=[-1, 5])d2l.plt.plot(x_train, y_train, 'o', alpha=0.5);y_hat = torch.repeat_interleave(y_train.mean(), n_test)
plot_kernel_reg(y_hat)

2.2.3 非参数注意力汇聚

如果一个键xi越是接近给定的查询x,那么分配给这个键对应值yi的注意力权重就会越大,也就“获得了更多的注意力”。

值得注意的是,Nadaraya‐Watson核回归是一个非参数模型。因此,是非参数的注意力汇聚(non‐ parametric attention pooling)模型。接下来,我们将基于这个非参数的注意力汇聚模型来绘制预测结果。从 绘制的结果会发现新的模型预测线是平滑的,并且比平均汇聚的预测更接近真实值。

# X_repeat的形状:(n_test,n_train),
# 每一行都包含着相同的测试输入(例如:同样的查询)
X_repeat = x_test.repeat_interleave(n_train).reshape((-1, n_train))
# x_train包含着键。attention_weights的形状:(n_test,n_train),
# 每一行都包含着要在给定的每个查询的值(y_train)之间分配的注意力权重
attention_weights = nn.functional.softmax(-(X_repeat - x_train)**2 / 2, dim=1)
# y_hat的每个元素都是值的加权平均值,其中的权重是注意力权重
y_hat = torch.matmul(attention_weights, y_train)
plot_kernel_reg(y_hat)

现在来观察注意力的权重。这里测试数据的输入相当于查询,而训练数据的输入相当于键。因为两个输入都 是经过排序的,因此由观察可知 “查询‐键”对越接近,注意力汇聚的注意力权重就越高

d2l.show_heatmaps(attention_weights.unsqueeze(0).unsqueeze(0),xlabel='Sorted training inputs',ylabel='Sorted testing inputs')

2.2.4 带参数注意力汇聚

非参数的Nadaraya‐Watson核回归具有一致性(consistency)的优点:如果有足够的数据,此模型会收敛到最优结果。尽管如此,我们还是可以轻松地将可学习的参数集成到注意力汇聚中。

为了更有效地计算小批量数据的注意力,我们可以利用深度学习开发框架中提供的批量矩阵乘法

假设第一个小批量数据包含n个矩阵X1, . . . , Xn,形状为a × b,第二个小批量包含n个矩阵Y1, . . . , Yn,形状 为b × c。它们的批量矩阵乘法得到n个矩阵 X1Y1, . . . , XnYn,形状为a × c。因此,假定两个张量的形状分别 是(n, a, b)和(n, b, c),它们的 批量矩阵乘法输出的形状为(n, a, c)

X = torch.ones((2, 1, 4))
Y = torch.ones((2, 4, 6))
torch.bmm(X, Y).shape   # torch.Size([2, 1, 6])
torch.bmm(X, Y)   
# tensor([[[4., 4., 4., 4., 4., 4.]],
#         [[4., 4., 4., 4., 4., 4.]]])

在注意力机制的背景中,我们可以使用 小批量矩阵乘法来计算小批量数据中的加权平均值

weights = torch.ones((2, 10)) * 0.1
values = torch.arange(20.0).reshape((2, 10))
torch.bmm(weights.unsqueeze(1), values.unsqueeze(-1))# tensor([[[ 4.5000]],
#         [[14.5000]]])

2.2.5 定义模型

使用 小批量矩阵乘法,定义Nadaraya‐Watson核回归的带参数版本为:

class NWKernelRegression(nn.Module):def __init__(self, **kwargs):super().__init__(**kwargs)self.w = nn.Parameter(torch.rand((1,), requires_grad=True))def forward(self, queries, keys, values):# queries和attention_weights的形状为(查询个数,“键-值”对个数)queries = queries.repeat_interleave(keys.shape[1]).reshape((-1, keys.shape[1]))self.attention_weights = nn.functional.softmax(-((queries - keys) * self.w)**2 / 2, dim=1)# values的形状为(查询个数,“键-值”对个数)return torch.bmm(self.attention_weights.unsqueeze(1),values.unsqueeze(-1)).reshape(-1)

接下来,将训练数据集变换为键和值用于训练注意力模型。在带参数的注意力汇聚模型中,任何一个训练样 本的输入都会和除自己以外的所有训练样本的“键-值”对进行计算,从而得到其对应的预测输出。

# X_tile的形状:(n_train,n_train),每一行都包含着相同的训练输入
X_tile = x_train.repeat((n_train, 1))
# Y_tile的形状:(n_train,n_train),每一行都包含着相同的训练输出
Y_tile = y_train.repeat((n_train, 1))
# keys的形状:('n_train','n_train'-1)
keys = X_tile[(1 - torch.eye(n_train)).type(torch.bool)].reshape((n_train, -1))
# values的形状:('n_train','n_train'-1)
values = Y_tile[(1 - torch.eye(n_train)).type(torch.bool)].reshape((n_train, -1))

训练带参数的注意力汇聚模型时,使用平方损失函数和随机梯度下降

net = NWKernelRegression()
loss = nn.MSELoss(reduction='none')
trainer = torch.optim.SGD(net.parameters(), lr=0.5)
animator = d2l.Animator(xlabel='epoch', ylabel='loss', xlim=[1, 5])
for epoch in range(5):trainer.zero_grad()l = loss(net(x_train, keys, values), y_train)l.sum().backward()trainer.step()print(f'epoch {epoch + 1}, loss {float(l.sum()):.6f}')animator.add(epoch + 1, float(l.sum()))

如下所示,训练完带参数的注意力汇聚模型后可以发现:在尝试拟合带噪声的训练数据时,预测结果绘制的 线不如之前非参数模型的平滑

# keys的形状:(n_test,n_train),每一行包含着相同的训练输入(例如,相同的键)
keys = x_train.repeat((n_test, 1))
# value的形状:(n_test,n_train)
values = y_train.repeat((n_test, 1))
y_hat = net(x_test, keys, values).unsqueeze(1).detach()
plot_kernel_reg(y_hat)

为什么新的模型更不平滑了呢?下面看一下输出结果的绘制图:与非参数的注意力汇聚模型相比,带参数的模型加入可学习的参数后,曲线在注意力权重较大的区域变得更不平滑

d2l.show_heatmaps(net.attention_weights.unsqueeze(0).unsqueeze(0),xlabel='Sorted training inputs',ylabel='Sorted testing inputs')

小结:

  • Nadaraya‐Watson核回归是 具有注意力机制的机器学习范例
  • Nadaraya‐Watson核回归的注意力汇聚是 对训练数据中输出的加权平均。从注意力的角度来看,分配给每个值的注意力权重取决于将值所对应的键和查询作为输入的函数。
  • 注意力汇聚可以分为 非参数型和带参数型

三  注意力评分函数

上节使用了 高斯核 来对查询和键之间的关系建模。其中的高斯核指数部分可以视为 注意力评分函数 (attention scoring function),简称评分函数(scoring function),然后把这个函数的输出结果输入到 softmax函数中进行运算。通过上述步骤,将得到与键对应的值的概率分布(即注意力权重)。最后,注意力汇聚的输出 就是基于这些注意力权重的值的加权和。

从宏观来看,上述算法可以用来实现了之前的注意力机制框架。下图说明了如何将注意力汇聚的输出 计算成为值的加权和,其中a表示注意力评分函数。由于注意力权重是概率分布,因此加权和其本质上是加权平均值

正如上图所示,选择不同的注意力评分函数a会导致不同的注意力汇聚操作。本节将介绍两个流行的评分函数稍后将用他们来实现更复杂的注意力机制

softmax操作 用于输出一个概率分布作为 注意力权重。在某些情况下,并非所有的值都应该 被纳入到注意力汇聚中。为了仅将有意义的词元作为值来获取注意力汇聚,可以指定一个有效序列长度(即词元的个数), 以便在计算softmax时过滤掉超出指定范围的位置。下面的masked_softmax函数 实现了这样的掩蔽softmax操 作(masked softmax operation),其中任何超出有效长度的位置都被掩蔽并置为0

import math
import torch
from torch import nn
from d2l import torch as d2l#@save
def masked_softmax(X, valid_lens):"""通过在最后一个轴上掩蔽元素来执行softmax操作"""# X:3D张量,valid_lens:1D或2D张量if valid_lens is None:return nn.functional.softmax(X, dim=-1)else:shape = X.shapeif valid_lens.dim() == 1:valid_lens = torch.repeat_interleave(valid_lens, shape[1])else:valid_lens = valid_lens.reshape(-1)# 最后一轴上被掩蔽的元素使用一个非常大的负值替换,从而其softmax输出为0X = d2l.sequence_mask(X.reshape(-1, shape[-1]), valid_lens,value=-1e6)return nn.functional.softmax(X.reshape(shape), dim=-1)

为了 演示此函数 是如何工作的,考虑由两个2 × 4矩阵表示的样本,这两个样本的有效长度分别为2和3。经过掩蔽softmax操作,超出有效长度的值都被掩蔽为0。

masked_softmax(torch.rand(2, 2, 4), torch.tensor([2, 3]))# tensor([[[0.5572, 0.4428, 0.0000, 0.0000],
#          [0.5652, 0.4348, 0.0000, 0.0000]],#         [[0.3246, 0.2382, 0.4372, 0.0000],
#          [0.2726, 0.4352, 0.2922, 0.0000]]])

同样,也可以使用二维张量,为矩阵样本中的每一行指定有效长度

masked_softmax(torch.rand(2, 2, 4), torch.tensor([[1, 3], [2, 4]]))# tensor([[[1.0000, 0.0000, 0.0000, 0.0000],
#          [0.3557, 0.2924, 0.3519, 0.0000]],#         [[0.4293, 0.5707, 0.0000, 0.0000],
#          [0.3322, 0.1845, 0.2947, 0.1886]]])

3.1 加性注意力

一般来说,当查询和键是不同长度的矢量时,可以使用加性注意力作为评分函数

其中可学习的参数是Wq ∈ R^h×q、Wk ∈ R^h×k和 wv ∈ R h。将查询和键连结起来后输入到一 个多层感知机(MLP)中,感知机包含一个隐藏层,其隐藏单元数是一个超参数h。通过 使用tanh作为激活函数,并且 禁用偏置项

#@save
class AdditiveAttention(nn.Module):"""加性注意力"""def __init__(self, key_size, query_size, num_hiddens, dropout, **kwargs):super(AdditiveAttention, self).__init__(**kwargs)self.W_k = nn.Linear(key_size, num_hiddens, bias=False)self.W_q = nn.Linear(query_size, num_hiddens, bias=False)self.w_v = nn.Linear(num_hiddens, 1, bias=False)self.dropout = nn.Dropout(dropout)def forward(self, queries, keys, values, valid_lens):queries, keys = self.W_q(queries), self.W_k(keys)# 在维度扩展后,# queries的形状:(batch_size,查询的个数,1,num_hidden)# key的形状:(batch_size,1,“键-值”对的个数,num_hiddens)# 使用广播方式进行求和features = queries.unsqueeze(2) + keys.unsqueeze(1)features = torch.tanh(features)# self.w_v仅有一个输出,因此从形状中移除最后那个维度。# scores的形状:(batch_size,查询的个数,“键-值”对的个数)scores = self.w_v(features).squeeze(-1)self.attention_weights = masked_softmax(scores, valid_lens)# values的形状:(batch_size,“键-值”对的个数,值的维度)return torch.bmm(self.dropout(self.attention_weights), values)

用一个 小例子来演示 上面的AdditiveAttention类,其中查询、键和值的形状为(批量大小,步数或词元序列 长度,特征大小),实际输出为(2, 1, 20)、(2, 10, 2)和(2, 10, 4)。注意力汇聚输出的形状为(批量大小,查询的 步数,值的维度)。

queries, keys = torch.normal(0, 1, (2, 1, 20)), torch.ones((2, 10, 2))
# values的小批量,两个值矩阵是相同的
values = torch.arange(40, dtype=torch.float32).reshape(1, 10, 4).repeat(2, 1, 1)
valid_lens = torch.tensor([2, 6])
attention = AdditiveAttention(key_size=2, query_size=20, num_hiddens=8,dropout=0.1)
attention.eval()
attention(queries, keys, values, valid_lens)# tensor([[[ 2.0000,  3.0000,  4.0000,  5.0000]],
#         [[10.0000, 11.0000, 12.0000, 13.0000]]], grad_fn=<BmmBackward0>)

尽管加性注意力包含了 可学习的参数,但由于本例子中每个键都是相同的,所以注意力权重是均匀的,由指 定的有效长度决定。

d2l.show_heatmaps(attention.attention_weights.reshape((1, 1, 2, 10)),xlabel='Keys', ylabel='Queries')

3.2 缩放点积注意力

使用 点积可以得到计算效率更高的评分函数,但是 点积操作要求查询和键具有相同的长度d。假设查询和键 的所有元素都是独立的随机变量,并且都满足零均值和单位方差,那么两个向量的点积的均值为0,方差为d。 为确保无论向量长度如何,点积的方差在不考虑向量长度的情况下仍然是1,我们再将点积除以√ d。

下面的缩放点积注意力的实现 使用了暂退法进行模型正则化

#@save
class DotProductAttention(nn.Module):"""缩放点积注意力"""def __init__(self, dropout, **kwargs):super(DotProductAttention, self).__init__(**kwargs)self.dropout = nn.Dropout(dropout)# queries的形状:(batch_size,查询的个数,d)# keys的形状:(batch_size,“键-值”对的个数,d)# values的形状:(batch_size,“键-值”对的个数,值的维度)# valid_lens的形状:(batch_size,)或者(batch_size,查询的个数)def forward(self, queries, keys, values, valid_lens=None):d = queries.shape[-1]# 设置transpose_b=True为了交换keys的最后两个维度scores = torch.bmm(queries, keys.transpose(1,2)) / math.sqrt(d)self.attention_weights = masked_softmax(scores, valid_lens)return torch.bmm(self.dropout(self.attention_weights), values)

为了演示上述的DotProductAttention类,我们使用与先前加性注意力例子中相同的键、值和有效长度。对于 点积操作,我们令 查询的特征维度与键的特征维度大小相同

queries = torch.normal(0, 1, (2, 1, 2))
attention = DotProductAttention(dropout=0.5)
attention.eval()
attention(queries, keys, values, valid_lens)# tensor([[[ 2.0000,  3.0000,  4.0000,  5.0000]],
#         [[10.0000, 11.0000, 12.0000, 13.0000]]])

与加性注意力演示相同,由于键包含的是相同的元素,而这些元素无法通过任何查询进行区分,因此获得了  均匀的注意力权重

d2l.show_heatmaps(attention.attention_weights.reshape((1, 1, 2, 10)),xlabel='Keys', ylabel='Queries')

小结:

  • 将注意力汇聚的输出计算可以作为值的加权平均,选择不同的注意力评分函数会带来不同的注意力汇聚操作
  • 当查询和键是不同长度的矢量时,可以使用可加性注意力评分函数。当它们的长度相同时,使用缩放的 “点-积”注意力评分函数的计算效率更高

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

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

相关文章

电子电器架构 --- 主机厂产线的两种刷写方法

电子电器架构 — 主机厂产线的两种刷写方法 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证…

DS:顺序表、单链表的相关OJ题训练(1)

欢迎各位来到 Harper.Lee 的学习小世界&#xff01; 博主主页传送门&#xff1a;Harper.Lee的博客主页 想要一起进步的uu可以来后台找我交流哦&#xff01; 在DS&#xff1a;单链表的实现 和 DS&#xff1a;顺序表的实现这两篇文章中&#xff0c;我详细介绍了顺序表和单链表的…

IDEA基于Maven构建项目

IDEA基于Maven构建项目 一、Maven简介 Apache Maven 是一个软件项目管理和理解工具。基于项目对象模型的概念&#xff08;POM&#xff09;&#xff0c;Maven 可以从中心信息中管理项目的构建、报告和文档。 Apache Maven 可以用于构建和管理任何基于 Java 的项目。 下载地址…

【可实战】被测需求理解(需求文档是啥样的、从哪些角度进行需求评审、需求分析需要分析出哪些内容、如何提高需求分析能力)

产品人员会产出一个需求文档&#xff0c;然后组织一个需求的宣讲。测试人员的任务就是在需求宣讲当中&#xff0c;分析需求有没有存在一些问题&#xff0c;然后在需求宣讲结束之后通过分析需求文档&#xff0c;分析里面的测试点并预估一个排期。 一、需求文档是什么样的&#x…

视频教程下载:为 GPTs 商店构建 10 个 GPTs获得被动收入

欢迎来到 AI 驱动的内容创作新时代 - GPT 商店。这门综合课程是您成为定制和利用 GPT 模型解决多样化应用的专家的路线图。无论你是错过了应用商店革命的初始浪潮还是乘着它取得了成功&#xff0c;这都是你站在下一个重大数字飞跃前沿的机会。 课程模块&#xff1a; - 介绍 Ch…

Unity 性能优化之动态批处理(四)

提示&#xff1a;仅供参考&#xff0c;有误之处&#xff0c;麻烦大佬指出&#xff0c;不胜感激&#xff01; 文章目录 前言一、动态合批是什么&#xff1f;二、使用动态批处理1.打开动态合批2.满足条件 三、检查动态合批是否成功五、动态合批弊端总结 前言 动态批处理是常用优…

libmodbus使用

安装可以看这个博客&#xff1a; https://blog.csdn.net/hanhui22/article/details/105786762 它的安装可以&#xff0c;但是编译测试看不太懂&#xff0c;我没跟着它的编译&#xff0c;完了后把/lib下的 放到开发板的/usr/lib下 编写代码: #include <stdio.h> #inclu…

UI组件库和内容文字的中英文切换

同时实现UI组件库(这里以ElementPlus为例)和内容文字的中英文切换 1. 安装vueI18n和element-plus pnpm i vue-i18n element-plus 2. 然后在项目中src目录下新建lang文件夹&#xff0c;里面新建en.ts和zh.ts还有index.ts index.ts import { createI18n } from vue-i18n impor…

jvm重要参数可视化和线上问题排查

jvm重要参数可视化和线上问题排查 目标jvm参数分类(了解)运行时数据区相关的&#xff08;jdk1.8&#xff09;处理 OOM 相关的垃圾回收器相关的GC 日志记录相关的意义,默认值,调优原则&#xff08;重要&#xff0c; 待拆分&#xff09; 排查 OOM 流程 和 常见原因参考文章 目标 …

c#数据库:1.c#创建并连接数据库

安装软件:SQL Server Management Studio Management Studio Visual Studio 2022 启动服务: 打开SQL Server Management Studio Management Studio ,连接到服务器(GUANZU是我的计算机名) 新建数据库,随便起个名字叫aq: c#代码: using System; using System.Collections.Gener…

深度学习:基于Keras,使用长短期记忆神经网络模型LSTM和RMSProp优化算法进行销售预测分析

前言 系列专栏&#xff1a;【机器学习&#xff1a;项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目&#xff0c;每个项目都处理一组不同的问题&#xff0c;包括监督和无监督学习、分类、回归和聚类&#xff0c;而且涉及创建深度学习模型、处理非…

[C++核心编程-02]----C++引用详解和使用方法分析

前言 在C中&#xff0c;引用是一个别名&#xff0c;它允许将一个已存在的变量或对象用不同的名称来访问。引用在定义时必须初始化&#xff0c;并且一旦初始化就不能再绑定其他对象&#xff0c;因此引用在声明时被初始化后就不能再改变引用对象。引用使用&符号进行声明。 引…

【C++STL详解(六)】--------list的模拟实现

目录 前言 一、接口总览 一、节点类的模拟实现 二、迭代器类的模拟实现 迭代器的目的 list迭代器为何要写成类&#xff1f; 迭代器类模板参数说明 模拟实现 1.构造函数 2.*运算符重载 3.->运算符重载 4.前置 5.后置 6.前置-- 7.后置-- 8.! 9. 三、list类的…

【Mac】graphpad prism for Mac(专业医学绘图工具) v10.2.3安装教程

软件介绍 GraphPad Prism for Mac是一款专业的科学数据分析和绘图软件&#xff0c;广泛用于生物医学和科学研究领域。它具有强大的统计分析功能&#xff0c;可以进行各种数据分析&#xff0c;包括描述性统计、生存分析、回归分析、方差分析等。同时&#xff0c;它还提供了丰富…

滑动验证码登陆测试编程示例

一、背景及原理 处理登录时的滑动验证码有两个难点&#xff0c;第一个是找到滑块需要移动的距离&#xff0c;第二个是模拟人手工拖动的轨迹。模拟轨迹在要求不是很严的情况下可以用先加速再减速拖动的方法&#xff0c;即路程的前半段加速度为正值&#xff0c;后半段为负值去模…

Go未用代码消除与可执行文件瘦身

在日常编写Go代码时&#xff0c;我们会编写很多包&#xff0c;也会在编写的包中引入了各种依赖包。在大型Go工程中&#xff0c;这些直接依赖和间接依赖的包数目可能会有几十个甚至上百个。依赖包有大有小&#xff0c;但通常我们不会使用到依赖包中的所有导出函数或类型方法。 这…

如何高速下载,百度 阿里 天翼 等网盘内的内容

如何高速下载&#xff0c;百度 阿里 天翼 等网盘内的内容&#x1f3c5; 前言教程下期更新预报&#x1f3c5; 前言 近段时间经常给大家分享各种视频教程&#xff0c;由于分享的资料是用迅雷网盘存的&#xff0c;但是绝大部分用户都是使用的某度&#xff0c;阿某的这些网盘&…

VScode添加c/c++头文件路径

1.设置工作区include path方法&#xff1a; 命令面板 -> 输入c/c 修改配置文件&#xff0c;添加路径&#xff1a; 2.全局路径&#xff1a; 设置 - > 搜索include path

tomcat+maven+java+mysql图书管理系统1-配置项目环境

目录 一、软件版本 二、具体步骤 一、软件版本 idea2022.2.1 maven是idea自带不用另外下载 tomcat8.5.99 Javajdk17 二、具体步骤 1.新建项目 稍等一会&#xff0c;创建成功如下图所示&#xff0c;主要看左方目录相同不。 给maven配置国外镜像 在左上…

【DPU系列之】Bluefield 2 DPU卡的功能图,ConnectX网卡、ARM OS、Host OS的关系?(通过PCIe Switch连接)

核心要点&#xff1a; CX系列网卡与ARM中间有一个PCIe Swtich的硬件单元链接。 简要记录。 可以看到图中两个灰色框&#xff0c;上端是Host主机&#xff0c;下端是BlueField DPU卡。图中是BF2的图&#xff0c;是BF2用的是DDR4。DPU上的Connect系列网卡以及ARM系统之间有一个…