深度学习----------------------注意力机制

目录

  • 心理学
    • 不随意线索
    • 随意线索
  • 注意力机制
  • 非参注意力池化层
  • Nadaraya-Watson核回归
    • 参数化的注意力机制
  • 总结
  • 注意力汇聚:Nadaraya-Watson核回归代码
    • 生成数据集
    • 核回归
    • 非参数注意力汇聚
    • 注意力权重
      • 该部分总代码
    • 带参数的注意力汇聚
      • 将训练数据集转换为键和值
      • 训练带参数的注意力汇聚模型
      • 预测结果绘制
        • 该部分总代码

心理学

动物需要在复杂环境下有效关注值得注意的点。
心理学框架:人类根据随意线索和不随意线索选择注意点

不随意线索

在这里插入图片描述

随意线索

在这里插入图片描述




注意力机制

卷积全连接池化层都只考虑不随意线索
注意力机制则显示的考虑随意线索
    随意线索被称为查询
    每个输入一个值不随意线索的对
    通过注意力池化层来有偏向性的选择某些输入。




非参注意力池化层

给定数据( x i x_i xi, y i y_i yi),i=1,…,n。其中x就是key、y就是value。

最简单的池化是平均池化
这里的x是query
在这里插入图片描述




更好的方案Nadaraya-Watson核回归

在这里插入图片描述




Nadaraya-Watson核回归

在这里插入图片描述

参数化的注意力机制

在之前基础上引入可以学习的w

在这里插入图片描述




总结

心理学认为人通过随意线索不随意线索选择注意点

注意力机制中,通过query(随意线索)和key(不随意线索)来有偏向性的选择输入

在这里插入图片描述




注意力汇聚:Nadaraya-Watson核回归代码

import torch
from torch import nn
from d2l import torch as d2l



生成数据集

import torch# 训练集样本数量
n_train = 50
# 生成训练集特征x_train,范围为[0, 5),并进行排序
x_train, _ = torch.sort(torch.rand(n_train) * 5)# 定义函数f,用于生成标签y(真实的函数)
def f(x):return 2 * torch.sin(x) + x ** 0.8# 生成训练集标签y_train,并加上服从正态分布的噪声
y_train = f(x_train) + torch.normal(0.0, 0.5, (n_train,))
# 生成测试集特征x_test,范围为[0, 5),步长为0.1
x_test = torch.arange(0, 5, 0.1)
# 生成测试集的真实标签y_truth
y_truth = f(x_test)
# 计算测试集样本数量
n_test = len(x_test)
print(n_test)

在这里插入图片描述


核回归

在这里插入图片描述

import torch
from torch import nn
from d2l import torch as d2l# 定义函数f,用于生成标签y(真实的函数)
def f(x):return 2 * torch.sin(x) + x ** 0.8# 绘制核回归结果的图像
def plot_kernel_reg(y_hat):# 绘制x_test和对应的真实标签y_truth以及预测标签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)# 训练集样本数量
n_train = 50
# 生成训练集特征x_train,范围为[0, 5),并进行排序
x_train, _ = torch.sort(torch.rand(n_train) * 5)
# 生成训练集标签y_train,并加上服从正态分布的噪声
y_train = f(x_train) + torch.normal(0.0, 0.5, (n_train,))
# 生成测试集特征x_test,范围为[0, 5),步长为0.1
x_test = torch.arange(0, 5, 0.1)
# 生成测试集的真实标签y_truth
y_truth = f(x_test)
# 计算测试集样本数量
n_test = len(x_test)
# 将y_train的均值重复n_test次作为预测标签y_hat
# 最简单的池化----平均池化,公式:f(x)=1/n * sum(y_i)
y_hat = torch.repeat_interleave(y_train.mean(), n_test)
# 调用plot_kernel_reg函数,绘制核回归结果的图像
plot_kernel_reg(y_hat)
d2l.plt.show()

在这里插入图片描述




非参数注意力汇聚

在这里插入图片描述

