注意力机制详解

引言 

在阅读一篇文章时,我们的大脑并不平等地处理每一个字词,而是根据上下文自动筛选出核心信息进行深入理解。注意力机制正是借鉴了这一生物学灵感,使得机器学习模型能够动态地分配其“注意力”资源,针对不同的输入部分赋予不同的重视程度,从而在纷繁复杂的数据中捕捉到最相关的特征。

从Transformer架构的横空出世,到BERT等预训练语言模型的惊艳表现,注意力机制已经成为推动自然语言处理乃至整个AI领域迅猛发展的核心驱动力之一。它不仅解决了长距离依赖问题,还使得模型能够更加灵活和高效地学习,即便是面对高度变异性或结构复杂的数据也能游刃有余。

注意力机制介绍 

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

它需要三个指定的输入Q(query), K(key), V(value), 然后通过计算公式得到注意力的结果, 这个结果代表query在key和value作用下的注意力表示. 当输入的Q=K=V时, 称作自注意力计算规则。

常见的注意力计算规则 

  • 将Q,K进行纵轴拼接, 做一次线性变化, 再使用softmax处理获得结果最后与V做张量乘法.Attention(Q,K,V)=Softmax(Linear([Q,K]))⋅V

  • 将Q,K进行纵轴拼接, 做一次线性变化后再使用tanh函数激活, 然后再进行内部求和, 最后使用softmax处理获得结果再与V做张量法.Attention(Q,K,V)=Softmax(sum(tanh(Linear([Q,K]))))⋅V

  • 将Q与K的转置做点积运算, 然后除以一个缩放系数, 再使用softmax处理获得结果最后与V做张量乘法.Attention(Q,K,V)=Softmax(Q⋅KT / √dk)⋅V

  • 说明:当注意力权重矩阵和V都是三维张量且第一维代表为batch条数时, 则做bmm运算.bmm是一种特殊的张量乘法运算

bmm运算演示:

# 如果参数1形状是(b × n × m), 参数2形状是(b × m × p), 则输出为(b × n × p)
>>> input = torch.randn(10, 3, 4)
>>> mat2 = torch.randn(10, 4, 5)
>>> res = torch.bmm(input, mat2)
>>> res.size()
torch.Size([10, 3, 5])

注意力机制是注意力计算规则能够应用的深度学习网络的载体, 同时包括一些必要的全连接层以及相关张量处理, 使其与应用网络融为一体. 使用自注意力计算规则的注意力机制称为自注意力机制,NLP领域中, 当前的注意力机制大多数应用于seq2seq架构, 即编码器和解码器模型。 

注意力机制实现步骤 

  • 第一步: 根据注意力计算规则, 对Q,K,V进行相应的计算.
  • 第二步: 根据第一步采用的计算方法, 如果是拼接方法,则需要将Q与第二步的计算结果再进行拼接, 如果是转置点积, 一般是自注意力, Q与V相同, 则不需要进行与Q的拼接.
  • 第三步: 最后为了使整个attention机制按照指定尺寸输出, 使用线性层作用在第二步的结果上做一个线性变换, 得到最终对Q的注意力表示
import torch
import torch.nn as nn
import torch.nn.functional as Fclass Attn(nn.Module):def __init__(self, query_size, key_size, value_size1, value_size2, output_size):"""初始化函数中的参数有5个, query_size代表query的最后一维大小key_size代表key的最后一维大小, value_size1代表value的导数第二维大小, value = (1, value_size1, value_size2)value_size2代表value的倒数第一维大小, output_size输出的最后一维大小"""super(Attn, self).__init__()# 将以下参数传入类中self.query_size = query_sizeself.key_size = key_sizeself.value_size1 = value_size1self.value_size2 = value_size2self.output_size = output_size# 初始化注意力机制实现第一步中需要的线性层.self.attn = nn.Linear(self.query_size + self.key_size, value_size1)# 初始化注意力机制实现第三步中需要的线性层.self.attn_combine = nn.Linear(self.query_size + value_size2, output_size)def forward(self, Q, K, V):"""forward函数的输入参数有三个, 分别是Q, K, V, 根据模型训练常识, 输入给Attion机制的张量一般情况都是三维张量, 因此这里也假设Q, K, V都是三维张量"""# 第一步, 按照计算规则进行计算, # 我们采用常见的第一种计算规则# 将Q,K进行纵轴拼接, 做一次线性变化, 最后使用softmax处理获得结果attn_weights = F.softmax(self.attn(torch.cat((Q[0], K[0]), 1)), dim=1)# 然后进行第一步的后半部分, 将得到的权重矩阵与V做矩阵乘法计算, # 当二者都是三维张量且第一维代表为batch条数时, 则做bmm运算attn_applied = torch.bmm(attn_weights.unsqueeze(0), V)# 之后进行第二步, 通过取[0]是用来降维, 根据第一步采用的计算方法, # 需要将Q与第一步的计算结果再进行拼接output = torch.cat((Q[0], attn_applied[0]), 1)# 最后是第三步, 使用线性层作用在第三步的结果上做一个线性变换并扩展维度,得到输出# 因为要保证输出也是三维张量, 因此使用unsqueeze(0)扩展维度output = self.attn_combine(output).unsqueeze(0)return output, attn_weights

 调用输出打印:

