利用神经网络学习语言(一)——自然语言处理的基本要素

news2024/11/18 11:51:05

相关说明

这篇文章的大部分内容参考自我的新书《解构大语言模型:从线性回归到通用人工智能》,欢迎有兴趣的读者多多支持。
本文涉及到的代码链接如下:regression2chatgpt/ch10_rnn/tokenizer.ipynb

本系列文章将深入探讨一种应用广泛的神经网络——循环神经网络(Recurrent Neural Network,RNN)。这类模型在各种场景下展现出惊人的效果,尤其在自然语言处理(Natural Language Processing,NLP)领域表现突出。实际上,引发世人惊叹甚至恐惧的大型语言模型正是基于循环神经网络构建的。

作为系列文章的开篇,本文将放眼于自然语言处理领域的基础知识,而非深入探讨具体模型的技术细节。更确切地说,我们将从数据的角度探讨如何利用神经网络模型处理自然语言。其中的重点是语言数字化和学习框架。

这篇文章将为后续的多篇内容奠定基础,这些内容将包括:

  • 利用神经网络学习语言(二)——利用多层感知器(MLP)学习语言
  • 利用神经网络学习语言(三)——循环神经网络(RNN)
  • 利用神经网络学习语言(四)——深度循环神经网络
  • 利用神经网络学习语言(五)——长短期记忆网络(LSTM)

内容大纲

  • 相关说明
  • 一、基础概念
  • 二、语言数字化
  • 三、分词器的语言基础
  • 四、英文分词器
  • 五、中文分词的挑战
  • 六、学习框架:迁移学习

一、基础概念

自然语言处理是人工智能领域中至关重要的任务。语言本身是一个复杂的学科,即使对于人类而言,掌握一门语言也需要耗费相当多的时间和努力。因此,自然语言处理汇聚了人工智能最先进的技术和一些最巧妙的设计。通过深入研究自然语言处理,我们能够迅速了解人工智能的最新技术和发展趋势。当然,自然语言处理的相关技术和建模思维也能够轻松地应用于其他领域。此外,人类的交流主要依赖文字,几乎所有的知识都以文字的形式进行呈现和存储。机器理解语言不仅可以使人与机器之间的交流更加顺畅,还能让机器学会存储在语言中的知识。这一过程有望推动人工智能产生质的飞跃——从单一的人工智能逐渐演进成为通用人工智能(Artificial General Intelligence,AGI)。

自然语言处理的目标非常明确:使计算机能够像人类一样处理和理解语言,以执行各种自动化任务。从技术角度来看,由于语言的复杂性,自然语言处理并没有一个严格且准确的定义。它包括多种不同的建模任务,如机器翻译、自动摘要、文本生成等。此外,随着时间的推移,这个领域使用的技术和主要依赖的模型也在不断发展演进。尽管自然语言处理涉及多样化的具体任务,使用的模型和技术也各不相同,但从宏观角度看,可以将其分为3个关键步骤:语言数字化、模型选择和学习框架,如图1所示。语言数字化和模型选择的概念相对容易理解。但什么是学习框架呢?学习框架是指训练模型的模式和方法。具体的细节将在文章的第六节中讨论,这里先做一个简单的铺垫。

图1

图1

在传统的自然语言处理中,通常会针对单一任务进行建模,比如文本分类。在这种情况下,学习框架相对简单,与其他建模任务类似,使用数字化的文本数据和相应的标签来训练模型。然而,这种单一任务的建模方式与真正理解语言的目标还有一定距离。当前最先进的大语言模型采用的是迁移学习(Transfer Learning)的框架,它包含两个步骤,分别是预训练(Pre-training)和微调(Fine-tuning)。

  • 预训练阶段:模型在大规模文本数据上进行训练,其目标是学习通用的语言知识,而不是特定的任务知识。
  • 微调阶段:针对具体的建模任务,在预训练模型的基础上微调模型参数,以提升它在特定任务上的表现。

