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

相关说明

这篇文章的大部分内容参考自我的新书《解构大语言模型:从线性回归到通用人工智能》,欢迎有兴趣的读者多多支持。
本文涉及到的代码链接如下: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。 ↩︎

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vitis HLS 学习笔记--基本指针和算术指针

目录 1. 简介 2. 基本指针 3. 算术指针 4. 疑点解答 4.1 疑点1 4.2 疑点2 5. 总结 1. 简介 在 C/C 语言中,指针被广泛用来表示内存中的地址信息,它们是理解和使用这些语言的核心概念之一。然而,在 Vitis HLS 中,指针的使用…

ChatGPT、Llama等大模型回答脑筋急转弯

分别使用ChatGPT3.5、 4.0 和Llama 2 70B 和3 70B这四个应用最广的大模型来回答这个流传最广的脑筋急转弯。 树上10知鸟,打死2只,还有几只? 看看它们的表现吧: 题目树上10知鸟,打死2只,还有几只&#xf…

保护共享资源的方法(互斥锁)

我最近开了几个专栏,诚信互三! > |||《算法专栏》::刷题教程来自网站《代码随想录》。||| > |||《C专栏》::记录我学习C的经历,看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

【BSP开发经验】简易文件系统digicapfs实现方式

文章目录 背景Linux vfs框架介绍数据结构系统调用openwriteread 总体框架 Linux 磁盘高速缓存机制标准文件访问同步文件访问异步文件访问buffer_head 如何实现一个简单的文件系统blkdevfs注册文件系统产生一个文件让文件变得可读可写 背景 在新的分区升级启动方案中需要分别实…

快手二面准备【面试准备】

快手二面准备【面试准备】 前言版权快手二面准备秋招一面中的问题实习一面中的问题计算机网络和操作系统论坛项目登录注册ThreadLocal代替session存储用户秒杀项目登录注册->阿里验证码->rpcsession为什么改为token实现,redis存储用户信息由binlog的用法->…

【Unity】免费的高亮插件——QuickOutline

除了常见的HighLightSystem来实现的高亮功能,其实还有很多的方法实现物体的高亮。 在 Unity资源商店 搜索OutLine,就会有很多免费好用的高亮插件。 下面介绍一下 QuickOutline这个插件,在 Unity资源商店 搜索到后,点击进去就可以…

网络模型-Qinq配置与应用

Qinq配置与应用 通过配置Qinq来实现利用公网提供的VLAN100使企业1互通,利用公网提供的VLAN200使企业2互通不同企业之间互相隔离。并通过在连接其它厂商设备的接口上配置修改0in0外层VLAN Tag的TPID值,来实现与其它厂商设备的互通。 一、创建VLAN #在Swi…

薪资不公、晋升无望?动笔写一份申诉材料吧!

薪资不公、晋升无望?动笔写一份申诉材料吧! 引言:每个努力工作的人都值得公平对待 在职场上,我们付出了汗水和智慧,期待着相应的回报——合理的工资和公正的晋升机会。然而,现实并不总是如此美好。当你感觉…

Thingsboard规则链:Entity Type Filter节点详解

在物联网(IoT)的世界里,数据的多样性与复杂性要求处理架构具备高度的灵活性和针对性。ThingsBoard作为一款强大的物联网平台,通过其规则链(Rule Chains)机制,让数据的自动化处理变得既强大又灵活…

谓词逻辑(一)

一、句子的谓词符号化 谓词逻辑,也叫一阶逻辑,它对每个最简单的命题尽一步进行分解。 1个体词:可以独立存在的客体。 2谓词:描述一个个体词的属性或多个个体词之间的关系(可用一元函数和多元函数来理解)…

18.SpringCloud Gateway

简介 SpringCloud Gateway是spingcloud家族的产品,使用netty实现的高性能服务网关,用于替换netflix公司的zuul网关实现。 参考地址: https://spring.io/projects/spring-cloud 术语 工作原理 Route Predicate Factories GatewayFilte…

降本增效!看TeeChart如何帮助实现海量「监测数据」可视化

“环境监测数据异常庞大,想要实现数据监测分析,除了要求控件具有良好的兼容性和稳定性,还对多样化、定制化的图表开发也有很高的要求” ——————— 项目负责工程师 王工 TeeChart Pro 最新版下载(qun:740060302&…

C++初阶学习第十弹——探索STL奥秘(五)——深入讲解vector的迭代器失效问题

vector(上):C初阶学习第八弹——探索STL奥秘(三)——深入刨析vector的使用-CSDN博客 vector(中):C初阶学习第九弹——探索STL奥秘(四)——vector的深层挖掘和…

JVM学习-堆空间(一)

堆空间 每个进程(JVM实例)拥有唯一的方法区和堆空间,拥有唯一的Runtime实例(基于饿汉式方式),线程共享进程的方法区和堆空间,每个线程拥有独立的程序计数器、本地方法栈和虚拟机栈。 一个JVM实例只存在一个堆内存&am…

windows docker desktop 更换镜像存储目录

windows docker desktop 更换镜像存储目录 方法:如图,Browse浏览一个新的目录并选中,确定后,程序会开始stop,在stop完成前,会持续迁移原有镜像到新的位置,你会发现目标位置的磁盘占用空间越来越…

内网穿透--Ngrok-入门-上线

免责声明:本文仅做技术交流与学习... 目录 Ngrok: 技术实现: 前提: 命令: 详细流程及图解: 平台Ngrok: Sunny-Ngrok内网转发内网穿透 - 国内内网映射服务器 支持的协议:tcp、http、https 支持的类型:正向代理、反向代理 --隧道开通免费的 --协议…

论文降重攻略!复盘降重至5.7%,aigc降到0%的经验!

论文降重攻略!复盘降重至5.7%,aigc降到0%的经验! 首先要提一个敲好用的论文降重软件-蝌蚪论文,当知网查重46%的时候有没有和我一样头都要炸的感觉,最关键的是自己改了几天还是没降下去。 索性删了好多标红的,但查重率…

别说废话!说话说到点上,项目高效沟通的底层逻辑揭秘

假设你下周要在领导和同事面前汇报项目进度,你会怎么做?很多人可能会去网上搜一个项目介绍模板,然后按照模板来填充内容。最后,汇报幻灯片做了 80 页,自己觉得非常充实,但是却被领导痛批了一顿。 这样的境…

四天学会JS高阶(学好vue的关键)——深入面向对象(理论+实战)(第三天)

***本章面试使用居多* 理论篇**一、编程思想 1.1 面向过程 JS 前端居多 按照步骤 性能高 适合跟硬件关系很紧密 没有面向对象易维护易复用易扩展 1.2 面向对象 java典型 按照功能,把事务分别成一个个对象,对象之间分工合作 比较灵活 适合多人合作的…

Java基础(三)- 多线程、网络通信、单元测试、反射、注解、动态代理

多线程基础 线程:一个程序内部的一条执行流程,只有一条执行流程就是单线程 java.lang.Thread代表线程 主线程退出,子线程存在,进程不会退出 可以使用jconsole查看 创建线程 有多个方法可以创建线程 继承Thread类 优点&#x…