query_size = 32
key_size = 32
value_size1 = 32
value_size2 = 64
output_size = 64
attn = Attn(query_size, key_size, value_size1, value_size2, output_size)
Q = torch.randn(1,1,32)
K = torch.randn(1,1,32)
V = torch.randn(1,32,64)
out = attn(Q, K ,V)
print(out[0])
print(out[1])# tensor([[[ 0.5516, -0.3521, -0.3781,  0.3092,  0.1177, -0.0565,  0.1061,-0.4302, -0.6292,  0.0413,  0.0801,  0.2090,  0.2203, -0.1348,0.5017,  0.4179,  0.1984,  0.0271, -0.0231, -0.2771,  0.1479,-0.0940, -0.5132, -0.3395,  0.2101, -0.2790, -0.0369,  0.3575,0.3478, -0.2412,  0.0185,  0.3209, -0.0266, -0.1229,  0.1988,0.5011,  0.2373, -0.0945, -0.2623,  0.1937, -0.7264, -0.1000,0.0942, -0.7034,  0.0833,  0.0088, -0.1904,  0.5210,  0.8732,-0.1510,  0.2940, -0.3701,  0.4335,  0.3952, -0.1875,  0.0576,-0.0145,  0.2639,  0.4688,  0.0203,  0.2685,  0.2491, -0.5202,-0.3083]]], grad_fn=<UnsqueezeBackward0>)
tensor([[0.0215, 0.0283, 0.0376, 0.0398, 0.0245, 0.0393, 0.0443, 0.0188, 0.0355,0.0616, 0.0721, 0.0136, 0.1269, 0.0221, 0.0099, 0.0248, 0.0108, 0.0232,0.0203, 0.0316, 0.0235, 0.0168, 0.0599, 0.0156, 0.0204, 0.0257, 0.0128,0.0157, 0.0210, 0.0320, 0.0196, 0.0306]], grad_fn=<SoftmaxBackward0>)

注意力机制示意图

Attention机制的工作原理并不复杂,我们可以用下面这张图做一个总结

💥举个例子:

一张图片有树、时光塔、雪、人、路。

可能对于一开始我们会先注意到雪和时光塔,然后其次是树、人、路。

我们可以抽象的为其设置权重:90、80、50、50、20,这些权值就是k,这些元素就是Value。

然后给出一个词:生物,我们就会首先注意到人和树,其次是后三个元素,这时我们大脑已经把权重重新分配了,人和树的权重为:90、80。此时的'生物'就是q,即query。

Attention计算过程

  • 阶段一: query 和 key 进行相似度计算,得到一个query 和 key 相关性的分值
  • 阶段二: 将这个分值进行归一化(softmax),得到一个注意力的分布
  • 阶段三: 使用注意力分布和 value 进行计算,得到一个融合注意力的更好的 value 值

为了更好的说明上面的情况, 我们通过注意力来做一个机器翻译的任务,机器翻译中,我们会使用 seq2seq 的架构,每个时间步从词典里生成一个翻译的结果。

在没有注意力之前,我们每次都是根据 Encoder 部分的输出结果来进行生成,提出注意力后,就是想在生成翻译结果时并不是看 Encoder 中所有的输出结果,而是先来看看想生成的这部分和哪些单词可能关系会比较大,关系大的我多借鉴些;关系小的,少借鉴些。就是这样一个想法,我们看看该如何操作。 