import torch
from torch import nn
from d2l import torch as d2l# 定义函数f,用于生成标签y(真实的函数)
def f(x):return 2 * torch.sin(x) + x ** 0.8# 绘制核回归结果的图像
def plot_kernel_reg(y_hat):# 绘制x_test和对应的真实标签y_truth以及预测标签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)# 训练集样本数量
n_train = 50
# 生成训练集特征x_train,范围为[0, 5),并进行排序
x_train, _ = torch.sort(torch.rand(n_train) * 5)
# 生成训练集标签y_train,并加上服从正态分布的噪声
y_train = f(x_train) + torch.normal(0.0, 0.5, (n_train,))
# 生成测试集特征x_test,范围为[0, 5),步长为0.1
x_test = torch.arange(0, 5, 0.1)
# 生成测试集的真实标签y_truth
y_truth = f(x_test)# 将测试集特征x_test重复n_train次并重新reshape为二维矩阵
# X_repeat的形状为torch.Size([50, 50]),
# x_test为
# tensor([0.0000, 0.1000, 0.2000, 0.3000, 0.4000, 0.5000, 0.6000, 0.7000, 0.8000,
#         0.9000, 1.0000, 1.1000, 1.2000, 1.3000, 1.4000, 1.5000, 1.6000, 1.7000,
#         1.8000, 1.9000, 2.0000, 2.1000, 2.2000, 2.3000, 2.4000, 2.5000, 2.6000,
#         2.7000, 2.8000, 2.9000, 3.0000, 3.1000, 3.2000, 3.3000, 3.4000, 3.5000,
#         3.6000, 3.7000, 3.8000, 3.9000, 4.0000, 4.1000, 4.2000, 4.3000, 4.4000,
#         4.5000, 4.6000, 4.7000, 4.8000, 4.9000])
# X_repeat为在列上重复五十次
# tensor([[0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],
#         [0.1000, 0.1000, 0.1000,  ..., 0.1000, 0.1000, 0.1000],
#         [0.2000, 0.2000, 0.2000,  ..., 0.2000, 0.2000, 0.2000],
#         ...,
#         [4.7000, 4.7000, 4.7000,  ..., 4.7000, 4.7000, 4.7000],
#         [4.8000, 4.8000, 4.8000,  ..., 4.8000, 4.8000, 4.8000],
#         [4.9000, 4.9000, 4.9000,  ..., 4.9000, 4.9000, 4.9000]])
X_repeat = x_test.repeat_interleave(n_train).reshape((-1, n_train))
# 计算注意力权重,通过对特征差值的平方取负并除以2,再进行softmax归一化
# dim=0是按行求和(实际上是按照行方向对每一列求和)
# dim=1按列求和(实际上是按照列的方向对每一行求和)每一行的和为1
attention_weights = nn.functional.softmax(-(X_repeat - x_train)**2 / 2, dim=1)
# 注意力权重与训练集标签y_train进行矩阵乘法得到预测标签y_hat
y_hat = torch.matmul(attention_weights, y_train)
# 调用plot_kernel_reg函数,绘制非参数注意力汇聚的核回归结果图像
plot_kernel_reg(y_hat)
d2l.plt.show()

在这里插入图片描述

非参的好处是不需要学习参数,然后有理论证明只要给你足够多的数据是能够把原始的模型弄出来的。




注意力权重

# 可视化注意力权重
d2l.show_heatmaps(attention_weights.unsqueeze(0).unsqueeze(0),xlabel='Sorted training inputs', ylabel='Sorted test inputs')



该部分总代码

