图解 BERT 模型

节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学.

针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。

汇总合集:《大模型面试宝典》(2024版) 发布!


《Attention is All You Need》发表于 2017 年,2018 年 Google AI Language 团队发表了论文《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》,提出了 Bert(Bidirectional Encoder Representations from Transformers)架构。

BERT 实际基于 Transformer 的编码器部分,如若大家理解了前述 Transformer 系列文章,那么再学习 BERT 会很容易理解。

这次依然尝试使用图解的方式介绍 BERT。文章一部分及配图参考了 Rahul Agarwal 在 Medium 上的文章及原始论文,建议收藏、关注、点赞,无论实战还是面试都是常考热点。

一、BERT 概览

简单来说,BERT 是一种可用于问题解答、分类、NER 等大量 NLP 下游任务的架构。可将预训练后的 BERT 视为一个黑盒。

BERT 有两个主要版本:

  • BERT Base:12层 Transformer 编码器,隐藏层大小为768,12个自注意头,总参数量约为1.1亿。

  • BERT Large:24层 Transformer 编码器,隐藏层大小为1024,16个自注意头,总参数量约为3.4亿。

BERT Base 版本的 BERT 为例,它能将输入中的每个 Token 转化为一个 H = 768 的向量。与 Transformer 相同,BERT 的输入序列可以是一个单独的句子,也可以是一对由分隔符 [SEP] 标记分隔,以开始符 [CLS] 标记开始的句子。

图片

二、BERT 解决什么问题

如果各位小伙伴对 Imagenet 有所了解,那么也会很容易理解 BERT 的预训练过程。

图片

ImageNet 是一个大型图像数据库,包含了数百万个带标签的图像。CV 模型在这个数据集上进行预训练,以学习图像特征;预训练完成后,对于具体图像任务,可以通过在较小的数据集上,微调模型最后几层来适应特定任务。前几年流行的 ResNet 和 VGG 等深度学习模型最初都是在 ImageNet 数据集上进行预训练的。

BERT 模型工作原理与使用 Imagenet 进行训练的大多数 CV 模型类似。首先,在大型语料库上训练 BERT 模型,然后通过在最后添加一些额外的层,针对具体的 NLP 任务(如分类、问题解答、NER 等)对模型进行微调。

例如,先在维基百科这样的语料库上训练 BERT(屏蔽 LM 任务),然后再用特定的数据对模型进行微调,以完成分类任务,诸如通过添加一些额外的层,将评论分为负面、正面或中性等方式。实际上,我们只是使用 [CLS] 标记的输出来完成分类任务。

如下图所示的微调过程,通过添加线性层和 Softmax 层,对 [cls] Token 进行分类输出。

图片

具体来说, 对 BERT 输出的 [cls] Token 使用矩阵乘法作变换。假设我们的分类数是 3,那么 [cls] Token 向量的维度是(1×768),引入的 W 矩阵的形状为( H × num_classes = 768 × 3), [cls] Token 代表的矩阵与 W 矩阵相乘,得到一个(1×3)的矩阵,这个矩阵再通过 Softmax 得到每个类别的概率,然后计算交叉熵损失。

当然,也可以通过在最后一层获取句子特征,然后再输出到 Softmax;或者可以取所有输出的平均值,然后再通过 Softmax。方式有多种,哪种最有效取决于任务的数据。

三、从嵌入的角度看 BERT

从嵌入的角度来看,BERT 的预训练为我们提供了上下文双向嵌入。

1. 上下文 Contextual:

词的嵌入不是固定的,它们依赖于周围的词语。在前序《图解 Transformer》序列文章就详细介绍过这个概念。比如,在“one bird was flying below another bird”这句话中,“bird”这个词的两个嵌入会有所不同。

2. 双向 Bi-Directional:

图片

LSTM 按顺序读取文本输入(从左到右或从右到左),而 Transformer 的编码器则是一次性读取整个单词序列,因此被认为是双向的(注意,Transformer 模型的解码器部分通常是单向的)。因此,对于“BERT model is awesome.”这样的句子,“model”这个词的嵌入会包含“BERT”、“awesome”和“is”所有词的上下文。

四、BERT 工作的具体流程

接下来从“架构-Architecture 、输入-Input、训练-Training”三个部分介绍 BERT 的具体工作流程。

1. Architecture

