Text models —— BERT,RoBERTa, BERTweet,LLama
BERT
什么是BERT?
BERT,全称Bidirectional Encoder Representations from Transformers,BERT是基于Transformer的Encoder(编码器)结构得来的,因此核心与Transformer一致,都是注意力机制。这种机制使得模型能够捕捉到句子中词语之间远距离的依赖关系,这是传统RNN/LSTM难以高效实现的能力。
BERT中的B —— Bidirectional
在自然语言中,一个词语的真正含义往往不是孤立存在的,它深深植根于其所处的上下文。更重要的是,这个上下文不仅包括它左边的词(前文),还包括它右边的词(后文)。
传统的语言模型,在BERT之前,要么是单向的(例如GPT-1,它只能自左向右地预测下一个词),要么是浅层双向的(例如ELMo,它通过训练两个独立的单向LSTM——一个从左到右,一个从右到左——然后将它们的表示拼接起来)。这两种方式都存在局限性:
- 单向模型: 当模型在处理一个词时,它无法“看到”这个词之后的信息。这意味着,如果一个词的真实含义需要依赖它后面的词语来 disambiguate(消除歧义),单向模型就会束手无策。这就像你看书,却被要求只能看到当前页的左边部分,无法预知右边即将出现的内容。
eg:
1.“他把钱存进了bank的账户里。”
2. “这条小船停靠在河边的bank。”
在这两个句子中,“bank”这个词是多义词,它既可以指“金融机构”(bank),也可以指“河流的岸边”(river bank)。如果模型只能从左到右看,那么对于第一句,到bank前,模型看到的是:“他把钱存进了...”,基于这些信息,模型可能会猜测“bank”指的是一个金融机构。这似乎是正确的。但对于第二句,到bank前,模型看到的是:“这条小船停靠在河边的...”,仅仅依靠“河边”这个词,模型可能会倾向于猜测“bank”指的是河岸,这在这个语境下也是正确的。但会存在一个问题,你基于bank的理解都只是基于上文,对于第一个句子,“他把钱存进了...”,你下一个词也可以是"保险柜","储钱罐"等等,为什么一定是“银行”呢,因此如果,你如果知道右边的信息“账户”这个下文,你就可以更加明确这里预测的更可能是"bank",而不是“保险柜”等。对于第二个句子,你又怎么知道这里指的是"河岸"而不是"银行"呢?,万一句子想要表达的意思是"船夫将船停靠在河边的bank,并进去取钱",在缺乏下文"取钱"这个含义下,你这时候还能说"bank"是表达岸边的意思吗?因此,基于单向模型的文本编码无法有效照顾到上下文,它对于信息的获取都是基于局部已有信息,具有狭隘性。
- 浅层双向模型: 拼接式的双向虽然看似考虑了两边,但通常是两个独立的单向模型分别编码,然后简单合并。它们在深度上,并没有真正实现左右上下文的深度交互和融合,导致对复杂语境的理解能力不足。如ELMo,其工作原理为:1.分别训练一个从左到右 (L-R) 的LSTM:它处理输入序列并学习每个词基于其左侧上下文的表示。一个从右到左 (R-L) 的LSTM:它处理反向的输入序列(或者说,它学习每个词基于其右侧上下文的表示)。2.对于序列中的每个词,ELMo会将这两个独立的LSTM生成的隐藏状态(向量表示)进行拼接 (concatenation) 或者加权平均,从而得到该词的最终表示。
这就像是分别安排两个人读同一文本段落,让其中一个从左到右读,另外一个从右到左读,然后将两个人的内容进行交换从而获得对于这一文本段落的理解。但这种方式不如一个人直接从左到右和从右到左分别读一遍,这样跟两个人以不同方式读相比,歧义会少。而BERT就是基于这个思想出发来进行设计。
eg:
"他计划周五去bank开户,尽管那时河边bank可能已经关门。"
针对第一个bank,从左到右的LSTM在处理第一个“bank”时: 它能看到“他计划周五去”。基于这些信息,它可能会给出一个通用的表示,因为它完全不知道后面有“开户”这个强烈的提示词。从右到左的LSTM在处理第一个“bank”时, 它能看到“开户,尽管那时...”。这个模型能捕捉到“开户”与“银行”的关联,从而给出指向“金融机构”的表示。最终表示: 这两个独立计算出来的表示(一个只看到左边,一个只看到右边)被拼接起来。
浅层双向的局限性体现在,从左到右的LSTM在处理到“bank”时,它无法在其内部计算过程中,根据“开户”这个后续信息来实时调整和精炼它对“bank”的理解。它只能依赖它当时已知的左侧上下文。虽然最终会拼接右侧信息,但这种融合是事后的,而非过程中的深度交互。如果从左向右针对该词给出的通用表示与bank歧义比较大,从右向左针对该词给的表示可以表示“金融机构”,但你能确保这两个拼接起来,针对该词最终的表示可以表示为“金融机构”吗?
BERT所追求的“双向性”,是深层次的、同时利用左右上下文的理解。 这意味着,在模型理解和表示一个词语时,它能够同时“看到”这个词语在句子中的所有前文和所有后文,从而获取一个真正完整的语境信息。
BERT的预训练
BERT在海量无标签文本数据上进行无监督(unsupervised learning)预训练来学习语言的通用表示。这个过程类似于人类通过大量阅读来积累语感和知识。BERT的预训练主要依赖于两个创新任务:
-
掩码语言模型 (Masked Language Model, MLM)
MASK IS ALL YOU NEED,这是BERT实现深度双向性的基石。
- 操作方式: 在输入文本中,BERT会随机选择15%的词语进行“遮蔽”(即替换成一个特殊的
[MASK]
标记)。 - 训练目标: 模型的任务就是预测这些被遮蔽(MASK)的词语是什么。
- 巧妙之处: 为了防止模型简单地“记住”被遮蔽的位置(记答案),这15%的词语有以下处理方式:
- 80%的概率:被替换为
[MASK]
标记。(基于上下文预测该MASK对应的词语——填空题) - 10%的概率:被替换为词汇表中的任意一个其他随机词语。这强迫模型不仅要预测被遮蔽的词,还要分辨出替换的词是否合理,增加了学习的难度和深度。(基于上下文来判断该MASK的词语使用是否正确——判断题)
- 10%的概率:保持不变。这进一步迫使模型不仅仅依赖
[MASK]
标记来识别被预测的词,而是从完整的上下文信息中进行推断。(举一反三,而不是只会做题)。在这10%的情况下,模型需要预测的那个词并没有被替换成[MASK]
。它依然以其原始形式存在于句子中。但模型的目标仍然是预测它!这意味着模型不能仅仅依赖[MASK]
标记来知道“这里需要预测”。它必须通过分析整个句子中所有其他词语的完整上下文来推断出这个词本来应该是什么,即使这个词就在那里,也好像它被“隐藏”了一样。
补充:设想一下,如果BERT总是把要预测的词替换成特殊的 [MASK]
标记(比如100%的概率),那么模型很快就会学会一个简单的规则:只要看到 [MASK]
,我就要预测一个词。这样做会带来一个问题:过度依赖 [MASK]
标记: 模型可能会过于依赖 [MASK]
这个显式信号来知道“这里需要预测一个词”。它可能不会真正深入地学习如何仅凭周围的完整上下文信息来推断一个词。换句话说,它可能在某种程度上“偷懒”,而不是真正理解语言的深层模式。
下一句预测 (Next Sentence Prediction, NSP)
BERT的另一个预训练任务是理解句子之间的关系。
BERT的输入可以是输入两个句子 ( [CLS], 句子1, [SEP], 句子2, [SEP] ) , [SEP]的token标记用于分割句子。
- 操作方式: 模型会输入两个句子(Segment A 和 Segment B)。
- 训练目标: 预测 Segment B 是否真的是 Segment A 的下一句。
- 数据构造: 在训练数据中,50%的样本是真实的下一句对,另外50%是随机从语料库中抽取的句子对。
NSP任务让BERT学会了理解文本的连贯性和篇章结构,这对于问答、文本蕴含、自然语言推理等需要判断句子间逻辑关系的任务非常重要。
BERT的输入表示
它通过特殊的方式对输入进行编码:
- 分词(Tokenization): 通常使用WordPiece分词器,将词语拆分为更小的子词单元。token 不恒为 word,这一点需清楚,对于短单词,才可能 token == word。
- 特殊标记:
[CLS]
(Classification) 标记:每个输入序列的开头都会加上这个特殊标记。它对应的最终隐藏状态(向量)被用作整个序列的聚合表示,常用于分类任务。[SEP]
(Separator) 标记:用于分隔两个句子(如A和B),并在单个句子输入的末尾。
- 词元嵌入(Token Embeddings):最基础的嵌入,代表了文本序列中的每个词元(token)本身的语义信息。
- 段落嵌入(Segment Embeddings): 用于区分序列中的不同句子(例如,A句的所有token都有一个
A
的段落嵌入,B句有B
的段落嵌入),帮助模型理解句子边界。基于SEP标记来确定Segment Embeddings的值,如只有一个[SEP]标记的话,[SEP]标记前的Segment Embeddings的值为0,如果有两个[SEP],那么第二个[SEP]和第一个[SEP]之间的句子的Segment Embeddings的值为1。类似于数组的下标索引,现在数组中每个元素的值变成了一个句子而已。 - 位置嵌入(Position Embeddings): 由于Transformer的自注意力机制是并行处理的,不包含序列顺序信息,因此需要位置嵌入来告知模型每个词在序列中的位置。如:如果没有额外的信息,模型无法区分“猫追狗”和“狗追猫”这样的序列。原版的Transformer是使用固定、周期性的正弦/余弦函数生成位置编码不同,BERT采用的是可学习的(Learned)位置嵌入。BERT在预训练过程中,会为每个可能的序列位置学习一个唯一的、随机初始化的向量。这些位置嵌入向量像词元嵌入一样,被存储在一个查找表(lookup table)中,模型在训练过程中会根据任务和数据特点来优化这些向量。即词与词之间的先后顺序是模型在大量数据预训练过程中自己学习到了,并存储为一个tabel,你后续获得对应token的时候,将其放到table中进行查找就能知道这个token应该是在句子的哪些位置。
这三类嵌入(Token Embeddings + Position Embeddings + Position Embeddings)相加,形成了BERT模型的最终输入Embedding,随后就是Encoding部分。
RoBERTa
RoBERTa全称Robustly Optimized BERT Pretraining Approach,其是基于BERT的优化,模型架构仍然是Transformer, 只是对BERT的预训练方法进行了系统性优化,以提高模型的性能和鲁棒性。
与BERT相比,主要区别在于:
- 更大的数据量、更长的训练时间、更大的批次大小。RoBERTa使用了160GB的训练数据,远超BERT所使用的16GB的训练数据。数据量的大小所带来的模型性能提升。
- 移除下一句预测任务(NSP),专注于单个句子中MLM任务的分析。RoBERTa 团队经实验发现,NSP 任务收益有限,甚至干扰模型对句内语义捕捉。RoBERTa 果断移除 NSP,仅靠 MLM 任务预训练。实践表明,精简任务结构后,模型聚焦句内信息,语义表征更精准。
- 采用动态掩码。在BERT中, 采用的是静态掩码(Static Masking)。在数据预处理阶段,会预先对训练数据进行一次词语遮蔽,并生成固定好的掩码模式。这意味着在整个多轮(epochs)训练中,同一个句子总是以相同的掩码模式出现。RoBERTa 采用动态掩码(Dynamic Masking)。在每个训练批次(batch)送入模型之前,都会动态地生成新的掩码模式。这意味着同一个句子在不同的训练步中,可能会有不同的词语被遮蔽。
eg:
对于句子:"我 喜欢 学习 自然语言处理。"
对于BERT(静态掩码):
- 在整个训练过程中(比如训练了10个epoch),这个句子可能总是被遮蔽成: "我 喜欢
[MASK]
自然语言处理。" (模型预测 "学习")
对于RoBERTa(动态掩码):
- Epoch 1: "我 喜欢
[MASK]
自然语言处理。" - Epoch 2: "我 喜欢 学习
[MASK]
语言处理。" - Epoch 3: "我
[MASK]
学习 自然语言处理。" - ...每次训练,模型都需要重新从不同角度理解上下文来预测被遮蔽的词。
BERTweet
BERTweet,顾名思义,其实基于Tweet数据+BERT结构预训练所得出的模型。与BERT和RoBERTa相比,可以用一句话进行表述,BERTweet是基于RoBERTa的预训练范式,但在数据、分词和预处理上进行了Twitter领域特有的适配,即RoBERTa预训练范式 + 针对推文的数据预训练。
BERTweet充分体现了领域适应性,通过在Twitter数据上的大规模预训练,并结合专门的分词和预处理策略,使其能够更精准地捕捉推文的语言特征,从而在情感分析、情绪识别、话题分类等Twitter相关的NLP任务上,显著超越了未经领域适配的BERT和RoBERTa模型。
LLama
LLama,全称 Large Language Model Meta AI,在西班牙语中意为“羊驼”,因此LLama又被称之为羊驼。
LLama的初衷是认为最佳性能不是通过堆模型参数量实现的,而是通过在更多数据上训练的较小模型实现的。
补充说明:一般而言,模型越大,效果越好。然而有文献指出,当给定计算量的预算之后,最好的performance,并不是最大的模型,而是在一个小模型上用更多的数据进行训练。针对给定的计算量预算,scaling laws可以计算如何选择数据量的大小和模型的大小。然而这忽略了inference的预算,而这一点在模型推理时非常关键。当给定一个模型performance目标之后,最好的模型不是训练最快的模型,而是推理最快的模型。尽管在这种情况下,训练一个更大的模型成本会更低。
文献中推荐,训练一个 10B 的模型,需要 200B 的 tokens,而本文的实验发现,一个7B的模型,经过 1T tokens 训练之后,performance 仍然在增加。本文的目标在于,通过在超大规模的数据上训练,给出一系列可能最好 performance 的 LLM。
LLama是一个大规模的生成式语言模型,其模型结构与GPT等生成模型类似,也是基于Transformer-decoder-only的架构进行部分模块的优化。
有以下三个改进:
- 使用了GPT3的预标准化。为了提高训练稳定性,对每个Transformer子层的输入进行归一化,而不是对输出进行归一化。使用由RMSNorm 归一化函数。
-
用 SwiGLU 激活函数替换 ReLU 非线性,以提高性能。使用
的维度替代PaLM中的
-
类似GPTNeo,删除了绝对位置嵌入,而是添加了旋转位置嵌入(RoPE)。
针对第一点,在进行注意力机制的计算前,即在进入Transformer子层前对Embedding进行了归一化。并且归一化函数从LayerNorm改为使用RMSNorm。
RMSNorm是LayerNorm的变体,LayerNorm是通过调整当前层输入的均值和方差来解决内部协变量偏移问题,防止梯度消失或爆炸,并使训练对学习率和初始化更加鲁棒。RMSNorm,全称 Root Mean Square Layer Normalization (均方根层归一化),与LayerNorm相比,RMSNorm移除了均值计算,只关注通过均方根(RMS)进行重新缩放。
RMS的公式为
是输入向量,
是输入向量中的第
个元素。
输入向量的维度(即特征的数量)。
表示输入向量的均方差
代表可学习的缩放(gain)参数
是一个很小的参数,一般设为10^-5,主要作用是为了计算稳定。
RMSNorm与LayerNorm相比,没了偏置项和移除了均值。
针对第二点,
相关文章:
Text models —— BERT,RoBERTa, BERTweet,LLama
BERT 什么是BERT? BERT,全称Bidirectional Encoder Representations from Transformers,BERT是基于Transformer的Encoder(编码器)结构得来的,因此核心与Transformer一致,都是注意力机制。这种…...
CodeBuddy初探
回顾Trae 上一篇博客Trae IDE和VSCode Trae插件初探-CSDN博客,我们进行了TraeIDE和Trae插件初探,给了Trae这样一个任务: 生成一个to do list清单web页面,采用vue实现,可以在页面上进行todolist进行增删改查。 Trae的…...
spark数据处理练习题详解【上】
1. (单选题) scala中属于序列的可变的集合,可以添加,删除元素的是() A.Array B.List C.Tuple D.ListBuffer 答案及解析:D 在Scala中,属于序列的可变集合,可以添加和删除元素的是ÿ…...
sparkSQL读入csv文件写入mysql(2)
(二)创建数据库和表 接下来,我们去创建一个新的数据库,数据表,并插入一条数据。 -- 创建数据库 CREATE DATABASE spark; -- 使用数据库 USE spark;-- 创建表 create table person(id int, name char(20), age int);-- …...
产品周围的几面墙
不能把排序,当单选题做。 2025年的杭州咖啡馆,味道最浓的不是咖啡,是聊各种项目和创业的卷味。 在过去几年,聊项目的也不少,那时候带着更加浓烈的自信和松弛感,不过今年略带几分忐忑和试探的口吻。 看到网…...
【锂电池剩余寿命预测】LSTM长短期记忆神经网络锂电池剩余寿命预测(Pytorch完整源码和数据)
目录 效果一览程序获取程序内容代码分享效果一览 程序获取 获取方式一:文章顶部资源处直接下载:...
螺旋矩阵--LeetCode
题目 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 1: 输入:matrix [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,2,3,6,9,8,7,4,5]示例 2: 输入:matrix [[…...
湖北理元理律师事务所:债务管理的社会价值探索
债务问题从来不是孤立的经济事件,其背后牵涉家庭稳定、社会信用体系乃至区域经济发展。湖北理元理律师事务所通过五年服务数据发现:科学债务规划可使单个家庭挽回约23%的可支配收入,间接降低离婚率、心理健康问题发生率等社会成本。 债务优化…...
知识图谱(KG)与大语言模型(LLM)
知识图谱(KG)以其结构化的知识表示和推理能力,为大语言模型(LLM)的“幻觉”、知识更新滞后和可解释性不足等问题提供了有力的解决方案。反过来,LLM的强大文本理解和生成能力也为KG的构建、补全、查询和应用…...
LLM大语言模型系列1-token
一,什么是token 1,什么是token: 参考:https://en.wikipedia.org/wiki/Token https://en.wikipedia.org/wiki/Lexical_analysis#Token 我们有很多描述token的解释,建议是汇总在一起进行综合理解: 1️⃣To…...
数据清洗-案例
四)实现代码 在之前的项目的基础之上,重写去写一个包,并创建两个类:WebLogMapper和WebLogDriver类。 (1)编写WebLogMapper类 package com.root.mapreduce.weblog; import java.io.IOException; import…...
项目的部署发布和访问的流程
首先打包项目: npm run build 打包后的文件会生成在dist文件夹中,将dist文件夹需要放到服务器里面,意味着服务有dist静态资源(index.html,css/,js/,img/) 用户在浏览器输入域名&am…...
人工智能、机器学习、深度学习定义与联系
人工智能、机器学习、深度学习定义与联系目录 一、人工智能(Artificial Intelligence, AI)1、定义2、特征:3、关键阶段的概述:1. 萌芽期(1940s–1950s):理论奠基2. 形成期(1950s–19…...
Gartner《如何将生成式人工智能(GenAI)集成到应用架构》学习心得
针对软件架构师、技术专业人士如何更好的把 GenAI 如何融入解决方案,提升用户体验、生产力并带来差异化成果的趋势,Gartner发布了《Integrating GenAI Into Your Application Architecture》研究报告。 报告首先介绍了 GenAI 的发展背景,指出其已成为主流趋势,大型语言模型…...
vscode中Debug c++
在vscode中Debug ros c程序 1 在Debug模式下编译 如果用命令行catkin_make,在输入catkin_make时加上一个参数: catkin_make -DCMAKE_BUILD_TYPEDebug 或者直接修改CMakelist.txt,添加以下代码: SET(CMAKE_BUILD_TYPE "D…...
c++从入门到精通(六)--特殊工具与技术-完结篇
特殊工具与技术-完结篇 控制内存分配 重载new和delete: 如果应用程序希望控制内存分配的过程,则它们需要定义自己的operator new函数和operator delete函数。当自定义了全局的operator new函数和operator delete函数后,我们就担负起了控…...
原型链的详细解释及使用场景
一、原型链的概念 原型链是JavaScript实现继承和属性共享的核心机制。每个对象都有一个内部属性[[Prototype]](可通过proto访问),指向其原型对象。当访问对象的属性时,若对象自身不存在该属性,则会沿着原型链向上查找…...
OpenCL C C++核心对象与属性对比
基础对象对应关系 OpenCL C 对象OpenCL C 对应类型创建函数示例cl::Platformcl_platform_idclGetPlatformIDs(1, &platform, NULL)cl::Devicecl_device_idclGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL)cl::Contextcl_contextclCreateContext(NULL,…...
Azure 机器学习初学者指南
Azure 机器学习初学者指南 在我们的初学者指南中探索Azure机器学习,了解如何设置、部署模型以及在Azure生态系统中使用AutoML & ML Studio。Azure 机器学习 (Azure ML) 是一项全面的云服务,专为机器学习项目生命周期而设计&am…...
一文读懂----Docker 常用命令
Docker 是一个强大的容器化平台,广泛用于开发、测试和生产环境。通过 Docker 命令行工具(CLI),我们可以轻松管理容器、镜像、网络和卷等资源。本文将详细介绍 Docker 的常用命令,带你熟练掌握 Docker 的核心操作命令。…...
React 19 中的useRef得到了进一步加强。
文章目录 前言一 useRef 的核心原理1.1 为什么需要 useRef?1.2 基本语法 二、React 19 中 useRef 的常见用法2.1 访问 DOM 元素2.2 保存跨渲染的数据 三、React 19 中的改进ref 作为一个属性案例演示(触发子组件焦点事件) 注意 总结 前言 在 React 的世界里&#x…...
报错System.BadImageFormatException:“试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)”
this.hWindowControl_Player new HalconDotNet.HWindowControl();报错System.BadImageFormatException:“试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)” System.BadImageFormatException 错误通常是由于平台架构不匹配导致的。它意味着你正在尝试在一个平台上加…...
【图像处理基石】OpenCV中都有哪些图像增强的工具?
OpenCV 图像增强工具系统性介绍 OpenCV 提供了丰富的图像增强工具,主要分为以下几类: 亮度与对比度调整 线性变换(亮度/对比度调整)直方图均衡化自适应直方图均衡化(CLAHE) 滤波与平滑 高斯滤波中值滤波双…...
Nordic 的RTC(Real-time counter)的介绍
目录 概述 1 RTC(Real-time counter)介绍 1.1 框架结构 1.2 时钟源 1.3 分辨率与溢出和precaler 2 寄存器功能介绍 2.1 计数寄存器 2.2 事件控制功能 2.3 比较功能 2.4 读取COUNTER寄存器 概述 本文主要介绍Nordic 的RTC(Real-time…...
【数据结构】2-2-2 顺序表的插入删除查找
数据结构知识点合集 知识点 顺序表的插入 ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。 /*在顺序表L的第i个位置插入元素e*/ bool ListInsert(SqList &L,int i,int e) {/*判断i的范围是否有效*/if(i<0||i>L.length)return fals…...
【免杀】C2免杀技术(五)动态API
一、什么是动态API 在C2免杀领域中,“动态API” 主要指的是绕过静态检测的一种技术手段,其本质是运行时动态解析和调用Windows API函数,而不是在程序编译阶段就明确引用这些API。这种方式可以有效躲避静态分析工具和杀软的签名识别。 为什么…...
77.数据大小端赋值的差异与联系
上述赋值a定义为大端模式 a[7] a[6] a[5] a[4] a[3] a[2] a[1] a[0] 上述赋值b定义为小端模式 a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] 因为5的二进制数…...
GO语言语法---switch语句
文章目录 基本语法1. 特点1.1 不需要break1.2 表达式可以是任何类型1.3 省略比较表达式1.4 多值匹配1.5 类型switch1.6 case穿透1.7 switch后直接声明变量1.7.1 基本语法1.7.2 带比较表达式1.7.3 不带比较表达式1.7.4 结合类型判断 1.8 switch后的表达式必须与case语句中的表达…...
PH热榜 | 2025-05-16
1. Tolt 标语:专为SaaS初创公司打造的一体化联盟营销软件 介绍:Tolt帮助SaaS初创公司启动和发展联盟计划。它提供自动化的支付、欺诈保护、与多种平台的无缝集成(包括Stripe、Paddle和Chargebee),还有一个品牌化的联…...
Java正则表达式:从基础到高级应用全解析
Java正则表达式应用与知识点详解 一、正则表达式基础概念 正则表达式(Regular Expression)是通过特定语法规则描述字符串模式的工具,常用于: 数据格式验证文本搜索与替换字符串分割模式匹配提取 Java通过java.util.regex包提供支持,核心类…...
iOS 初识RunLoop
iOS 初识RunLoop 文章目录 iOS 初识RunLoopRunLoop的概念RunLoop的功能RunLoop和线程的关系RunLoop的结构ModeObserverTimer 和 source小结 RunLoop的核心RunLoop的流程RunLoop的应用AutoreleasePool响应触控事件刷新界面常驻线程网络请求NSTimer 和 CADisplayLinkNSTimerGCDTi…...
备忘录模式
1.意图 备忘录模式是一种行为型设计模式,允许在不破坏封装的特性前提,获取并保存一个对象的内部状态,后续需要时恢复该状态。核心是将对象的状态存储在一个独立的备忘录对象中,并在需要时恢复。 2.模式类型 行为型对象设计模式 …...
UCOS 嵌入式操作系统
UCOS 嵌入式操作系统是一款在嵌入式领域应用广泛且具有重要地位的实时操作系统,以下是对它的详细介绍。 发展历程 初始版本诞生:UCOS 最早由美国嵌入式系统专家 Jean J. Labrosse 于 1991 年开始开发。当时他在项目中需要一个合适的实时操作系统&#…...
redis读写一致问题
title: redis读写一致问题 date: 2025-05-18 11:11:31 tags: redis categories: redis的问题方案 Redis读写一致问题 条件: 数据库此时的数据为10,redis此时的数据也为10 业务流程: 操作数据库使得数据库的数据为20,删除redis里面的数据保证读写一致 先删缓存…...
Redis实现分布式锁的进阶版:Redisson实战指南
一、为什么选择Redisson? 在上一篇文章中,我们通过Redis原生命令实现了分布式锁。但在实际生产环境中,这样的基础方案存在三大痛点: 锁续期难题:业务操作超时导致锁提前释放不可重入限制:同一线程无法重复…...
标准库、HAl库和LL库(PC13初始化)
标准库 (Standard Peripheral Library) c #include "stm32f10x.h"void GPIO_Init_PC13(void) {GPIO_InitTypeDef GPIO_InitStruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);GPIO_InitStruct.GPIO_Pin GPIO_Pin_13;GPIO_InitStruct.GPIO_Mode GPIO_…...
第二章:安卓端启动流程详解与疑难杂症调试手册
想让一个安卓项目跑起来,从表面看无非就是:双击打开、连接真机、点击运行。 但是到了互动娱乐组件项目里,事情就变成了:点击运行→等待→黑屏→白屏→强制退出→LogCat爆炸→你怀疑人生。 本章就来系统性解决几个问题࿱…...
备份C#的两个类
GuestIP依赖项: using System.Data.SQLite; //这是第三方依赖项,要从nuget下载 static class GuestIP {public static void ReadLastGuestIP(string constr "Data Sourceguestip_log.db;"){using (var connection new SQLiteConnection(co…...
通过串口设备的VID PID动态获取串口号(C# C++)
摘要 本篇文章主要介绍分别通过C#和C++使用设备VID PID如何动态获取COM口 目录 1 简述 2 VID PID查看方式 3 C#实现通过串口设备的VID PID动态获取串口号 3.1 辅助类实现 3.2 调用实例 4 C++实现通过串口设备的VID PID动态获取串口号 4.1 辅助类实现 4.2 调用实例 1 简…...
C语言指针深入详解(二):const修饰指针、野指针、assert断言、指针的使用和传址调用
目录 一、const修饰指针 (一)const修饰变量 (二)const 修饰指针变量 二、野指针 (一)野指针成因 1、指针未初始化 2、指针越界访问 3、指针指向的空间释放 (二)如何规避野指…...
《P5283 [十二省联考 2019] 异或粽子》
题目描述 小粽是一个喜欢吃粽子的好孩子。今天她在家里自己做起了粽子。 小粽面前有 n 种互不相同的粽子馅儿,小粽将它们摆放为了一排,并从左至右编号为 1 到 n。第 i 种馅儿具有一个非负整数的属性值 ai。每种馅儿的数量都足够多,即小粽…...
C#自定义扩展方法 及 EventHandler<TEventArgs> 委托
有自定义官方示例链接: 如何实现和调用自定义扩展方法 - C# | Microsoft Learn 1.静态类 2.静态方法 3.第一参数固定为this 要修改的类型,后面才是自定的参数 AI给出的一个示例:没有自定义参数 、有自定义参数的 using System; using System.Colle…...
oracle 资源管理器的使用
14.8.2资源管理器的使用 资源管理器控制CPU资源使用说明: 第一种分配方法:EMPHASIS CPU 分配方法确定在资源计划中对不同使用者组中的会话的重视程度。CPU占用率的分配级别为从1 到8,级别1 的优先级最高。百分比指定如何将CPU 资源分配给每…...
(二十一)Java集合框架源码深度解析
一、集合框架概述 Java集合框架(Java Collections Framework, JCF)是Java语言中用于存储和操作数据集合的一套标准架构。它提供了一组接口、实现类和算法,使开发者能够高效地处理各种数据结构。 1.1 集合框架的历史演变 在Java 1.2之前,Java只有几种简…...
spark数据的提取和保存
Spark数据提取和保存 一、数据提取(读取数据) 1. 读取文件(文本、CSV、JSON等) scala // 读取文本文件 val textData spark.read.text("路径/文件.txt") // 读取CSV文件(带表头) val csvD…...
Graphics——基于.NET 的 CAD 图形预览技术研究与实现——CAD c#二次开发
一、Graphics 类的本质与作用 Graphics 是 .NET 框架中 System.Drawing 命名空间下的核心类,用于在二维画布(如 Bitmap 图像)上绘制图形、文本或图像。它相当于 “绘图工具”,提供了一系列方法(如 DrawLine、FillElli…...
vue3_flask实现mysql数据库对比功能
实现对mysql中两个数据库的表、表结构、表数据的对比功能, 效果如下图 基础环境请参考 vue3flasksqlite前后端项目实战 代码文件结构变化 api/ # 后端相关 ├── daos/ │ ├── __init__.py │ └── db_compare_dao.py # 新增 ├── routes/ │ ├── _…...
【数据结构】2-3-1单链表的定义
数据结构知识点合集 知识点 单链表存储结构 优点:不要求大片连续空间,改变容量方便;缺点:不可随机存取,要耗费一定空间存放指针 /*单链表节点定义*/ typedef struct LNode{ElemType data;struct LNode *next; }LNo…...
面试题总结一
第一天 1. 快速排序 public class QuickSort {public static void quickSort(int[] arr, int low, int high) {if (low < high) {// 分区操作,获取基准元素的最终位置int pivotIndex partition(arr, low, high);// 递归排序基准元素左边的部分quickSort(arr, …...
Ubuntu24.04下安装ISPConfig全过程记录
今天在网上看到ISPConfig,觉得不错,刚好手里又有一台没用的VPS,就顺手安装一个玩玩。具体安装步骤如下: 一、配置服务器hosts及hostname 【安装时候需要检查】 使用root账号登录VPS后 先安装vim编辑器,然后编辑hosts࿰…...