import torch
from torch import nn
from d2l import torch as d2l# 定义函数f,用于生成标签y(真实的函数)
def f(x):return 2 * torch.sin(x) + x ** 0.8# 训练集样本数量
n_train = 50
# 生成训练集特征x_train,范围为[0, 5),并进行排序
x_train, _ = torch.sort(torch.rand(n_train) * 5)
# 生成训练集标签y_train,并加上服从正态分布的噪声
y_train = f(x_train) + torch.normal(0.0, 0.5, (n_train,))
# 生成测试集特征x_test,范围为[0, 5),步长为0.1
x_test = torch.arange(0, 5, 0.1)
# 生成测试集的真实标签y_truth
y_truth = f(x_test)# 将测试集特征x_test重复n_train次并重新reshape为二维矩阵
# X_repeat的形状为torch.Size([50, 50]),
# x_test为
# tensor([0.0000, 0.1000, 0.2000, 0.3000, 0.4000, 0.5000, 0.6000, 0.7000, 0.8000,
#         0.9000, 1.0000, 1.1000, 1.2000, 1.3000, 1.4000, 1.5000, 1.6000, 1.7000,
#         1.8000, 1.9000, 2.0000, 2.1000, 2.2000, 2.3000, 2.4000, 2.5000, 2.6000,
#         2.7000, 2.8000, 2.9000, 3.0000, 3.1000, 3.2000, 3.3000, 3.4000, 3.5000,
#         3.6000, 3.7000, 3.8000, 3.9000, 4.0000, 4.1000, 4.2000, 4.3000, 4.4000,
#         4.5000, 4.6000, 4.7000, 4.8000, 4.9000])
# X_repeat为在列上重复五十次
# tensor([[0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],
#         [0.1000, 0.1000, 0.1000,  ..., 0.1000, 0.1000, 0.1000],
#         [0.2000, 0.2000, 0.2000,  ..., 0.2000, 0.2000, 0.2000],
#         ...,
#         [4.7000, 4.7000, 4.7000,  ..., 4.7000, 4.7000, 4.7000],
#         [4.8000, 4.8000, 4.8000,  ..., 4.8000, 4.8000, 4.8000],
#         [4.9000, 4.9000, 4.9000,  ..., 4.9000, 4.9000, 4.9000]])
X_repeat = x_test.repeat_interleave(n_train).reshape((-1, n_train))
# 计算注意力权重,通过对特征差值的平方取负并除以2,再进行softmax归一化
# dim=0是按行求和(实际上是按照行方向对每一列求和)
# dim=1按列求和(实际上是按照列的方向对每一行求和)每一行的和为1
attention_weights = nn.functional.softmax(-(X_repeat - x_train)**2 / 2, dim=1)
# 可视化注意力权重
d2l.show_heatmaps(attention_weights.unsqueeze(0).unsqueeze(0),xlabel='Sorted training inputs', ylabel='Sorted test inputs')
d2l.plt.show()

在这里插入图片描述




带参数注意力汇聚 假定两个张量的形状分别是(n,a,b)和(n,b,c),他们的批量矩阵乘法输出的形状为(n,a,c)

import torchX = torch.ones((2, 1, 4))
Y = torch.ones((2, 4, 6))
print(torch.bmm(X, Y).shape)

在这里插入图片描述


使用小批量矩阵乘法来计算小批量数据中的加权平均值

import torch# weights 的形状为[2,10]
weights = torch.ones((2, 10)) * 0.1
values = torch.arange(20.0).reshape((2, 10))
# 执行小批量矩阵乘法,计算加权平均值
# weights.unsqueeze(1)的形状为[2,1,10],在第一维度上加了一个维度
# values.unsqueeze(-1)的形状为[2,10,1],在最后一维度上加了一个维度
torch.bmm(weights.unsqueeze(1), values.unsqueeze(-1))



带参数的注意力汇聚

在这里插入图片描述

# 带参数的注意力汇聚
class NWKernelRegression(nn.Module):def __init__(self, **kwargs):super().__init__(**kwargs)# 创建形状为(1,)的参数张量w,用于调整注意力权重self.w = nn.Parameter(torch.rand((1,), requires_grad=True))def forward(self, queries, keys, values):# 重复queries并调整形状,使其与keys具有相同的列数queries = queries.repeat_interleave(keys.shape[1]).reshape(-1, keys.shape[1])# 计算注意力权重,通过调整参数w对注意力进行调节self.attention_weights = nn.functional.softmax(-((queries - keys) * self.w) ** 2 / 2, dim=1)# 执行带参数的注意力汇聚,并返回最终结果的形状调整return torch.bmm(self.attention_weights.unsqueeze(1), values.unsqueeze(-1)).reshape(-1)



将训练数据集转换为键和值