如果你对 Transformers 已经有所了解,那么 BERT 的架构非常容易理解。BERT 基本上是由我们非常熟悉的Transformers 中的编码器堆栈(Encoder Stacks)组成的。

图片

原始论文中,作者实验了两种模型,即我们在开头也提到过的 BERT Base 与 BERT Large 两种架构。

2. Training Input

我们使用下图中的输入结构向 BERT 提供输入。输入由(两个句子+两个特殊的 Token)构成。两个特殊的 token是 [CLS]和[SEP] token。

图片

例如,对于两个句子“my dog is cute”和“he likes playing”,BERT 首先使用 WordPiece 分词将序列转换为Token,并在开头添加[CLS] Token,在第二个句子的开头和结尾添加[SEP] Token,因此输入是:

图片

在 BERT 中使用的 WordPiece 分词方法会将单词如 playing 分解成“play”和“##ing”。对于为什么使用 WordPiece 这种方式,我们后面再详细介绍。

BERT 的每个 token 的嵌入由 Token Embeddings、Position Embeddings、Segment Embeddings 三种嵌入向量进行表示:

Token Embedding(词嵌入): 通过在一个大小为 30000x768(H) 的词表矩阵中查找,来获取 Token 嵌入。这里,30000 是WordPiece 分词后的词汇表长度。这个矩阵所代表的权重将在训练过程中学习。

图片

Segment Embedding(段落嵌入): 对于知识问答等任务,我们需要指定这个句子是来自哪个段落。如果嵌入来自第一个句子,这些嵌入是长度为H的全0向量;如果嵌入来自第二个句子,则为全1向量。

图片

位置嵌入(位置嵌入):这些嵌入用于指定单词在序列中的位置,和 Transformer 中所做的一样。位置矩阵的列数为768,矩阵的第一行是[CLS] Token的嵌入,第二行是单词“my”的嵌入,第三行是单词“dog”的嵌入,以此类推。

图片

给BERT的最终输入是 Token Embeddings、Segment Embeddings、Position Embeddings的叠加(Token Embeddings + Segment Embeddings + Position Embeddings)。

3. 训练遮蔽语言模型(Masked LM)

这部分是 BERT 最有趣的地方。我们将通过各种架构尝试并发现每种尝试的缺陷,以此来解释这些概念,并形成 BERT的最终架构。

尝试1:例如,如果我们按如下方法设置 BERT 训练,即预测输入序列的每个单词。

图片

这种方法的问题在于学习任务过于简单。网络提前就知道它要预测什么,因此可以轻松地学习权重以达到100%的分类准确率。

注意:这里的“预测-Predict”与 Transformer 解码器中基于已经生成的单词,预测下一个单词的“预测”的含义略微不同。这里的“预测-Predict”是“生成-Generation”的意思。这里使用“Predict”这个词,是表达在 Masked LM 模型中,模型根据上下文信息推断被掩蔽 token 的过程。虽然“生成”也可以理解为一种预测,但在NLP术语中,“生成”通常指的是更广泛的内容创建,而不是特定位置 token 的推断。下面几种方法中提到的“预测”一词也是这样的含义。

尝试2:遮蔽语言模型(Masked LM)。原论文中尝试使用此方法克服上述问题。在每个训练输入序列中随机遮蔽15%的单词,并仅预测这些单词的输出。

图片

此种方式计算损失时只针对屏蔽的单词。模型学会了预测它未见过的单词,同时还能看到这些单词周围的上下文。(注意,图中屏蔽了 3 个单词,实际上应该只屏蔽 1 个单词,因为这个示例中,8 个单词的 15% 就是 1 个单词。)

但这种方式的造成了模型在“预训练-微调”两个过程的不匹配问题。

具体来说,在预训练阶段,模型需要根据上下文预测被遮蔽的 token,因此模型会更多地依赖上下文信息来填补空白。但在微调阶段,模型直接处理完整的句子,输入方式不同可能会导致模型的预测行为与预训练阶段存在偏差。另外,在预训练时模型通过预测被掩蔽的token来学习语言的结构和语义,但在微调阶段,模型的目标通常是根据完整输入直接进行分类或预测,这种目标上的差异可能导致模型在微调时需要重新调整。

尝试3:使用随机单词的遮蔽语言模型:

在这个尝试中,仍然会遮蔽15%的位置。但会用随机单词替换那些被遮蔽标记中的20%。这样做是为了让模型知道,即使单词不是[MASK]标记,我们仍然需要输出一些结果。因此,如果我们有一个长度为500的序列,我们将遮蔽75个标记(500的15%),在这75个标记中,有15个标记(75的20%)将被随机单词替换。示意图如下:

图片

这种方式的优点在于,网络仍然可以处理任何单词。

但其问题在于,模型会学到一种错误模式,即看到随机替换的单词时,这些单词永远不会是正确的输出。比如对于我们的例子,将“likes”随机替换为“eats”,而我们在这个位置需要的输出为“likes”,模型会学习到“eats”的输出永远不会是“eats”。而在不同的上下文中,比如输入“he eats bread”,需要的输出中包含“eats”。

尝试4:使用随机单词和未遮蔽单词的遮蔽语言模型

为了解决这个问题,作者提出了以下训练设置。

在训练数据中随机选择 15% 的 token 位置进行预测。这些随机选择的 token 中,80%替换为[MASK]标记,10%随机替换为词汇表中的其他 token,10% 保持不变。

如果我们有一个长度为 500 的序列,我们将遮蔽75个 token(500的15%),在这75个 token中,7个 token(75的10%)将被随机 token 替换,7个 token(75的10%)保持不变。示意如下:

图片

这样就有了最佳设置,模型不会学习到不良模式。

4. 训练附加的下一句预测任务(NSP)

BERT 模型在训练过程中还有另一个并行的于 Masked LM 的训练任务,这个任务称为下一句预测(Next Sentence Prediction, NSP)。在创建训练数据时,我们为每个训练样本选择句子A和B,其中50%的情况下B是实际紧跟在A后的句子(标记为IsNext),而另外50%的情况下B是语料库中的一个随机句子(标记为NotNext)。然后我们使用[CLS]标记的输出来计算损失,这个损失也会通过网络反向传播来调整权重。

摘自 BERT 论文原文:许多重要的下游任务,如问答(QA)和自然语言推理(NLI),都基于两个句子之间的关系,而这种关系不是通过语言模型直接捕捉到的。为了训练一个能够理解句子关系的模型,我们进行了一种二元化的下一句预测任务(binarized next sentence prediction task)的预训练,这个任务可以从任何单语语料库中轻松生成。

图片

现在我们有了预训练的BERT模型,它可以为我们提供上下文嵌入。那么如何将它用于各种任务呢?

五、针对具体任务进行微调

如前所述,我们可以在 [CLS] 输出上添加几层并微调权重,然后使用BERT进行分类任务。

图片

以下是论文中介绍的 BERT 用于其他任务的方法:

图片

让我们逐一浏览这些任务:

1. 句子对分类任务:这与分类任务非常相似。即在大小为768的[CLS]输出上添加一个线性层和一个Softmax层(Linear + Softmax)。

2. 单句分类任务:与句子对分类任务相同。

4. 单句标注任务:与训练 BERT 时的设置非常相似,只是我们需要为单句中的每个 Token 进行标注。如对于词性标注任务(如预测名词、动词或形容词),我们只需添加一个大小为(768 x n_outputs)的线性层,并在上面添加一个Softmax层进行预测。

3. 问答任务——这个任务中,我们给出一个问题和一个包含答案的段落:目标是确定答案在段落中的起始和结束位置。

六、问答任务详细工作流程

BERT 执行问答任务的原理与 GPT 等以自回归生成答案的模型不同。以下是关于 BERT 在执行问答任务时的详细流程:

1. 输入序列

输入序列由问题和段落拼接而成,并添加特殊标记:

[CLS] 问题 [SEP] 段落 [SEP]

2. BERT模型输出

输入序列通过 BERT 模型处理,生成每个 token 的上下文表示。假设输入序列长度为 𝐿,隐藏层维度为 𝐷,则BERT 的输出表示为一个矩阵 𝐻,其形状为 𝐿×𝐷。

3. 定义向量 𝑆 和 𝐸

向量 𝑆 和 𝐸 是在微调过程中学习的参数,用于分别预测起始位置和结束位置的分数。若隐藏层维度 𝐷=768,则 𝑆 和 𝐸的形状均为 1×768。

4. 计算分数

对于每个 token 的表示向量 ℎ𝑖(BERT的输出),计算其作为答案起始位置和结束位置的分数。具体计算方式向量每个 ℎ𝑖 分别与 𝑆 和 𝐸 向量的装置进行点积(内积),其结果为一个标量:

图片

图片

5. 将分数通过 Softmax 函数转换为概率分布

图片

6. 选择最可能的起始和结束位置

  • 确定起始和结束位置:根据计算出的起始位置概率分布 𝑃𝑠 和结束位置概率分布 𝑃𝑒,选择概率最高的token 作为答案的起始和结束位置。具体做法是找到使 𝑃𝑠 和 𝑃𝑒 最大的索引位置:

图片

  • 确定答案范围:确保起始位置 𝑦𝑠在结束位置 𝑦𝑒 之前,即 𝑦𝑠≤𝑦𝑒。如果需要,可以在推理过程中应用额外的逻辑来处理不合逻辑的预测结果(例如,设置一个最大答案长度)。

7. 提取答案

根据确定的起始和结束位置,从输入序列中的段落部分提取对应的token序列,拼接成最终答案。

8. 训练时的损失计算

问答任务训练的目标是最大化正确起始位置和结束位置的对数似然之和。假设真实的起始位置和结束位置分别为 𝑦𝑠 和 𝑦𝑒,则损失函数(负对数似然)为:

图片

总损失函数为:

图片

对比 BERT,GPT 在处理问答型任务时,使用自回归方式生成答案,即逐步预测每个 token,基于前面的token生成下一个token,直到生成结束标记或达到预设的最大长度。

七、WordPiece 技术与词嵌入方法的差异

前边我们遗留了一个问题,即 WordPiece 和词嵌入技术方面的差异。以下是二者差异的详细介绍:

1. 原始 Transformer 模型的词嵌入

词汇表:原始的 Transformer 模型通常使用一个固定的词汇表,词汇表中的每个单词都被映射到一个固定长度的向量(词嵌入)。

词嵌入矩阵:在 Transformer 模型中,有一个词嵌入矩阵,用于将输入单词转换为对应的向量表示。

完整单词表示:原始 Transformer 模型中的词嵌入通常是基于完整单词的,也就是说,每个单词在词汇表中都有一个对应的向量。

2. BERT 的 tokenization 技术

词片(WordPiece)嵌入:BERT使用的是一种称为 WordPiece 的子词级别的 tokenization方法。这种方法将单词拆分成更小的子词单元(词片),这些子词单元构成了模型的词汇表。

更小的词汇表:由于使用了子词级别的 tokenization,BERT 的词汇表比基于完整单词的词汇表要小得多。这种方法可以有效处理词汇量大的问题,减少OOV(out-of-vocabulary,词表外词)的情况。

处理未知单词:对于不在词汇表中的单词,BERT 可以通过拆分成已知的子词单元来表示,从而更好地处理未知单词和新词。

词嵌入矩阵:与原始 Transformer 类似,BERT 也有一个词嵌入矩阵,但它是基于子词单元的。每个子词单元都有一个对应的向量表示,这些向量组合在一起构成单词的表示。

3. 示例对比:

输入句子:“Playing football is enjoyable.”

原始 Transformer 模型:

Tokenization结果

[“Playing”, “football”, “is”, “enjoyable”]

词嵌入向量

embedding(“Playing”),embedding(“football”),embedding(“is”),embedding(“enjoyable”),每个单词直接作为一个token处理,模型依赖于词汇表中存在的完整单词。

BERT 模型:

Tokenization结果