需要明确的是,上述3个关键步骤中的每一个都包括多种不同的技术。因此,将它们分开讨论有助于更好地理解。在实际应用中,读者可以根据需求自由组合。本文将重点讨论文本数字化和学习框架,模型选择将在本系列的后续文章中详细讨论。

二、语言数字化

与图像识别中的图像特征提取相似,语言的特征提取同样具有挑战性。为了解决这个问题,可以借鉴图像处理的方法(如果读者对图像识别不太熟悉,可以参考其他文章[TODO]),首先考虑如何将语言数字化,然后利用模型(通常是神经网络)自动提取特征。

语言数字化的核心是一个将文字排好序的字典。举例来说,假设有一个包含 n n n个文字的字典,比如“我”排在第1位,“成”排在第2位,如图2下半部分所示。借助这个字典,每个文字都可以用一个 n n n维向量表示。如果一个文字在字典中排在第 j j j位,那么相应位置的值就是1,即 x j = 1 x_j = 1 xj=1;其他位置的值为0,即 x i = 0 , i ≠ j x_i = 0,i ≠j xi=0,i=j。如果一个文本包含 k k k个文字,那么它可以轻松地被数字化为一个 k × n k×n k×n的矩阵(二维张量)。这种方法在学术界通常被称为独热编码(One-Hot Encoding)。

图2

图2

在前面的讨论中,我们有意忽略了一个重要的问题:当需要数字化的文字不在字典中时,应该如何处理?在实际应用中,这种情况相当常见。字典是在处理文本之前预先生成的,而文本的内容千变万化,可能包括生僻字、新的英文缩写、表情符号等,这些“文字”都可能不在字典中。为了解决这个问题,通常的做法是在字典中预留一个特殊字符。当所有其他字符都无法匹配时,就用这个特殊字符来表示未知的“文字”。举个极端的例子,如果字典只包含26个英文字母和一个特殊字符,那么所有汉字都会被表示为相同的特殊字符,从而被数字化成相同的向量。在这种情况下,即使模型再强大,也难以学会处理中文。

尽管现实情况不会那么极端,但字典的定义确实对模型的效果影响巨大。以大语言模型ChatGPT为例,它使用相同的模型结构来处理不同语言的文本,但在处理英文时,模型效果明显好于中文,其中一个原因就是英文的字典定义更加合理1。可以将字典类比为图像识别中的像素点,它在自然语言处理中扮演着基础角色。如果这个基础不稳固,存在一些偏差,那么即使模型的结构再绝妙,也难以取得良好的效果。

那么,字典是如何生成的呢?这将是接下来的讨论重点,即分词器(Tokenizer)。分词器的任务是将文本划分成有意义的单元,并以此为基础构建字典。

三、分词器的语言基础

实际上,字典中的元素通常不是我们日常理解的“文字”或“单词”(虽然有一定相似性)。为了避免混淆,将这些元素称为词元(或令牌、Token)。它们是语言数字化时不可再分的语义结构,也是模型进行计算和推断的最小单元。因此,接下来的讨论将广泛使用词元这个术语,希望读者能迅速熟悉并理解它。

词元的生成取决于分词器。分词器不仅是技术领域的一个话题,而且涉及多个学科的交叉领域。因此,本节以及接下来的两节内容可能会有些偏离主题。读者如果对细节感兴趣,可以参考这些讨论并结合其他资料进行深入研究;如果对细节不感兴趣,可以将分词器视为一个封装好的工程组件,其主要任务是将语言划分成词元,构建字典,并最终实现语言数字化。