Attention计算逻辑

当然,Attention 并不是只有这一种计算方式,后来还有很多人找到了各种各样的计算注意力的方法, 比如我们上面介绍的三种计算规则, 但是从本质上,它们都遵循着这个三步走的逻辑:

  • query 和 key 进行相似度计算,得到一个query 和 key 相关性的分值
  • 将这个分值进行归一化(softmax),得到一个注意力的分布
  • 使用注意力分布和 value 进行计算,得到一个融合注意力的更好的 value 值

有无attention模型对比

无attention机制的模型

文本处理领域的Encoder-Decoder框架可以这么直观地去理解:可以把它看作适合处理由一个句子(或篇章)生成另外一个句子(或篇章)的通用处理模型。对于句子对,我们的目标是给定输入句子Source,期待通过Encoder-Decoder框架来生成目标句子Target。Source和Target可以是同一种语言,也可以是两种不同的语言。而Source和Target分别由各自的单词序列构成:

encoder顾名思义就是对输入句子Source进行编码,将输入句子通过非线性变换转化为中间语义表示C:

对于解码器Decoder来说,其任务是根据句子Source的中间语义表示C和之前已经生成的历史信息,y_1, y_2…y_i-1来生成i时刻要生成的单词y_i

上述图中展示的Encoder-Decoder框架是没有体现出“注意力模型”的,所以可以把它看作是注意力不集中的分心模型。为什么说它注意力不集中呢?请观察下目标句子Target中每个单词的生成过程如下:

 

  • 💥其中f是Decoder的非线性变换函数。从这里可以看出,在生成目标句子的单词时,不论生成哪个单词,它们使用的输入句子Source的语义编码C都是一样的,没有任何区别。

  • 💥每个yi都依次这么产生,那么看起来就是整个系统根据输入句子Source生成了目标句子Target。如果Source是中文句子,Target是英文句子,那么这就是解决机器翻译问题的Encoder-Decoder框架;如果Source是一篇文章,Target是概括性的几句描述语句,那么这是文本摘要的Encoder-Decoder框架;如果Source是一句问句,Target是一句回答,那么这是问答系统或者对话机器人的Encoder-Decoder框架。由此可见,在文本处理领域,Encoder-Decoder的应用领域相当广泛。

问题点是: 语义编码C是由句子Source的每个单词经过Encoder 编码产生的,这意味着不论是生成哪个单词,还是,其实句子Source中任意单词对生成某个目标单词yi来说影响力都是相同的,这是为何说这个模型没有体现出注意力的缘由。这类似于人类看到眼前的画面,但是眼中却没有注意焦点一样。

有attention机制的模型

💯如果拿机器翻译来解释这个分心模型的Encoder-Decoder框架更好理解,比如输入的是英文句子:Tom chase Jerry,Encoder-Decoder框架逐步生成中文单词:“汤姆”,“追逐”,“杰瑞”。在翻译“杰瑞”这个中文单词的时候,分心模型里面的每个英文单词对于翻译目标单词“杰瑞”贡献是相同的,很明显这里不太合理,显然“Jerry”对于翻译成“杰瑞”更重要,但是分心模型是无法体现这一点的,这就是为何说它没有引入注意力的原因。

💦没有引入注意力的模型在输入句子比较短的时候问题不大,但是如果输入句子比较长,此时所有语义完全通过一个中间语义向量来表示,单词自身的信息已经消失,可想而知会丢失很多细节信息,这也是为何要引入注意力模型的重要原因。

💦上面的例子中,如果引入Attention模型的话,应该在翻译“杰瑞”的时候,体现出英文单词对于翻译当前中文单词不同的影响程度,比如给出类似下面一个概率分布值:(Tom,0.3)(Chase,0.2) (Jerry,0.5).每个英文单词的概率代表了翻译当前单词“杰瑞”时,注意力分配模型分配给不同英文单词的注意力大小。这对于正确翻译目标语单词肯定是有帮助的,因为引入了新的信息。