[“Play”, “##ing”, “foot”, “##ball”, “is”, “enjoy”, “##able”]

词嵌入向****量

embedding(“Play”),embedding(“##ing”),embedding(“foot”),embedding(“##ball”),embedding(“is”),embedding(“enjoy”),embedding(“##able”)

八、总结

用最简单的话语概括 BERT 的重要思想

自己总结的:

1.BERT 模型架构利用 Transformer 编码器堆栈结构,是一种能进行文本双向嵌入的语言模型。

2.BERT的 tokenization 采用的是 WordPiece 的方式,Embedding 是 Token Embeddings、Segment Embeddings、Position Embeddings 三者的叠加。

3.BERT 使用“预训练+微调”的方式用于分类、问答、NER 等 NLP 下游任务;预训练采用的是 “MLM+NSP”双任务并行的方式,使用 MLM、NSP 损失的加权和作为总损失进行反向传播;微调时仅需在预训练后的 BERT 模型上增加一个输出层,对此输出层进行微调。

chatgpt-4o总结的:

1. 模型架构
  • Transformer编码器:BERT使用多层的 Transformer 编码器堆栈,每层包含多头自注意力机制和前馈神经网络。这个架构使得 BERT 能够有效地捕捉输入序列中的复杂依赖关系。

  • 双向性:BERT是双向的(Bidirectional),这意味着它在训练时能够同时从左到右和从右到左看待上下文。与传统的单向语言模型不同,这种双向性使得BERT能够更好地理解句子的上下文。

2. Tokenization 和 Embeddings
  • WordPiece Tokenization:BERT 使用 WordPiece 分词方法,将单词拆分为更小的子词或字符片段,以处理未见过的词和稀有词。这样可以更好地覆盖语言中的各种词汇。

  • 三种嵌入:Token Embeddings,将每个 token 映射到一个固定维度的向量;Position Embeddings,添加位置嵌入,以表示每个token在序列中的位置,从而保留顺序信息;Segment Embeddings,用于区分不同的句子,特别是在句子对任务中,通过添加句子A和句子B的嵌入来区分它们。

3. 预训练任务
  • 掩蔽语言模型(Masked Language Model, MLM):在输入序列中随机掩蔽15%的token,然后让模型预测这些被掩蔽的token。这种方法使模型能够在双向上下文中学习每个token的表示。

  • 下一句预测(Next Sentence Prediction, NSP):训练模型判断两个句子是否在原始文本中是连续的句子。输入由两个句子组成,50%的情况下它们是连续的,50%的情况下它们是随机选择的不连续句子。这有助于模型理解句子间的关系。

4. 预训练和微调策略
  • 预训练:在大规模无标签文本数据上进行预训练,使用 MLM 和 NSP 任务进行训练。预训练使模型学习到通用的语言表示,包括词汇、语法和句子间的关系。

  • 微调:在特定的下游任务数据集上进行微调。通过在预训练的BERT模型顶部添加一个任务特定的输出层(例如分类层或序列标注层),对整个模型进行微调。这使得 BERT 可以适应各种特定任务,如文本分类、问答、命名实体识别等。

5. 应用场景
  • 文本分类:使用[CLS] token的表示,通过一个线性分类层进行分类任务。适用于情感分析、主题分类等任务。

  • 问答系统:输入包括问题和段落,通过预测答案在段落中的起始和结束位置来回答问题。适用于SQuAD等问答数据集。

  • 命名实体识别(NER):在每个token的表示上添加一个标注层,预测每个token的实体类别。适用于识别文本中的人名、地名、组织名等。

  • 句子对任务:判断两个句子之间的关系,如自然语言推理(NLI)任务,通过在[CLS] token的表示上添加分类层进行预测。适用于MNLI、SNLI等数据集。

综上, BERT(Bidirectional Encoder Representations from Transformers)是一种基于双向Transformer编码器的预训练语言模型,通过双向的上下文嵌入和大规模预训练,提供了强大的语言表示能力。其核心包括WordPiece tokenization、Token/Position/Segment Embeddings、MLM和NSP预训练任务,以及预训练+微调的应用方式。BERT在文本分类、问答系统、命名实体识别等NLP任务中表现优异,广泛应用于各种自然语言处理场景。

用通俗易懂方式讲解系列

  • 《大模型面试宝典》(2024版) 正式发布!

  • 《大模型实战宝典》(2024版)正式发布!

  • 用通俗易懂的方式讲解:自然语言处理初学者指南(附1000页的PPT讲解)

  • 用通俗易懂的方式讲解:1.6万字全面掌握 BERT

  • 用通俗易懂的方式讲解:NLP 这样学习才是正确路线

  • 用通俗易懂的方式讲解:28张图全解深度学习知识!

  • 用通俗易懂的方式讲解:不用再找了,这就是 NLP 方向最全面试题库

  • 用通俗易懂的方式讲解:实体关系抽取入门教程

  • 用通俗易懂的方式讲解:灵魂 20 问帮你彻底搞定Transformer

  • 用通俗易懂的方式讲解:图解 Transformer 架构

  • 用通俗易懂的方式讲解:大模型算法面经指南(附答案)

  • 用通俗易懂的方式讲解:十分钟部署清华 ChatGLM-6B,实测效果超预期

  • 用通俗易懂的方式讲解:内容讲解+代码案例,轻松掌握大模型应用框架 LangChain

  • 用通俗易懂的方式讲解:如何用大语言模型构建一个知识问答系统

  • 用通俗易懂的方式讲解:最全的大模型 RAG 技术概览

  • 用通俗易懂的方式讲解:利用 LangChain 和 Neo4j 向量索引,构建一个RAG应用程序

  • 用通俗易懂的方式讲解:使用 Neo4j 和 LangChain 集成非结构化知识图增强 QA

  • 用通俗易懂的方式讲解:面了 5 家知名企业的NLP算法岗(大模型方向),被考倒了。。。。。

  • 用通俗易懂的方式讲解:NLP 算法实习岗,对我后续找工作太重要了!。

  • 用通俗易懂的方式讲解:理想汽车大模型算法工程师面试,被问的瑟瑟发抖。。。。

  • 用通俗易懂的方式讲解:基于 Langchain-Chatchat,我搭建了一个本地知识库问答系统

  • 用通俗易懂的方式讲解:面试字节大模型算法岗(实习)

  • 用通俗易懂的方式讲解:大模型算法岗(含实习)最走心的总结

  • 用通俗易懂的方式讲解:大模型微调方法汇总

参考

1-Rahul Agarwa 博客链接:https://thealgorithmicminds.com/explaining-bert-simply-using-sketches-ba30f6f0c8cb

2-BERT 论文:https://arxiv.org/abs/1810.04805

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

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

相关文章

【Docker】docker-compose 常用命令

启动服务: docker-compose up 如果你想在后台运行服务,可以添加 -d 标志: docker-compose up -d 开启所有服务 docker-compose start 停止服务: docker-compose down 查看服务状态: docker-compose ps 查看…

5-21作业

流式域套接字 服务器端实现 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <semaphore.h> #include <…

【MiniCPM-V】win10本地部署OCR等性能测试

性能尝试 本地配置如下 --------------------------------------------------------------------------------------- | NVIDIA-SMI 546.80 Driver Version: 546.80 CUDA Version: 12.3 | |-----------------------------------------------------…

QQ名片满级会员装x助手HTML源码

源码介绍 QQ名片满级会员展示生成HTML源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;保存素材去选择QQ个性名片-选择大图模板-把图上传照片墙即可 源码效果 源码下载 蓝奏云&#xff1a;http…

第18章-综合以上功能 基于stm32的智能小车(远程控制、避障、循迹) 基于stm32f103c8t6/HAL库/CubeMX/超详细,包含代码讲解和原理图

这个是全网最详细的STM32项目教学视频。 第一篇在这里: 视频在这里 STM32智能小车V3-STM32入门教程-openmv与STM32循迹小车-stm32f103c8t6-电赛 嵌入式学习 PID控制算法 编码器电机 跟随 第18章-综合以上功能 18-按键和app按钮切换功能 根据上面介绍&#xff0c;我们的模式可…

城市空气质量数据爬取分析可视化

城市空气质量数据爬取分析可视化 一、效果展示二、完整代码2.1 数据爬取代码2.2 数据分析代码一、效果展示 先来看一下数据情况以及可视化效果,本项目使用了pyecharts绘制了日历图、雷达图、折线图、柱状图、饼图和平行坐标系。完整代码附后: 数据如下: 日历图: 饼图: …

Go源码--sync库(1)

简介 这篇主要介绍 sync.Once、sync.WaitGroup和sync.Mutex sync.Once once 顾名思义 只执行一次 废话不说 我们看源码 英文介绍直接略过了 感兴趣的建议读一读 获益匪浅 其结构体如下 Once 是一个严格只执行一次的object type Once struct {// 建议看下源码的注解&#xf…

【找出缺失的观测数据】python

思路&#xff1a; 主要在于分配剩余的部分分配问题 代码&#xff1a; class Solution:def missingRolls(self, rolls: List[int], mean: int, n: int) -> List[int]:m len(rolls)total_sum (n m) * meantoset total_sum - sum(rolls)# 检查 toset 是否在可能的范围内i…

亚马逊高效广告打法及数据优化,亚马逊高阶广告打法课

课程下载&#xff1a;https://download.csdn.net/download/m0_66047725/89342733 更多资源下载&#xff1a;关注我。 课程内容&#xff1a; 001.1-亚马逊的广告漏斗和A9算法的升级变化.mp4 002.2-流量入口解析和广告的曝光机制.mp4 003.3-标签理论 .mp4 004.4-不同广告类…

影响所有股票、债券和ETF交易!一文看懂美国“T+1”结算新规

T1对投资者有何好处&#xff1f;有哪些风险&#xff1f;T1已经到来&#xff0c;T0还远吗&#xff1f; 美股将在本周迎来历史性时刻。 从当地时间5月28日开始&#xff0c;美股交易结算周期将由T2缩短至T1&#xff0c;即投资者当天卖出的股票&#xff0c;在交易后一个工作日就能…

蓝牙模块唤醒原理是怎样的?

随着科技的发展&#xff0c;蓝牙技术已经广泛应用于各种设备&#xff0c;如智能手机、平板电脑、智能手表等。蓝牙模块作为一种重要的通信手段&#xff0c;为我们的生活带来了极大的便利。然而&#xff0c;蓝牙模块并不仅仅是用于传输数据的工具&#xff0c;它还具有一项独特的…

LangChain之链的认识

Chain链 概述 为开发更复杂的应用程序&#xff0c;需要使用Chain来链接LangChain中的各个组件和功能&#xff0c;包括模型之间的链接以及模型与其他组件之间的链接。 链在内部把一系列的功能进行封装&#xff0c;而链的外部则又可以组合串联。 链其实可以被视为LangChain中的一…

unity制作app(11)--dropdown统一字体

下拉栏统一字体只能在执行的时候&#xff0c;而且要深入到content的最下层 全改以后 这样是无法保存的&#xff0c;但此时已经具备了找content的思维&#xff0c;在非play状态下做如下修改 其他下拉栏照改就可以了。

【CTF Web】CTFShow web2 Writeup(SQL注入+PHP+UNION注入)

web2 1 管理员赶紧修补了漏洞&#xff0c;这下应该没问题了吧&#xff1f; 解法 注意到&#xff1a; <!-- flag in id 1000 -->但是 or 被拦截了。 if(preg_match("/or|\/i",$id)){die("id error");}使用UNION注入&#xff1a; ?id1 union sele…

【Linux-RTC】

Linux-RTC ■ rtc_device 结构体■ RTC 时间查看与设置■ 1、时间 RTC 查看■ 2、设置 RTC 时间 ■ rtc_device 结构体 Linux 内核将 RTC 设备抽象为 rtc_device 结构体 rtc_device 结构体&#xff0c;此结构体定义在 include/linux/rtc.h 文件中 ■ RTC 时间查看与设置 ■ 1…

CSS绘制圆弧

css绘制如图的圆弧&#xff1a; 这种矩形弧形的效果中&#xff0c;弧形的效果一般是由一条曲线拉伸出来的&#xff0c;这条曲线往往是属于一个椭圆的&#xff0c;所以可以绘制一个椭圆&#xff0c;截取部分可视区域实现效果。 <style> .wrapper{width: 400px;height: 60…

完全背包洛谷题单

[USACO08NOV] Buying Hay S 题解&#xff1a;这题看到每个都可以卖出无限多个干草包&#xff0c;就应该想到完全背包&#xff0c;但又不同于普通的完全背包&#xff0c;普通的完全背包是让你通过对应的背包求出最大的价值&#xff0c;但是在这题理解上却是知道能够达到背包容量…

【C/C++】观察者模式

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

香橙派 AIpro开发体验:使用YOLOV8对USB摄像头画面进行目标检测

香橙派 AIpro开发体验&#xff1a;使用YOLOV8对USB摄像头画面进行目标检测 前言一、香橙派AIpro硬件准备二、连接香橙派AIpro1. 通过网线连接路由器和香橙派AIpro2. 通过wifi连接香橙派AIpro3. 使用vscode 通过ssh连接香橙派AIpro 三、USB摄像头测试1. 配置ipynb远程开发环境1.…

AI重塑了我的工作流

阅读内容 Inhai: Agentic Workflow&#xff1a;AI 重塑了我的工作流 4 种主要的 Agentic Workflow 设计模式 Reflection&#xff08;反思&#xff09;&#xff1a;让 Agent 审视和修正自己生成的输出。 举例&#xff1a;如果有两个 Agent&#xff1a;一个负责 Coding&#…