不同的分词器会产生差异很大的结果。以英语(表音文字的典型代表)为例,可以考虑以下两种分词器。

  • 字母分词器:这种分词器按字母来划分文本,将每个字母作为词元。由于英语字母有限,字典会非常小,只包含26个元素(排除符号),输入数据的维度较低,这降低了模型训练的难度。然而,这种划分方式产生的数据不是很适合学习,因为单个字母通常不携带太多含义,而且不同字母在不同单词中可能具有完全不同的语义。
  • 空格分词器:这种分词器将英文文本按照空格划分,将每个单词作为词元。这种方式产生的数据更适合学习,因为每个词元都代表一个明确的含义。然而因为英语中的词汇量很大,字典会非常庞大。研究表明,仅英语就包含超过26万个单词,而通常的模型最好使用包含5万个词元的字典。

通过上述讨论,可以了解到理想的分词器需要满足两个关键要求:首先,生成的字典不应过于庞大2;其次,每个词元最好只表示一个明确的语义。正如哲学家维特根斯坦所强调的,“一个词的意义就在于它在语言中的使用(The meaning of a word is its use in the language)”。因此,理想的分词器必须具备对语言结构和使用规则的深刻理解。为了更深入地讨论分词器,首先需要对世界上的语言进行分类。根据其书写系统的不同,可以将语言分为4种类型。

  • 语素文字(Logographic)、音节文字(Syllabic):代表语言包括中文等,这些语言的书写系统基于语素或音节,每个字符通常代表一个单词或有特定含义的语言单元。
  • 全音素文字(Alphabetical): 代表语言包括英文、法文等,它们的书写系统由字母组成,每个字母代表一个音素或声音。
  • 辅音音素文字(Abjad): 代表语言包括阿拉伯文,它们的书写系统主要包含辅音,省略了元音,所以朗读文章时口中需补上适当的元音。
  • 元音附标文字(Abugida): 代表语言包括北印度婆罗米文字,它们的书写系统以元音为基础,辅音附在元音之后。

我们也可以“文化沙文主义”3一点,将这些文字根据其书写系统的特点简化为两大类。

  • 语素文字(Logographic):例如中文,每个字符代表一个词或特定含义的单元。
  • 表音文字(Phonogram):除中文之外的其他文字,它们的书写系统基于音素或音节。

无论如何分类,中文都是一种独特的文字,因此其分词方法与其他语言有显著不同。接下来的讨论将首先关注英文的分词器,介绍几种常用的分词方法及其优缺点,随后在第五节中详细讨论中文分词。

四、英文分词器

上一节中的两个分词器示例分别代表了两个极端。为了实现理想的分词效果,我们需要在这两个极端之间找到一个平衡点,也就是一种“既能比单个字母更大,又比完整单词更小”的语义单元,这就是子词分词(Subword Tokenization)。举例来说,技术文档中经常出现以下这些单词:data(数据)和metadata(元数据)、physics(物理)和metaphysics(形而上学)。通过观察这些单词,我们可以发现meta实际上是一个子词,即比单词更小但具有独立语义的单元。那么,如何穷尽这些子词呢?经典的方法之一是字节对编码(Byte-Pair Encoding,BPE),具体步骤如下。

  1. 初始化:将文本拆分成单个字符,并计算每个字符的出现频率。
  2. 合并:选择出现频率最高的字符对(Byte Pair),将它们合并成一个新的子词元,并更新词汇表。
  3. 重复:重复第2步,直到达到预设的词汇表大小或者合并次数。
  4. 最终词汇表:包括字符和子词元,可以用于分词和文本编码。

整个过程如图3所示。根据上述描述,最终生成的分词器的词汇表大小取决于算法执行了多少次合并操作。例如,如果初始字符集包含478个字符,那么经过40000次合并后,将生成包含40478个词元的词汇表(这是初代GPT使用的分词算法)。

图3

图3

上述算法的基础是语言中存在一个相对较小的初始字符库,这对于表音文字是可行的,但对于中文等非表音文字并不适用,原因在于中文不是由字母构成的。为了使分词器能够处理各种语言,学术界进一步提出了字节级字节对编码(Byte-level BPE)4。这个设计的精妙之处在于,无论是英文、中文还是其他语言,它们的字符在计算机中最终都被转换成二进制来存储。