import torch
from torch import nn# 带参数的注意力汇聚
class NWKernelRegression(nn.Module):def __init__(self, **kwargs):super().__init__(**kwargs)# 创建形状为(1,)的参数张量w,用于调整注意力权重self.w = nn.Parameter(torch.rand((1,), requires_grad=True))def forward(self, queries, keys, values):# 重复queries并调整形状,使其与keys具有相同的列数queries = queries.repeat_interleave(keys.shape[1]).reshape(-1, keys.shape[1])# 计算注意力权重,通过调整参数w对注意力进行调节self.attention_weights = nn.functional.softmax(-((queries - keys) * self.w) ** 2 / 2, dim=1)# 执行带参数的注意力汇聚,并返回最终结果的形状调整return torch.bmm(self.attention_weights.unsqueeze(1), values.unsqueeze(-1)).reshape(-1)def f(x):return 2 * torch.sin(x) + x ** 0.8n_train = 50
x_train, _ = torch.sort(torch.rand(n_train) * 5)
y_train = f(x_train) + torch.normal(0.0, 0.5, (n_train,))
# X_tile的形状:(50, 50)
X_tile = x_train.repeat((n_train, 1))
# 将y_train在行维度上重复n_train次,形成一个矩阵Y_tile,形状为(n_train, n_train)
Y_tile = y_train.repeat((n_train, 1))
# 通过掩码操作,从X_tile中排除对角线元素,得到键矩阵keys
# torch.eye(n_train)使对角线全为1其余为0
# tensor([[1., 0., 0.,  ..., 0., 0., 0.],
#         [0., 1., 0.,  ..., 0., 0., 0.],
#         [0., 0., 1.,  ..., 0., 0., 0.],
#         ...,
#         [0., 0., 0.,  ..., 1., 0., 0.],
#         [0., 0., 0.,  ..., 0., 1., 0.],
#         [0., 0., 0.,  ..., 0., 0., 1.]])
# 然后使1 - torch.eye(n_train)将对角线的元素变为0其余为1,然后将结果转为布尔型
# keys的形状为[50, 49]
keys = X_tile[(1 - torch.eye(n_train)).type(torch.bool)].reshape((n_train, -1))
# 通过掩码操作,从Y_tile中排除对角线元素,得到值矩阵values
values = Y_tile[(1 - torch.eye(n_train)).type(torch.bool)].reshape(n_train, -1)

往前缩进一列,所以变成了49列
在这里插入图片描述




训练带参数的注意力汇聚模型

import torch
from torch import nn
from d2l import torch as d2l# 带参数的注意力汇聚
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 = 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)return torch.bmm(self.attention_weights.unsqueeze(1), values.unsqueeze(-1)).reshape(-1)def f(x):return 2 * torch.sin(x) + x ** 0.8n_train = 50
x_train, _ = torch.sort(torch.rand(n_train) * 5)
y_train = f(x_train) + torch.normal(0.0, 0.5, (n_train,))
X_tile = x_train.repeat((n_train, 1))
Y_tile = y_train.repeat((n_train, 1))
keys = X_tile[(1 - torch.eye(n_train)).type(torch.bool)].reshape((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])# 遍历5次
for epoch in range(5):trainer.zero_grad()l = loss(net(x_train, keys, values), y_train) / 2# 反向传播,计算梯度l.sum().backward()# 更新参数trainer.step()# 打印当前的损失print(f'epoch {epoch + 1}, loss {float(l.sum()):.6f}')# 绘制损失曲线animator.add(epoch + 1, float(l.sum()))
d2l.plt.show()

在这里插入图片描述




预测结果绘制