同理,目标句子中的每个单词都应该学会其对应的源语句子中单词的注意力分配概率信息。这意味着在生成每个单词的时候,原先都是相同的中间语义表示C会被替换成根据当前生成单词而不断变化的。理解Attention模型的关键就是这里,即由固定的中间语义表示C换成了根据当前输出单词来调整成加入注意力模型的变化的。

生成目标句子单词的过程成了下面的形式:

而每个Ci可能对应着不同的源语句子单词的注意力分配概率分布,比如对于上面的英汉翻译来说,其对应的信息如下:

💥f2函数代表Encoder对输入英文单词的某种变换函数,比如如果Encoder是用的RNN模型的话,这个f2函数的结果往往是某个时刻输入后隐层节点的状态值;g代表Encoder根据单词的中间表示合成整个句子中间语义表示的变换函数,一般的做法中,g函数就是对构成元素加权求和。

  • Lx代表输入句子source的长度, a_ij代表在Target输出第i个单词时source输入句子中的第j个单词的注意力分配系数, 而hj则是source输入句子中第j个单词的语义编码, 假设Ci下标i就是上面例子所说的'汤姆', 那么Lx就是3, h1=f('Tom'), h2=f('Chase'),h3=f('jerry')分别输入句子每个单词的语义编码, 对应的注意力模型权值则分别是0.6, 0.2, 0.2, 所以g函数本质上就是加权求和函数, 如果形象表示的话, 翻译中文单词'汤姆'的时候, 数学公式对应的中间语义表示Ci的形成过程类似下图:

Self-attention介绍 

Self-attention就本质上是一种特殊的attention。这种应用在transformer中最重要的结构之一。前面我们介绍了attention机制,它能够帮我们找到子序列和全局的attention的关系,也就是找到权重值𝑤𝑖。Self-attention向对于attention的变化,其实就是寻找权重值的𝑤𝑖过程不同。

为了能够产生输出的向量𝑦𝑖 ,self-attention其实是对所有的输入做了一个加权平均的操作,这个公式和上面的attention是一致的。 

  • 𝑗代表整个序列的长度,并且j𝑗个权重的相加之和等于1。值得一提的是,这里的 wij𝑤𝑖𝑗并不是一个需要神经网络学习的参数,它是来源于𝑥𝑖和𝑥𝑗的之间的计算的结果(这里𝑤𝑖𝑗的计算发生了变化)。它们之间最简单的一种计算方式,就是使用点积的方式。

Self-attention和Attention使用方法 

  • 在神经网络中,通常来说你会有输入层(input),应用激活函数后的输出层(output),在RNN当中你会有状态(state)。如果attention (AT) 被应用在某一层的话,它更多的是被应用在输出或者是状态层上,而当我们使用self-attention(SA),这种注意力的机制更多的实在关注input上。
  • Attention (AT) 经常被应用在从编码器(encoder)转换到解码器(decoder)。比如说,解码器的神经元会接受一些AT从编码层生成的输入信息。在这种情况下,AT连接的是**两个不同的组件**(component),编码器和解码器。但是如果我们用**SA**,它就不是关注的两个组件,它只是在关注你应用的**那一个组件**。那这里他就不会去关注解码器了,就比如说在Bert中,使用的情况,我们就没有解码器。
  • SA可以在一个模型当中被多次的、独立的使用(比如说在Transformer中,使用了18次;在Bert当中使用12次)。但是,AT在一个模型当中经常只是被使用一次,并且起到连接两个组件的作用。
  • SA比较擅长在一个序列当中,寻找不同部分之间的关系。比如说,在词法分析的过程中,能够帮助去理解不同词之间的关系。AT却更擅长寻找两个序列之间的关系,比如说在翻译任务当中,原始的文本和翻译后的文本。这里也要注意,在翻译任务重,SA也很擅长,比如说Transformer。
  • AT可以连接两种不同的模态,比如说图片和文字。SA更多的是被应用在同一种模态上,但是如果一定要使用SA来做的话,也可以将不同的模态组合成一个序列,再使用SA。

Self-attetion实现步骤 

self-attention机制的实现步骤:

  • 第一步: 准备输入
  • 第二步: 初始化参数
  • 第三步: 获取key,query和value
  • 第四步: 给input1计算attention score
  • 第五步: 计算softmax
  • 第六步: 给value乘上score
  • 第七步: 给value加权求和获取output1
  • 第八步: 重复步骤4-7,获取output2,output3