具体来说,字符在计算机中都以字节为单位进行存储,而1字节由8个二进制数组成。通常来说,一个字母用1字节存储,也就是一个字母对应着一个8位二进制数,而一个中文汉字由2字节来存储。因此,任何字符都可以被表示为若干个8位二进制数的组合。

基于这一点,字节级字节对编码的做法是将之前算法中的初始化字符集替换为1字节所能表示的内容5,而其他步骤保持不变。这种分词器更加灵活,限制更少,因此也被称为通用分词器。通用分词器能够处理各种文本内容,包括不同的语言和表情符号等,因此是一个被广泛应用的强大工具。

五、中文分词的挑战

中文和英文的语言结构存在显著差异,因此难以直接借鉴英文中成熟的分词算法。为了更好地理解这一点,我们以前面提到的字节对编码算法为例。这个算法构建在英文的两个显著特点上:一是英文容易被划分成单词,二是单词由字母组成。然而,这两个前提在中文中都面临挑战。

第一,中文文本中的词语没有像英文那样使用明确的空格分隔,因此在中文中将文本划分成单个词语变得更复杂。

第二,中文不同于表音文字,没有字母的概念6。虽然汉字需要组合成词语才能表达意思,有点类似于英文字母,但汉字与英文字母存在两个显著的区别。

  • 在中文中,当我们遇到不认识的汉字时,通常可以通过识别偏旁部首或其他构成部分来猜测其含义和发音。正如俗语所说“四川人眼睛生得尖,认字认半边”,这表明汉字可以被进一步拆分为有意义的部分。也就是说,汉字在语义上与英文字母存在显著差异,更类似于英文字母的其实是偏旁部首。
  • 从工程角度看,中文拥有大量汉字,远远多于英文字母。如果将中文简单地视为字母,并尝试借鉴字节对编码算法来合并字符,会导致生成的字典过于庞大,使后续模型难以学习。

通用分词器看似解决了上述问题,但实际上它仍然存在某种程度的“语言偏见”。为了更好地说明这一点,来看一个具体的例子:分别用法语、英语和中文三种语言来介绍伟大的法国数学家埃瓦里斯特·伽罗瓦,然后用通用分词器对这三段文字进行分词。尽管这三段文字表达了相同的内容且文本长度相近,但中文(法语也存在类似情况)分词后的长度明显超过英文,如图4左侧所示(更多细节请参考代码)。这表明分词器对中文的划分过于细致,破坏了语言的内在结构。可以这样理解:这种分词效果类似于在处理英文时将其按字母进行分词,这会导致分词后的中文更难学习。

图4

图4

那么,是什么原因导致了这种现象呢?其根本原因在于通用分词器的训练数据偏向英文7。在全球的文献库中(以互联网语料库为代表),英文的比例远高于其他语言。就像人类学习一样,英文得到更广泛的暴露,因此通用分词器在英文上表现更出色。而对于其他语言,比如法语、中文等,分词效果就较差。实际上,如果使用中文语料库来训练分词器,然后对比中文和英文的分词效果,会发现结果与之前完全相反,如图10-4右侧所示。

总结一下,现有的分词技术主要是面向表音文字设计的,因此在处理中文时,直接套用这些技术通常效果平平。即使使用通用分词器,由于中文文献相对较少,中文分词的效果也明显不如英文。然而,这些短板并不应被视为不足之处,反而应被视为该领域的发展机遇。一方面,这说明中文自然语言处理领域仍然有许多机会等待着我们去发挥创造力;另一方面,中文的独特性也凸显了它在人工智能领域潜在的特殊价值。

图5

图5