import torch
from torch import nn
from d2l import torch as d2l# 带参数的注意力汇聚
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 = 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)return torch.bmm(self.attention_weights.unsqueeze(1), values.unsqueeze(-1)).reshape(-1)# 绘制核回归结果的图像
def plot_kernel_reg(y_hat):# 绘制x_test和对应的真实标签y_truth以及预测标签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)def f(x):return 2 * torch.sin(x) + x ** 0.8n_train = 50
x_train, _ = torch.sort(torch.rand(n_train) * 5)
y_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)X_tile = x_train.repeat((n_train, 1))
Y_tile = y_train.repeat((n_train, 1))
keys = X_tile[(1 - torch.eye(n_train)).type(torch.bool)].reshape((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)# 遍历5次
for epoch in range(5):trainer.zero_grad()l = loss(net(x_train, keys, values), y_train) / 2# 反向传播,计算梯度l.sum().backward()# 更新参数trainer.step()# 打印当前的损失print(f'epoch {epoch + 1}, loss {float(l.sum()):.6f}')keys = x_train.repeat((n_test, 1))
values = y_train.repeat((n_test, 1))
# 使用训练好的模型进行预测,得到预测结果y_hat
y_hat = net(x_test, keys, values).unsqueeze(1).detach()
# 绘制预测结果
plot_kernel_reg(y_hat)
d2l.plt.show()

在这里插入图片描述


# 曲线在注意力权重较大的区域变得更不平滑
d2l.show_heatmaps(net.attention_weights.unsqueeze(0).unsqueeze(0),xlabel='Sorted training inputs', ylabel='Sorted testing inputs')

在这里插入图片描述


该部分总代码
import torch
from torch import nn
from d2l import torch as d2l# 带参数的注意力汇聚
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 = 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)return torch.bmm(self.attention_weights.unsqueeze(1), values.unsqueeze(-1)).reshape(-1)# 绘制核回归结果的图像
def plot_kernel_reg(y_hat):# 绘制x_test和对应的真实标签y_truth以及预测标签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)def f(x):return 2 * torch.sin(x) + x ** 0.8n_train = 50
x_train, _ = torch.sort(torch.rand(n_train) * 5)
y_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)X_tile = x_train.repeat((n_train, 1))
Y_tile = y_train.repeat((n_train, 1))
keys = X_tile[(1 - torch.eye(n_train)).type(torch.bool)].reshape((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)# 遍历5次
for epoch in range(5):trainer.zero_grad()l = loss(net(x_train, keys, values), y_train) / 2# 反向传播,计算梯度l.sum().backward()# 更新参数trainer.step()# 打印当前的损失print(f'epoch {epoch + 1}, loss {float(l.sum()):.6f}')keys = x_train.repeat((n_test, 1))
values = y_train.repeat((n_test, 1))
# 使用训练好的模型进行预测,得到预测结果y_hat
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')
d2l.plt.show()

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

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

相关文章

[Linux] 进程创建、退出和等待

标题:[Linux] 进程创建、退出和等待 个人主页水墨不写bug (图片来源于AI) 目录 一、进程创建fork() 1) fork的返回值: 2)写时拷贝 ​编辑3)fork常规用法 4&#xff…

线性代数书中求解齐次线性方程组、非齐次线性方程组方法的特点和缺陷(附实例讲解)

目录 一、克拉默法则 1. 方法概述 2. 例16(1) P45 3. 特点 (1) 只适用于系数矩阵是方阵 (2) 只适用于行列式非零 (3) 只适用于唯一解的情况 (4) 只适用于非齐次线性方程组 二、逆矩阵 1. 方法概述 2. 例16(2) P45 3. 特点 (1) 只适用于系数矩阵必须是方阵且可逆 …

计算机毕业设计 基于Python的无人超市管理系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…

Leecode热题100-560.和为k的子数组

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:nums [1,1,1], k 2 输出:2示例 2: 输入:nums [1,2,3], k…

五、类与对象包访问权限

类与对象&包&访问权限 类的定义类的概念定义和使用类对象的初始化类的成员函数 再谈基本类型运算符重载函数中缀函数空值和空类型解构包和导入访问权限控制内部类 类的定义 在之前,我们一直在使用顶层定义: 在Kotlin中,顶层定义&…

计算机网络:计算机网络概述 —— 网络拓扑结构

文章目录 网络拓扑总线型拓扑特点缺陷 星型拓扑特点缺陷 环型拓扑特点缺陷 网状型拓扑优点缺陷 树型拓扑特点缺陷 网络拓扑 网络拓扑指的是计算机网络中节点(计算机、交换机、路由器等)之间物理或逻辑连接的结构。网络拓扑定义了节点之间的布局、连接方…

基于ssm 框架的java 开发语言的 在线教育学习平台系统设计与实现 源码 论文

博主介绍:专注于Java(springboot ssm springcloud等开发框架) vue .net php phython node.js uniapp小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆…

【高等数学学习记录】函数的极限

一、知识点 (一)知识结构 #mermaid-svg-Dz0Ns0FflWSBWY50 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Dz0Ns0FflWSBWY50 .error-icon{fill:#552222;}#mermaid-svg-Dz0Ns0FflWSBWY50 .erro…

ROW_NUMBER

How to rewrite a query which uses the ROW_NUMBER() window function in versions 5.7 or earlier before window functions were supported e.g., SELECT ROW_NUMBER() OVER (PARTITION BY fieldA) AS rownum, myTable.* FROM myTable; index 用不上的 Solution Assuming…