# 这里我们随机设置三个输入, 每个输入的维度是一个4维向量
import torch
x = [[1, 0, 1, 0], # Input 1[0, 2, 0, 2], # Input 2[1, 1, 1, 1]  # Input 3
]
x = torch.tensor(x, dtype=torch.float32)

 初始化参数

# 每一个输入都有三个表示,分别为key(橙黄色)query(红色)value(紫色)。比如说,每一个表示我们希望是一个3维的向量。由于输入是4维,所以我们的参数矩阵为 4*3 维。# 为了能够获取这些表示,每一个输入(绿色)要和key,query和value相乘,在例子中,我们使用如下的方式初始化这些参数。
w_key = [[0, 0, 1],[1, 1, 0],[0, 1, 0],[1, 1, 0]
]
w_query = [[1, 0, 1],[1, 0, 0],[0, 0, 1],[0, 1, 1]
]
w_value = [[0, 2, 0],[0, 3, 0],[1, 0, 3],[1, 1, 0]
]
w_key = torch.tensor(w_key, dtype=torch.float32)
w_query = torch.tensor(w_query, dtype=torch.float32)
w_value = torch.tensor(w_value, dtype=torch.float32)print("w_key: \n", w_key)
print("w_query: \n", w_query)
print("w_value: \n", w_value)

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

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

相关文章

大数据信用报告分析和评估有什么意义

大数据信用这个词在现在已经是很常见的了&#xff0c;只要是申贷的朋友对它就不陌生&#xff0c;在明面上的信用资质刚刚满足审核要求&#xff0c;但又要把控风险的时候&#xff0c;这个时候大数据信用就会作为风控机构交叉核查的重要依据。那你知道大数据信用报告分析和评估有…

代码随想录——二叉搜索树的最小绝对差(Leetcode530)

题目链接 层序遍历 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) …

if constexpr实现条件编译

#include <iostream>// 利用if constexpr实现了条件编译 template<typename T1, typename T2> void test_func() {if constexpr (std::is_same_v<T1, T2>) {std::cout << "hit stage\n";} else {std::cout << "miss\n";} }i…

Microsoft的Copilot现已登陆Telegram

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

数据结构复习指导之插入排序

文章目录 排序 考纲内容 知识框架 复习提示 1.排序的基本概念 1.1排序的定义 2.插入排序 2.1直接插入排序 2.2折半插入排序 2.3希尔排序 知识回顾 排序 考纲内容 &#xff08;一&#xff09;排序的基本概念 &#xff08;二&#xff09;插入排序 直接插…

内网不能访问域名怎么办?

在网络应用中&#xff0c;我们常常遇到内网不能访问域名的问题。这是由于内网环境限制导致的&#xff0c;内网无法直接连接到公网&#xff0c;因而无法访问互联网上的域名。我们可以利用一些特殊技术和工具来解决这个问题。 天联组网技术的应用 天联组网是一种非常受欢迎的解决…

NetApp财季报告亮点:全闪存阵列需求强劲,云计算收入增长放缓但AI领域前景乐观

在最新的财季报告中&#xff0c;NetApp的收入因全闪存阵列的强劲需求而显著增长。截至2024年4月26日的2024财年第四季度&#xff0c;NetApp的收入连续第三个季度上升&#xff0c;达到了16.7亿美元&#xff0c;较前一年同期增长6%&#xff0c;超出公司指导中值。净利润为2.91亿美…

前端开发:$nextTick()的使用及原理

目录 前言 $nextTick()的概念 $nextTick()的用法和原理 1、$nextTick()用法 2、$nextTick()原理 $nextTick()的具体使用示例 拓展&#xff1a;面试中考察$nextTick()的底层原理 最后 前言 在前端开发中&#xff0c;涉及到JS原生的使用原理是非常重要的知识点&#xff0…

使用pytorch搭建textCNN、BERT、transformer进行文本分类

首先展示数据处理后的类型&#xff1a; 第一列为文本&#xff0c;第二类为标注的标签&#xff0c;数据保存在xlsx的表格中&#xff0c;分为训练集和验证集。 textCNN 直接上整个工程代码&#xff1a; import pandas as pd import numpy as np import torch from torch.util…

c++函数基础总结