哲学家维特根斯坦曾说过,“我语言的边界即是我世界的边界(The limits of my language mean the limits of my world)”。一个人思考的方式和极限都受其所使用的语言的限制,可以说我们在使用语言的同时,也在被语言塑造。语言是我们表达思想的强大工具,但学习外语的人都深知,每种语言都包含独特的概念,很难用其他语言准确翻译。比如,《道德经》中的“道可道,非常道”在英文中难以准确表达,“道”这个概念在英文中找不到合适的对应词汇8。因此,作为一门广泛使用且蕴含丰富古老智慧的语言,中文为神经网络提供了更丰富的学习资源,使其能够变得更智慧,如图5所示。

六、学习框架:迁移学习

在人工智能的早期阶段,学习方法主要专注于单一任务,即为每个任务单独搭建模型。以图像识别为例,当进行图像识别时,模型并不试图理解图像的内容,比如是否包含多种颜色或曲线等,而是直接对预测标签进行建模。这种建模方式虽然目标明确,但存在一个严重的限制:构建的模型只能用于解决特定任务,即使面对极其相似的任务,也只能重新搭建和训练模型,无法做到知识的融会贯通。

现代深度学习正朝着更加通用和灵活的方向发展,使我们能够构建适用于多个任务的模型。这一方法被称为迁移学习,通过将从一个任务中获得的知识迁移到另一个任务中,从而节省时间和资源。本节开头讨论的学习框架——预训练和微调,就是迁移学习的典型代表,如图6所示。

图6

图6

在这个框架中,预训练阶段至关重要,模型在此阶段通过学习大量文本数据来理解语言。但由于此时还没有具体的建模目标,需要考虑如何准备数据来训练模型。换句话说,在不考虑模型的具体结构的情况下,应该如何为模型构建适当的输入数据和预测标签,使得模型能够理解语言。具体而言,有3种主要方法。

  1. 序列到序列模式(Sequence to Sequence Model):这种模式其实是在模拟语言翻译的过程。简而言之,需要提供一系列已经翻译好的文本对。例如,“I think therefore I am”和“我思故我在”,将第一句英文作为输入数据,第二句中文作为预测标签,反之亦然。在这种模式下,模型的主要任务是学习如何将一个文字序列翻译成另一个文字序列。
  2. 自回归模式(Autoregressive Model):这是一种简单而直接的方法,它根据给定的文本背景来预测下一个词元(可以简单地将词元这个术语简单地理解为中文中的词语或英文中的单词)是什么。以文本“我爱你”为例,可以创建两组训练数据:输入是“我”,预测标签是“爱”;输入是“我爱”,预测标签是“你”。这种方式生成的训练数据量通常远多于其他方式,而且能够覆盖更广泛的内容。例如,文本“I think therefore I am的中文翻译:我思故我在”就可以覆盖序列到序列模式想要传递的知识。
  3. 自编码模式(Autoencoding Model):随机屏蔽掉文本中的一些词元,然后预测缺失的部分9。以“我思故我在”为例,可以将其随机屏蔽为“我*故*在”(这就是输入数据),而预测标签是“思”和“我”。与自回归模式相比,自编码模式的实现稍显复杂,需要在文本中随机选择要屏蔽的词元,而自回归模式相当于只屏蔽最后一个词元10

实际上,上述的训练方法都源自Transformer模型的演化,最初的灵感来自Transformer的不同组件适合不同的训练方式。然而,随后的研究表明,对于同一个模型,只要稍做修改,就可以采用这3种模式中的任何一种来进行训练。