保姆级手把手使用YOLOv11训练自己数据集(含源代码、网络结构、模型检测和转换 、数据集查找、模型训练)

文章目录 前言项目地址项目内容:网络模型结构性能测试任务描述任务内容 项目运行模型训练 前言 本教程内含YOLOv11网络结构图训练教程推理教程数据集获取等有关的内容~ 项目地址 YOLO11是Ultralytics YOLO系列实时目标检测器的最新迭代版本,它以尖端的…

打卡第三天 P5729 【深基5.例7】工艺品制作

今天是我打卡第三天&#xff0c;做个入门题吧(#^.^#) 原题链接&#xff1a;【深基5.例7】工艺品制作 - 洛谷 题目描述 输入格式 输出格式 输出一个整数表示答案。 输入输出样例 输入 #1 4 4 4 1 1 1 1 2 2 2 输出 #1 56 说明/提示 C&#xff1a; #include<bits/std…

使用 classification_report 评估 scikit-learn 中的分类模型

介绍 在机器学习领域&#xff0c;评估分类模型的性能至关重要。scikit-learn 是一个功能强大的 Python 机器学习工具&#xff0c;提供了多种模型评估工具。其中最有用的函数之一是 classification_report&#xff0c;它可以全面概述分类模型的关键指标。在这篇文章中&#xff…

低组装滚珠导轨:承载力强,适应多样工况!

在自动化行业中&#xff0c;高质量、高效率的生产线是确保产品品质和生产效率的关键。而低组装型滚珠导轨作为生产线中的重要组件之一&#xff0c;能够提供精准的直线运动控制&#xff0c;为自动化设备的稳定运行和高精度检测提供可靠支持。 相对于传统的导轨系统来说&#xff…

汇编语言笔记2

7.MASM,NASM,ATT,ARM的介绍 MASM:Windows下编译汇编指令的软件,可以在DOSBox下运行 NASM:优化版的MASM,主要用于Linux操作系统 ATT:Linux默认的汇编风格(但不友好) ARM:非PC(IOT设备)的汇编,比如写51单片机打开keil4的界面可以看到ARM 8.汇编 C语言 C 之间的关系 发展历程…

Arduino UNO R3自学笔记21 之 Arduino电机的闭环控制

注意&#xff1a;学习和写作过程中&#xff0c;部分资料搜集于互联网&#xff0c;如有侵权请联系删除。 前言&#xff1a;上篇写了电机速度测定&#xff0c;这篇主要是讲测定出的速度用于反馈&#xff0c;使得实际速度快速响应到需要的速度。 1.控制系统介绍 分2大类&#x…

《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析

目录 一、透视变换 1、什么是透视变换 2、操作步骤 1&#xff09;选择透视变换的源图像和目标图像 2&#xff09;确定透视变换所需的关键点 3&#xff09;计算透视变换的变换矩阵 4&#xff09;对源图像进行透视变换 5&#xff09;对变换后的图像进行插值处理 二、轮廓检测…

idea插件市场安装没反应

https://plugins.jetbrains.com/idea重启后还是不行那就

Docker:安装 MongoDB 的详细指南

请关注微信公众号&#xff1a;拾荒的小海螺 博客地址&#xff1a;http://lsk-ww.cn/ 1、简述 MongoDB 是一个流行的 NoSQL 数据库&#xff0c;可以在 Docker 容器中轻松安装和运行。本文将介绍如何在 Docker 中安装 MongoDB&#xff0c;并展示如何在 Java 应用中使用 MongoDB…

kafka发送消费核心参数与设计原理详解

核心参数详解&#xff1a; 发送端参数&#xff1a; 发送方式&#xff1a;默认值一般都是1: 重试参数 &#xff1a; 批量参数&#xff1a; 消费端参数&#xff1a; 自动提交参数&#xff1a; 如果是false&#xff0c;就是说消费完后不提交位移。也就是说比如之前消费的1-5.…

Qt教程(002):Qt项目创建于框架介绍

二、创建Qt项目 2.1 创建项目 【1、New Project】 【2、选择Qt Widgets Application】 【3、设置项目名称和保存路径】 注意&#xff0c;项目名称和路径不要带中文。 【4、选择QWidget】 带菜单栏的窗口QMainWindow空白窗口QWidget对话框窗口QDialog 【5、编译】 2.2 项目框…