在给出的代码片段中&#xff0c;我们看到两部分内容&#xff1a;一个类定义和一个全局函数声明。让我们逐一分析它们&#xff1a; 类定义&#xff1a; cpp复制代码 class { public: void a(); }; 这个类定义是不完整的&#xff0c;因为它没有类名。但为了说明&#xff0c;我…

Linux开发工具(个人使用)

Linux开发工具 1.Linux yum软件包管理器1.1Linux安装程序有三种方式1.2注意事项1.3如何查看&#xff0c;安装&#xff0c;卸载软件包1.3.1查看软件包1.3.2安装软件包1.3.3卸载软件 2.Linux vim编辑器2.1vim的基本操作2.2vim正常模式命令集2.3vim底行模式命令集2.4vim配置 3.Lin…

如何设置eclipse中web.xml 文件的地址

新学了一个项目 &#xff0c;项目结构与平常自己构建的web项目不同 &#xff0c;用eclipse打开之后&#xff0c;eclipse竟然自己创建了一个web.xml 而项目里面原本的web.xml 文件eclipse没有识别出来&#xff0c;导致后来浏览器访问任何路径都报错404 一、修改项目中web.xml的…

Centos7.9环境下安装Keepalived(亲测版)

目录 一、在线安装 二、离线安装 (1)、 下载 (2)、安装依赖包 (3)、解压文件 (4)、编译 (4.1)、进入 keepalived-2.2.8 目录中 (4.2)、安装Keepalived (5)、配置文件修改 (6)、启动 (7)、检查启动状态 (8)、 设置开机自启 (9)、配置从节点 (10)、启动从节点keepalived…

vue3中实现鼠标点击后出现点击特效

一、效果展示 图片下方为效果体验地址 缓若江海凝清光 二、代码 js中&#xff1a; <script setup lang"ts"> window.addEventListener("click", (e: MouseEvent) > {const pointer document.createElement("div");pointer.classLi…

数模混合芯片之可靠性设计

一、可靠性设计目的 数模混合芯片设计之所以需要可靠性设计&#xff0c;主要原因有以下几点&#xff1a; 工艺与环境影响&#xff1a; 半导体制造工艺存在着不可避免的随机和系统性偏差&#xff0c;这可能导致芯片内部的模拟电路和数字电路参数发生变化&#xff0c;影响性能…

CobaltStrike基本渗透

目录 CobaltStrike简介 主要功能&#xff1a; 使用注意&#xff1a; 在使用CobaltStrike进行渗透测试时&#xff0c;务必遵守法律法规&#xff0c;并获得合法授权。 CobaltStrike安装 前提 安装 服务端安装 windows安装 CS基本使用 监听器配置 一些基本的攻击…

算法(十四)动态规划

算法概念 动态规划&#xff08;Dynamic Programming&#xff09;是一种分阶段求解的算法思想&#xff0c;通过拆分问题&#xff0c;定义问题状态和状态之间的关系&#xff0c;使得问题能够以递推&#xff08;分治&#xff09;的方式去解决。动态规划中有三个重点概念&#xff…

【监控】prometheus自定义指标 exporter

一、【写在前面】 prometheus自定义指标本质是用代码自己写一个网络访问的采集器&#xff0c;你可以在官网看到&#xff0c;Client libraries | Prometheus官方支持的语言有GO JAVA PYTHON RUBY RUST, 第三方的库就支持的更多了&#xff0c;有BASH C CPP LUA C# JS PHP R PER…

智慧医院物联网建设-统一管理物联网终端及应用

近年来&#xff0c;国家卫健委相继出台的政策和评估标准体系中&#xff0c;都涵盖了强化物联网建设的内容。物联网建设已成为智慧医院建设的核心议题之一。 作为医院高质量发展的关键驱动力&#xff0c;物联网的顶层设计与网络架构设计规划&#xff0c;既需要结合现代信息技术的…

Python3位运算符

前言 本文介绍的是位运算符&#xff0c;位运算可以理解成对二进制数字上的每一个位进行操作的运算&#xff0c;位运算分为 布尔位运算符 和 移位位运算符。 文章目录 前言一、位运算概览1、布尔位运算符1&#xff09;按位与运算符 ( & )2&#xff09;按位或运算符 ( | )3…