在自然语言处理的发展中,不同的训练模式在不同的历史时期占据主导地位11。最初,大多数模型采用序列到序列模式进行训练,随后自编码模式变得流行,而ChatGPT的成功让自回归模式逐渐引领了潮流。尽管这3种训练模式在构建训练数据方面存在很大差异,但它们训练出的模型内核却比较相似。这是因为不论采用哪种方式,预训练的主要目标都是学习如何更有效地提取文本的特征。从工程的角度来看,3种模式传递的知识是相似的。自回归模式更容易处理,能够生成更多的训练数据,因此,本系列的后续内容将专注于这一训练模式,并深入研究如何利用不同的模型更有效地学习语言。


  1. 大语言模型ChatGPT在英文上的表现最佳,其原因不仅是英文字典定义更为合理,还有其他一些因素,比如英文语料更加丰富且质量更高。 ↩︎

  2. 过于庞大的字典会导致模型难以训练。 ↩︎

  3. 沙文主义(Chauvinism)这一词源于尼古拉·沙文(有可能是文艺作品中的虚构人物),他是拿破仑手下的一名士兵,因为获得军功章而对拿破仑感恩戴德,对拿破仑以军事力量征服其他民族的政策狂热崇拜。文化沙文主义(Cultural Chauvinism)是一种极端的偏见和偏执,表现为对自己所属文化的过度自信和过度推崇。它通常伴随着对其他文化的贬低、轻视、歧视或敌视,以及对自己文化的绝对优越感。需要明确的是,在本书中,我们强调中文的独特性并不代表“文化沙文主义”。中文作为一门语言拥有其独特之处,这并不意味着要否定其他语言的重要性或价值。我们使用这一词汇的目的是提醒读者在利用人工智能学习人类语言时,要警惕正向或逆向的文化沙文主义,应接纳不同语言和文化的多样性,并珍惜其带来的贡献。 ↩︎

  4. 字节级字节对编码是GPT-2以及后续版本采用的分词方法。 ↩︎

  5. 因为8位二进制数的取值范围是0到255,所以初始字符集包含了256个元素。 ↩︎

  6. 在历史上,中文无法用拉丁化字母书写曾被认为是“中文的原罪”。这一观点在新文化运动时期尤为突出。在当时的社会背景下,中文因为难以印刷传播及其较高的学习难度,被认为是中国高文盲率和整体滞后的重要原因。陈独秀曾言,“中国文字,既难载新事新理,且为腐毒思想之魔窟,废之诚不足惜。”鲁迅甚至在死前高呼“xxxx,xxxx”(审核通不过,请自行百度)。因此,那个时代的汉字拉丁化运动倡导“不再使用汉字,全文采用字母书写”。然而,中华人民共和国成立后,通过开展扫盲运动,文盲率迅速下降,这显然证明了这一运动和观点的荒谬性。历史反复证明,激进的口号虽然能激发人们的热情,让人热血沸腾,但大多数情况下只会带来一地鸡毛。渐进的技术革新往往是真正的进步之道。 ↩︎

  7. 通用分词器也是通过数据训练而得到的。需要注意的是,它的训练原理不同于神经网络,不依赖梯度下降法和反向传播等技术。 ↩︎

  8. 反过来的例子也有很多,比如中文中原本没有“科学”一词的概念。在“五四运动”时期,曾经将这个词音译为“赛因斯”(赛先生)。然而,随着时间的推移和人们对该领域的深入理解,科学已经成为中文中不可或缺的概念。与人工智能类似,通过学习多种语言,我们可以扩展视野,丰富知识储备。以英文为例,它是科学的通用语言,精通英语有助于更深刻地理解科技发展。实际上,英语已经不再仅仅是英国人的母语,许多科技领域中的新术语和新概念,如神经网络中的Back Propagation(反向传播),即使对于以英语为母语的人来说也可能需要时间来理解,就像学习一门新外语一样。
    虽然以母语表达和感受母语之美通常会激发爱国情怀,但承认语言的局限性只是陈述一个客观事实,与情感和意识形态无关。相反,作为中文的传承者,学习其他语言中独特的概念,将其翻译并融入中文,有助于丰富和发展我们的母语,使其成为一门更加美丽的语言。这也是我们的使命和责任。 ↩︎

  9. 在最初的版本中,自编码模式还包含另一个训练任务,即预测两个句子是否来自同一文本并且在该文本中是否连续。 ↩︎

  10. 理论上,自编码模式可以覆盖自回归模式,即将长度为n的原始文本转化为n-1个新文本,例如将“我爱你”转化为“我爱”和“我爱你”,然后屏蔽这些新文本的最后一个字。然而,在实际应用中,很少使用这种方法来构建自编码模式的训练数据,因此不能将这种方法视为自回归模式的扩展。 ↩︎

  11. 序列到序列模式的代表有BART和T5;自回归模式的代表是GPT;自编码模式的代表是BERT。 ↩︎

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

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

相关文章

hcia datacom学习(8):静态NAT、动态NAT、NAPT、Easy IP、NAT server

1.私网地址 在现实环境中,企业、家庭使用的网络是私网地址(内网),运营商维护的网络则是公网地址(外网)。私网地址是在局域网(LAN)内使用的,因此无法被路由,不…

计算机毕业设计 | springboot药品库存追踪与管理系统 药店管理(附源码)

1,绪论 1.1 背景调研 如今药品调价频繁,且品种繁多,增加了药品销售定价的难度。药品来货验收登记中的审查有效期环节容易出错,错收过期或有效期不足的药品。 手工模式下的药品库存难以及时掌握,虽然采取了每日进行缺…

5.23.1 深度学习在乳腺癌成像中的应用

乳腺成像在早期发现乳腺癌以及在治疗期间监测和评估乳腺癌方面发挥着重要作用。最常用的乳腺成像方式是数字乳房X线摄影、数字乳腺断层合成、超声和磁共振成像。 传统的 CAD 系统基于传统的机器学习 (ML) 技术;预定义(手工制作)的特征是系统…

元器件基础学习笔记——电感的分类及主要参数

一、电感的分类 电感器是一种电子元件,它能够将电能转化为磁能并储存起来。电感器的分类方法有很多,可以根据用途、形状、结构等不同的标准进行划分。 分类依据类型备注电感值固定电感固定线圈可变电感改变磁芯的饱和度用途高频电感绕线型,积…

Nest的test中的best是Jest框架

Nest的test中的best是Jest框架 前言 花了3天时间给自己之前做的一个小系统基本补完了单元测试,趁此机会>脑袋里对于单元测试的知识还算热乎,来输出一篇比较详细的关于单元测试的文章,以梳理知识,融汇贯通;如果对你…

配置旁挂二层组网直接转发示例(命令行)

业务需求 企业用户通过WLAN接入网络,以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时,不影响用户的业务使用。 组网需求 AC组网方式:旁挂二层组网。DHCP部署方式: AC作为DHCP服务器为AP分配IP地址。汇聚交换机SwitchB作…

vue小记——小组件(1)

代码&#xff1a; <template><div><el-steps :active"active" finish-status"success" simple><el-step title"数据导入"><i class"fa fa-cloud-upload fa-icon-custom" slot"icon"></i…

Docker搭建mysql性能测试环境

OpenEuler使用Docker搭建mysql性能测试环境 一、安装Docker二、docker安装mysql三、测试mysql连接 一、安装Docker 建立源文件vim /etc/yum.repos.d/docker-ce.repo增加内容[docker-ce-stable] nameDocker CE Stable - $basearch baseurlhttps://repo.huaweicloud.com/docker…

【手势识别-UIPinchGestureRecognizer捏合-UIPanGestureRecognizer缩放 Objective-C语言】

一、接下来,我们来说这个捏合,和,这个缩放啊 1.捏合, 首先呢,步骤,也都是一样的啊, 1)创建手势对象 2)添加手势 3)实现手势方法 pinch:捏合 UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:(id) action:(SEL)]; U…

ThreadLocal原理及使用

一、引言 在Java多线程编程中&#xff0c;ThreadLocal是一个非常有用的工具&#xff0c;它提供了一种将对象与线程关联起来的机制&#xff0c;使得每个线程都可以拥有自己独立的对象副本&#xff0c;从而避免了线程安全问题。然而&#xff0c;使用不当会导致内存泄漏问题。 二…

spring-boot整合Micrometer+Prometheus

环境&#xff1a; micrometer 1.8.2 prometheus 0.14.1 spring-boot-actuator 2.6.6 使用案例 <!-- Springboot启动actuator&#xff0c;默认会引入依赖&#xff1a;micrometer-core --> <dependency><groupId>org.springframework.boot</groupId>&l…

ctfhub中的SSRF相关例题(中)

目录 上传文件 gopher协议的工作原理&#xff1a; gopher协议的使用方法&#xff1a; 相关例题: FastCGI协议 FastCGI协议知识点 相关例题&#xff1a; Redis协议 知识点&#xff1a; 相关例题 第一种方法 第二种方法 上传文件 gopher协议的工作原理&#xff1a; …

《ESP8266通信指南》番外-(附完整代码)ESP8266获取DHT11接入(基于Lua)

前言 此篇为番外篇,是 ESP8266 入门的其他功能教程,包括但不限于 DHT11 驱动TCP 通信Thingsboard 平台的接入阿里云物联网云平台接入华为云平台接入 1. 小节目标 使用 Lua 驱动 DHT11 传感器,获取温湿度的值 2. 进入主题 NodeMCU 基于 LUA 相关资料 官方文档&#xff1a;…

商品指数创年内新高,粘性通胀成为美联储噩梦

文章概述 虽然美国4月CPI增幅放缓让美联储今年降息的可能性大增&#xff0c;但与此同时&#xff0c;大宗商品价格却达到了一年来的最高水平&#xff0c;粘性通胀可能成为美联储的噩梦。数据显示&#xff0c;跟踪24种能源、金属和农业合约彭博大宗商品现货指数今年以来已经上涨…

Mysql超详细安装配置教程(保姆级图文)

MySQL是一种流行的开源关系型数据库管理系统&#xff0c;它广泛用于网站和服务的数据存储和管理。MySQL以其高性能、可靠性和易用性而闻名&#xff0c;是许多Web应用程序的首选数据库解决方案之一。 一、下载安装包 &#xff08;1&#xff09;从网盘下载安装文件 点击此处直…

RK3588 Android13 TvSetting 中增加字体样式切换功能

前言 电视产品,客户需求又升级了,有了切换字体大小还不行,还得增加动态切换字体样式功能, 同样需要在设备偏好设置子菜单里的显示和声音二级菜单里增加字体样式菜单功能,开整。 效果图 framework 部分修改文件清单 frameworks/base/data/fonts/fonts.mk frameworks/bas…

附代码:策略常用-正余弦优化算法

正余弦优化算法作为群智能优化算法的一种, 正弦余弦算法 (sine cosine algorithm, SCA) 是 2016 年由 Mirjalili 提出的一种新型仿自然优化算法, 通过创建多个随机候选解, 利用正余弦函数的数学性质来平衡算法在搜系过程中的全局探索和局部开发能力。该算法具有结构简单、参数少…

MobaXterm:Network error: Connection refused

问题描述 使用MobaXterm连接服务器或者虚拟机里面的操作系统显示“Network error: Connection refused” 因为服务器或者虚拟机里面的操作系统没安装 ssh 解决方法 安装ssh sudo apt-get update sudo apt-get upgrade sudo apt-get install ssh重启 ssh service ssh resta…

Docker 镜像是什么?

Docker 镜像是什么&#xff1f; Docker 镜像&#xff08;Docker Image&#xff09;是用于创建 Docker 容器的只读模板。它包含了运行应用程序所需的所有内容&#xff0c;包括代码、运行时环境、库、环境变量以及配置文件。Docker 镜像是构建和分发应用程序的基础。 在深入阅读…

[数据集][目标检测]弹簧上料检测数据集VOC+YOLO格式142张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;142 标注数量(xml文件个数)&#xff1a;142 标注数量(txt文件个数)&#xff1a;142 标注类别…