当前位置: 首页 > news >正文

从零训练LLM-1.训练BPE

文章目录

    • BPE 简介
    • BPE (Byte-Pair Encoding) 算法训练流程
    • BPE 编码流程
    • BPE 评估
    • 代码
  • 参考

本文基于 HF -tokenizer 训练,更便捷


BPE 简介

分词器将单词从自然语言通过“词典”映射到0, 1, 36这样的数字,可以理解为数字就代表了单词在“词典”中的页码。 可以选择自己构造词表训练一个“词典”或者选择比较出名的开源大模型分词器(直接将 tokenizer 的模型文件复制过来,然后 tokenizer.from_pretrained), 正如同直接用新华/牛津词典的优点是token编码压缩率很好,缺点是页数太多,动辄数十万个词汇短语; 自己训练的分词器,优点是词表长度和内容随意控制,缺点是压缩率很低(例如"hello"也许会被拆分为"h e l l o" 五个独立的token),且生僻词难以覆盖。 “词典”的选择固然很重要,LLM的输出本质上是SoftMax到词典N个词的多分类问题,然后通过“词典”解码到自然语言。 因为模型体积需要严格控制,为了避免模型头重脚轻(词嵌入embedding层参数在LLM占比太高),所以词表长度短益善。


BPE (Byte-Pair Encoding) 算法训练流程

  1. 准备语料库,将文本拆分为基本单位(通常是字符或字节)

  2. 统计所有相邻单元对的频率

  3. 选择最高频率的单元对合并为新的单元

  4. 更新语料库,替换所有该单元对为新单元

  5. 重复步骤2-4直到达到预设的词表大小或合并次数

BPE 编码流程

  1. 把文本先拆成最小单位(比如单个字母或字节)

  2. 识别文本中的特殊token(如, ),这些特殊token会直接映射到对应ID

  3. 对于普通文本部分:

    a. 初始化为基本单位序列

    b. 扫描当前序列中的所有相邻单位对

    c. 查找这些单位对是否在训练时学到的"合并规则表"中

    d. 优先选择合并后ID值最小的单位对进行合并(即优先合并更基础、更短的单位)

    e. 合并后继续重复b-d步骤,直到没有可合并的单位对

  4. 将特殊token和处理好的普通文本部分组合,得到完整的token序列

  5. 最后得到的单位序列就是文本的token编码结果


BPE 评估

评估 BPE 分词器质量的主要方法包括:

  1. 分词质量指标
  • 词表利用率: 检查分词后的词表中各 token 使用频率分布,好的分词器应当避免出现大量低频或未使用的 token
  • 平均 token 长度: 较好的分词器通常能将文本压缩为更少的 token
  • 未知词率 (OOV率): 在测试集上计算未登录词(需用 表示)的比例,越低越好
  1. 下游任务评估
  • 困惑度 (Perplexity): 在语言模型上测试,较低的困惑度表示分词更有效
  • 下游任务表现: 在翻译、分类等任务中比较不同分词方案的效率差异
def eval_tokenizer():# 加载预训练的tokenizertokenizer = AutoTokenizer.from_pretrained("./EmoLLM_tokenizer")# 准备测试数据test_texts = ["你好,我最近感到有些焦虑,不知道该怎么办。","我对未来感到迷茫,希望能得到一些建议。","最近工作压力很大,感觉睡不好觉。"]# 1. 计算平均token长度token_lengths = []for text in test_texts:tokens = tokenizer.encode(text)token_lengths.append(len(tokens))avg_token_length = sum(token_lengths) / len(token_lengths)print(f"平均token长度: {avg_token_length:.2f}")# 2. 检查词表利用率all_tokens = []for text in test_texts:tokens = tokenizer.encode(text)all_tokens.extend(tokens)unique_tokens = set(all_tokens)vocab_size = len(tokenizer)utilization_rate = len(unique_tokens) / vocab_size * 100print(f"词表利用率: {utilization_rate:.2f}%")# 3. 分析最常见的tokensfrom collections import Countertoken_counter = Counter(all_tokens)print("最常见的10个token:")for token_id, count in token_counter.most_common(10):token = tokenizer.decode([token_id])print(f"  Token: '{token}', ID: {token_id}, 出现次数: {count}")# 4. 检查长文本的编码/解码一致性long_text = " ".join(test_texts)encoded = tokenizer.encode(long_text)decoded = tokenizer.decode(encoded)print(f"编码/解码一致性: {long_text == decoded}")
  • 也可以与其他 tokenizer 进行比较
def compare_tokenizers(test_text):# 加载不同的tokenizer进行比较tokenizers = {"EmoLLM": AutoTokenizer.from_pretrained("./EmoLLM_tokenizer"),"GPT2": AutoTokenizer.from_pretrained("gpt2"),"BERT": AutoTokenizer.from_pretrained("bert-base-uncased")}print(f"文本: {test_text}")for name, tok in tokenizers.items():tokens = tok.encode(test_text)print(f"{name} token数量: {len(tokens)}")# 可视化分词结果if hasattr(tok, "tokenize"):print(f"{name} 分词结果: {tok.tokenize(test_text)}")else:print(f"{name} 分词结果: {[tok.decode([t]) for t in tokens]}")

代码

import json
import os
import randomfrom tokenizers import (Tokenizer, decoders, models, normalizers,pre_tokenizers, processors, trainers)
from transformers import AutoTokenizer# 设置随机种子以确保结果可复现
random.seed(42)# BPE (Byte-Pair Encoding) 算法训练流程:
# 1. 准备语料库,将文本拆分为基本单位(通常是字符或字节)
# 2. 统计所有相邻单元对的频率
# 3. 选择最高频率的单元对合并为新的单元
# 4. 更新语料库,替换所有该单元对为新单元
# 5. 重复步骤2-4直到达到预设的词表大小或合并次数# BPE 编码流程:
# 1. 把文本先拆成最小单位(比如单个字母或字节)
# 2. 识别文本中的特殊token(如<s>, </s>),这些特殊token会直接映射到对应ID
# 3. 对于普通文本部分:
#    a. 初始化为基本单位序列
#    b. 扫描当前序列中的所有相邻单位对
#    c. 查找这些单位对是否在训练时学到的"合并规则表"中
#    d. 优先选择合并后ID值最小的单位对进行合并(即优先合并更基础、更短的单位)
#    e. 合并后继续重复b-d步骤,直到没有可合并的单位对
# 4. 将特殊token和处理好的普通文本部分组合,得到完整的token序列
# 5. 最后得到的单位序列就是文本的token编码结果def train_tokenizer():# 读取JSONL文件并提取文本数据def read_texts_from_jsonl(file_path):with open(file_path, 'r', encoding='utf-8') as f:for line in f:data = json.loads(line)yield data['text']data_path = '../dataset/pretrain_hq.jsonl'# 初始化tokenizertokenizer = Tokenizer(models.BPE())# 预分词器负责将原始文本进行初步分割,为后续的 BPE 合并操作做准备add_prefix_space=False 表示不在每个序列前添加空格tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)# 定义特殊tokenspecial_tokens = ["<unk>", "<s>", "</s>"]# 设置训练器并添加特殊tokentrainer = trainers.BpeTrainer(vocab_size=6400,special_tokens=special_tokens,  # 确保这三个token被包含show_progress=True,# 使用字节级别的基础字符集作为初始词汇,它包含了256个可能的字节值(0-255)对应的Unicode字符表示initial_alphabet=pre_tokenizers.ByteLevel.alphabet())# 读取文本数据texts = read_texts_from_jsonl(data_path)# 训练tokenizertokenizer.train_from_iterator(texts, trainer=trainer)# 设置解码器tokenizer.decoder = decoders.ByteLevel()# 检查特殊token的索引# 确保三个特殊token被正确分配了预期的ID:# <unk>应该是ID 0 - 用于表示未知词汇assert tokenizer.token_to_id("<unk>") == 0# <s>应该是ID 1 - 用于表示文本开始assert tokenizer.token_to_id("<s>") == 1# </s>应该是ID 2 - 用于表示文本结束assert tokenizer.token_to_id("</s>") == 2# 保存tokenizertokenizer_dir = "./EmoLLM_tokenizer"os.makedirs(tokenizer_dir, exist_ok=True)tokenizer.save(os.path.join(tokenizer_dir, "tokenizer.json"))tokenizer.model.save("./EmoLLM_tokenizer")# 手动创建配置文件config = {"add_bos_token": False,"add_eos_token": False,"add_prefix_space": False,"added_tokens_decoder": {# 配置 <unk> 标记 (未知词标记)# 索引为0,用于表示词表外的词或字符"0": {"content": "<unk>",  # 标记的实际内容"lstrip": False,     # 是否从左侧移除空白"normalized": False,  # 是否规范化"rstrip": False,     # 是否从右侧移除空白"single_word": False,  # 是否作为单个词处理"special": True      # 标记为特殊标记,在解码时会特殊处理},# 配置 <s> 标记 (序列开始标记)# 索引为1,用于标识文本序列的开始"1": {"content": "<s>","lstrip": False,"normalized": False,"rstrip": False,"single_word": False,"special": True},# 配置 </s> 标记 (序列结束标记)# 索引为2,用于标识文本序列的结束"2": {"content": "</s>","lstrip": False,"normalized": False,"rstrip": False,"single_word": False,"special": True}},"additional_special_tokens": [],"bos_token": "<s>","clean_up_tokenization_spaces": False,"eos_token": "</s>","legacy": True,"model_max_length": 32768,"pad_token": "<unk>","sp_model_kwargs": {},"spaces_between_special_tokens": False,"tokenizer_class": "PreTrainedTokenizerFast","unk_token": "<unk>",# 配置聊天模板 - 使用Jinja2模板格式定义模型输入的格式化方式"chat_template": "{% if messages[0]['role'] == 'system' %}{% set system_message = messages[0]['content'] %}{{ '<s>system\\n' + system_message + '</s>\\n' }}{% else %}{{ '<s>system\\n你是 EmoLLM,是一个完全开源的心理健康大模型。</s>\\n' }}{% endif %}{% for message in messages %}{% set content = message['content'] %}{% if message['role'] == 'user' %}{{ '<s>user\\n' + content + '</s>\\n<s>assistant\\n' }}{% elif message['role'] == 'assistant' %}{{ content + '</s>' + '\\n' }}{% endif %}{% endfor %}"# 聊天模板说明:# 1. 如果第一条消息是系统消息,将其作为系统指令;否则使用默认系统消息# 2. 用户消息格式: <s>user\n{用户内容}</s>\n<s>assistant\n# 3. 助手消息格式: {助手内容}</s>\n# 4. 特殊标记<s>和</s>用于标记消息的开始和结束}# 保存配置文件with open(os.path.join(tokenizer_dir, "tokenizer_config.json"), "w", encoding="utf-8") as config_file:json.dump(config, config_file, ensure_ascii=False, indent=4)print("Tokenizer training completed and saved.")def eval_tokenizer():# 加载预训练的tokenizertokenizer = AutoTokenizer.from_pretrained("./EmoLLM_tokenizer")messages = [{"role": "system", "content": "你是一个优秀的聊天机器人,总是给我正确的回应!"},{"role": "user", "content": '你来自哪里?'},{"role": "assistant", "content": '我来自地球'}]new_prompt = tokenizer.apply_chat_template(messages,tokenize=False)print(new_prompt)# 获取实际词汇表长度(包括特殊符号)actual_vocab_size = len(tokenizer)print('tokenizer实际词表长度:', actual_vocab_size)model_inputs = tokenizer(new_prompt)print('encoder长度:', len(model_inputs['input_ids']))input_ids = model_inputs['input_ids']response = tokenizer.decode(input_ids, skip_special_tokens=False)print('decoder和原始文本是否一致:', response == new_prompt)def main():train_tokenizer()eval_tokenizer()if __name__ == '__main__':main()

参考

  1. https://github.com/jingyaogong/minimind/blob/master/scripts/train_tokenizer.py
  2. https://github.com/SmartFlowAI/EmoLLM
  3. https://github.com/aJupyter/ThinkLLM

相关文章:

从零训练LLM-1.训练BPE

文章目录 BPE 简介BPE (Byte-Pair Encoding) 算法训练流程BPE 编码流程BPE 评估代码 参考 本文基于 HF -tokenizer 训练&#xff0c;更便捷 BPE 简介 分词器将单词从自然语言通过“词典”映射到0, 1, 36这样的数字&#xff0c;可以理解为数字就代表了单词在“词典”中的页码。…...

shield.io网站|markdown中适用的“徽标”

动态的我还没看是怎么弄&#xff0c;但是应该和静态的差不多&#xff0c;因此本文仅讨论静态徽标 静态徽标效果 创建方法 网址&#xff1a;Shields.io | Shields.io 进入之后点击“Badges”标签进入网页创建徽标的页面&#xff0c;根据文档中对每个属性的介绍在右侧将自己预…...

Vue 3 自定义指令

Vue 3 是一个非常强大的前端框架&#xff0c;它不仅提供了简单易用的 API&#xff0c;还支持多种高级功能&#xff0c;以便开发者根据需要扩展和优化应用。在 Vue 中&#xff0c;自定义指令是一种非常灵活的功能&#xff0c;它允许我们为 DOM 元素添加特定的行为&#xff0c;扩…...

25某团校招后端开发一面

一、进程通信和线程通信方式 进程通信方式 管道&#xff08;Pipe&#xff09; 半双工通信&#xff0c;数据单向流动&#xff0c;仅用于有亲缘关系的进程&#xff08;如父子进程&#xff09;。通过内核缓冲区实现数据传输&#xff0c;如父进程写、子进程读。命名管道&#xff…...

音视频学习(三十四):H264中的宏块

什么是宏块&#xff1f; 在 H.264 中&#xff0c;宏块是编码图像时最小的处理单位。它的核心作用包括&#xff1a; 帧内预测&#xff08;Intra Prediction&#xff09;帧间预测&#xff08;Inter Prediction&#xff09;变换、量化、熵编码等 标准定义&#xff1a; 一个宏块…...

Pandas 中透视表(`pivot_table`)和交叉表(`crosstab`)的区别

Pandas 中透视表&#xff08;pivot_table&#xff09;和交叉表&#xff08;crosstab&#xff09;的区别 核心区别 透视表 (pivot_table) 用于对数据进行 聚合计算&#xff08;如求和、均值、计数等&#xff09;。支持多维度分组&#xff08;行、列、甚至多层索引&#xff09;。…...

Restful风格接口开发

目录 Restful Apifox 介绍 端口号8080怎么来的&#xff1f; 为什么要使用Apifox? Restful 如果请求方式是Post&#xff0c;那我就知道了要执行新增操作&#xff0c;要新增一个用户 如果请求方式是Put&#xff0c;那就代表我要修改用户 具体要对这些资源进行什么样的操…...

20250414| AI:RAG多路召回和融合重排序技术

好的&#xff01;以下是对RAG&#xff08;检索增强生成&#xff09;中多路召回和融合重排序技术的详细解释&#xff0c;结合解释学习的视角&#xff0c;帮助你更好地理解和学习。这些技术是RAG系统的核心组成部分&#xff0c;决定了检索阶段的效果和最终生成答案的质量。我会尽…...

基于时间序列分解与XGBoost的交通通行时间预测方法解析

一、问题背景与数据概览 在城市交通管理系统中,准确预测道路通行时间对于智能交通调度和路径规划具有重要意义。本文基于真实道路传感器数据,构建了一个结合时间序列分解与机器学习模型的预测框架。数据源包含三个核心部分: 道路通行数据(new_gy_contest_traveltime_train…...

论文精度:HeightFormer:基于Transformer的体素高度预测在路边3D目标检测中的应用

论文地址:https://arxiv.org/pdf/2503.10777 1. 背景与问题定义 1.1 路边视觉3D检测的重要性 在自动驾驶领域,车辆端的视觉感知系统面临视角局限性​(如遮挡、短距离感知)和安全挑战。相比之下,​路边摄像头通过高位安装,可覆盖更广的感知范围(如交叉路口、高速公路)…...

华为手机清理大数据的方法

清理手机最大的问题是&#xff0c;手动和自动清理了多次&#xff0c;花费了很长时间&#xff0c;但是只腾挪出来了一点点空间&#xff0c;还是有很大空间无法使用&#xff0c;这篇文章就告诉你怎样做&#xff0c;以花瓣剪辑为例&#xff0c;如下&#xff1a; 删除数据&#xff…...

tcp特点+TCP的状态转换图+time_wait详解

tcp特点TCP的状态转换图time wait详解 目录 一、tcp特点解释 1.1 面向连接 1.1.1 连接建立——三次握手 1.1.2 连接释放——四次挥手 1.2 可靠的 1.2.1 应答确认 1.2.2 超时重传 1.2.3 乱序重排 1.2.4 去重 1.2.5 滑动窗口进行流量控制 1.3 流失服务&#xff08;字节…...

flutter 桌面应用之窗口自定义

在开发桌面软件的时候我们经常需要配置软件的窗口的大小以及位置 我们有两个框架选择:window_manager和bitsdojo_window 对比bitsdojo_window 特性bitsdojo_windowwindow_manager自定义标题栏✅ 支持❌ 不支持控制窗口行为&#xff08;大小/位置&#xff09;✅&#xff08;基本…...

【C++】NAN相关研究

先说结论&#xff1a;NAN对比一切都是false INF 对INF 是true 正无穷与正无穷比较相等&#xff0c;正无穷与负无穷比较不相等 window linux环境下基本相同&#xff0c; debug release基本相同 NAN -NAN INF -INF 不做论述 // TestNan.cpp : 此文件包含 "main" 函数。…...

windows下Git安装及其IDEA配置

1.下载Git安装包 阿里镜像链接&#xff08;建议从这里下载&#xff0c;速度很快&#xff09; git-scm.com&#xff08;官方网站&#xff0c;提供了各个平台&#xff08;Windows、Mac、Linux&#xff09;的安装程序&#xff09; 选择版本号后&#xff0c;在选择此版本的不同包…...

迷你世界脚本脚本常见问题

脚本常见问题 彼得兔 更新时间: 2024-05-22 17:54:44 在查阅开发者学院中的脚本API时&#xff0c;若有任何问题或建议&#xff0c;欢迎通过问卷进行反馈&#xff01;【点我填写问卷】 1.Block中的data在什么地方使用 data使用有具体需求,此处不建议开发者使用。开发者尽可能使…...

2025蓝桥杯C++ A组省赛 题解

昨天打完蓝桥杯本来想写个 p y t h o n python python A A A 组的题解&#xff0c;结果被队友截胡了。今天上课把 C A CA CA 组的题看了&#xff0c;感觉挺简单的&#xff0c;所以来水一篇题解。 这场 B B B 是一个爆搜&#xff0c; C C C 利用取余的性质比较好写&#…...

链接世界:计算机网络的核心与前沿

计算机网络引言 在数字化时代&#xff0c;计算机网络已经成为我们日常生活和工作中不可或缺的基础设施。从简单的局域网&#xff08;LAN&#xff09;到全球互联网&#xff0c;计算机网络将数以亿计的设备连接在一起&#xff0c;推动了信息交换、资源共享以及全球化的进程。 什…...

MySQL 常见存储引擎全解析:InnoDB、MyISAM、Memory 等对比与实战

一、什么是存储引擎&#xff1f; 存储引擎&#xff08;Storage Engine&#xff09;是 MySQL 中负责数据存储与管理的底层模块。不同的存储引擎负责处理表的读写、索引维护、事务支持、崩溃恢复等机制。 在创建表时可以指定使用的存储引擎&#xff1a; CREATE TABLE user (id…...

21天Python计划:零障碍学语法(更新完毕)

目录 序号标题链接day1Python下载和开发工具介绍https://blog.csdn.net/XiaoRungen/article/details/146583769?spm1001.2014.3001.5501day2数据类型、字符编码、文件处理https://blog.csdn.net/XiaoRungen/article/details/146603325?spm1011.2415.3001.5331day3基础语法与…...

Python中NumPy的统计运算

在数据分析和科学计算领域&#xff0c;Python凭借其丰富的库生态系统成为首选工具之一&#xff0c;而NumPy作为Python数值计算的核心库&#xff0c;凭借其高效的数组操作和强大的统计运算功能&#xff0c;广泛应用于机器学习、信号处理、统计分析等场景。本文将系统介绍NumPy在…...

SQL 解析 with as

sql的运行顺序 <select id"getTrendList" parameterType"java.util.HashMap" resultType"java.util.Map"><![CDATA[WITH-- 生成连续年份列表&#xff08;当前年前8年到前1年&#xff09;year_range AS (SELECT EXTRACT(YEAR FROM SYSD…...

07-算法打卡-链表-移除链表-leetcode(203)-第七天

1 题目地址 203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09;203. 移除链表元素 - 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a;[https://assets.leetc…...

抓包神器,自研EtherCAT抓包工具

大家好&#xff0c;博主自研了一款以太网抓包神器&#xff0c;可以用于EtherCAT抓包。 把抓包工具接入以太网总线中&#xff0c;就能正常使用了。 上位机软件采用wireshark。 开启以下协议 抓包截图如下 时间戳的精度为5ns。...

五、adb常用命令

SDK路径下的 \Android\Sdk\platform-tools\adb.exe adb devices 查看连接的设备 adb shell getprop ro.build.version.release 查看系统版本 adb shell dumpsys window windows | findstr mFocusedApp 获取正在运行的app启动包名 结果为空&#xff0c;我不知道是不是Android…...

Java第四节:idea在debug模式夏改变变量的值

作者往期文章 Java第一节&#xff1a;debug如何调试程序&#xff08;附带源代码&#xff09;-CSDN博客 Java第二节&#xff1a;debug如何调试栈帧链&#xff08;附带源代码&#xff09;-CSDN博客 Java第三节&#xff1a;新手如何用idea创建java项目-CSDN博客 步骤一 在需要修改…...

Java学习手册:Java反射与注解

Java反射&#xff08;Reflection&#xff09;和注解&#xff08;Annotation&#xff09;是Java语言中两个强大的特性&#xff0c;它们在框架开发和复杂应用中扮演着重要角色。反射允许程序在运行时检查和操作类、对象、接口、字段和方法&#xff0c;而注解则提供了一种元数据形…...

21 天 Python 计划:MySQL事务四大隔离级别深度剖析

文章目录 一、事务1.1 什么是事务&#xff1f;1.2 事务的四大特性 二、事务并发存在的问题2.1 脏读&#xff08;dirty read&#xff09;2.2 不可重复读&#xff08;unrepeatable read&#xff09;2.3 幻读 三、事务的四大隔离级别实践3.1 读未提交&#xff08;Read Uncommitted…...

IO多路复用沉浸式体验

这篇文章主要讲解一下IO多路复用常见问题&#xff0c;包含常见面试题&#xff0c;对你有帮助的话可以留个赞和关注嘛&#xff1f;谢谢大家支持&#xff01; 1.epoll 相比于 select/poll 的优点有哪些&#xff1f; 高效的数据结构&#xff1a;epoll使用红黑树管理fd&#xff0…...

音视频学习(三十三):GOP详解

GOP 概念 GOP&#xff08;图像组&#xff09;是视频编码中一组帧的集合(按相关性分组)&#xff0c;它从一个关键帧&#xff08;I帧&#xff09;开始&#xff0c;后面跟随若干个参考帧&#xff08;P帧&#xff09;和预测帧&#xff08;B帧&#xff09;。其结构决定了视频帧的压…...

部署YUM仓库

目录 一.YUM 1.1yum概述 1.2yum的实现 1.3yum服务的组成 1.4yum服务实现过程 1.5yum配置文件位置 二.yum相关命令 三.搭建yum仓库的方式 3.1使用HTTP方式搭建yum仓库 准备工作&#xff08;服务端和客户端都需要做&#xff09; 服务端 客户端 3.2使用ftp方式搭建yu…...

中位数学习(低估它了)

-----------------------------------------------------------------中位数------------------------------------------------------- 中位数有一个很好的性质&#xff1a;假设有一批数据&#xff0c;你想找一个数&#xff0c;使得这批数据与它差的绝对值的和最小&#xff0…...

音视频转换器 AV 接口静电保护方案

方案简介 音视频转换器是将音视频&#xff08;AV&#xff09;信号转换成其他格式或信号类型的设备或软件。 它能够实现大多数视频、音频以及图像格式之间的转换&#xff0c;包括但不限于 RMVB、AVI、 MP4、MOV 等常见格式&#xff0c;同时也支持将不同采样率、位深度、声道数…...

蓝桥杯嵌入式第十二届省赛程序设计1(超简单版)

此程序只需要会C语言数组&#xff0c;结构体(struct)&#xff0c;for , if , switch(也可以用if)就能够实现。 引脚设置&#xff1a; 引脚配置&#xff08;参照笔记&#xff09;&#xff1a; 代码部分&#xff1a; /* USER CODE END Header */ /* Includes ------------------…...

CSS 链接样式学习笔记

在网页设计中&#xff0c;链接&#xff08;<a> 标签&#xff09;是不可或缺的元素&#xff0c;通过 CSS 可以对链接进行丰富的样式设置&#xff0c;从而提升用户体验和页面美观度。以下是关于 CSS 链接样式的详细学习笔记。 一、链接的四种状态 链接有四种不同的状态&a…...

有ts文件却无法ts出来解决办法

一开始报错是报这个&#xff0c;但是我其实完全看不懂为什么 原因是这个 打开某个test就行了...

javaSE.Lambda表达式

如果一个接口中有且只有一个待实现的抽象方法&#xff0c;那么我们可以将匿名内部类简写为Lambda表达式。 简写规则 标准格式&#xff1a; &#xff08;【参数类型 参数名称&#xff0c;】...&#xff09; -> {代码语句&#xff0c; 包括返回值} 只有一行花括号{}可以省略。…...

Web渗透之文件包含漏洞

文件包含漏洞原理 1、源代码 <?php$filename $_GET[filename]; include $filename; //或include_once,require,require_onceecho "欢迎来到PHP的世界.";?> 2、利用条件 php.ini中alllow_url_fopenOn(默认开启)和allow_url_includeOff(默认关闭)要开启…...

费马引理和罗尔定理

cheer 向……欢呼&#xff0c;使高兴&#xff0c;欢呼&#xff0c;欢呼&#xff0c;愉快 前言区间平均值费马引理罗尔三步万能构造原函数的方法什么时候用罗尔定理计划拉格朗日需要记忆的不等式柯西中值定理泰勒高阶导数判断极值最后 前言 继续学习。今天争取把讲义和作业题都…...

【合新通信】浸没式液冷中低成本冷媒开发的最新进展

浸没式液冷光模块是一种结合高效散热技术与光通信的新型解决方案&#xff0c;主要用于数据中心、超算中心等高密度计算场景。其核心特点是通过将光模块直接浸入绝缘冷却液中&#xff08;如矿物油、氟化液等&#xff09;&#xff0c;实现高效散热和节能降耗。低成本冷却液的研发…...

【开发记录】服务外包大赛记录

参加服务外包大赛的A07赛道中&#xff0c;最近因为频繁的DEBUG&#xff0c;心态爆炸 记录错误 以防止再次出现错误浪费时间。。。 2025.4.13 项目在上传图片之后 会自动刷新 没有等待后端返回 Network中的fetch /upload显示canceled. 然而这是使用了VS的live Server插件才这样&…...

智能指针之设计模式1

本文探讨一下智能指针和GOF设计模式的关系&#xff0c;如果按照设计模式的背后思想来分析&#xff0c;可以发现围绕智能指针的设计和实现有设计模式的一些思想体现。当然&#xff0c;它们也不是严格意义上面向对象的设计模式&#xff0c;毕竟它们没有那么分明的类层次体系&…...

Spring Boot 中应用的设计模式

Spring Boot 中应用的设计模式详解 Spring Boot 作为 Spring 框架的扩展&#xff0c;广泛使用了多种经典设计模式。以下是主要设计模式及其在 Spring Boot 中的具体应用&#xff1a; 一、创建型模式 1. 工厂模式 (Factory Pattern) 应用场景&#xff1a; BeanFactory 和 Ap…...

23种GoF设计模式

GoF&#xff08;Gang of Four&#xff09;设计模式是由四位计算机科学家 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 合著的书籍《Design Patterns: Elements of Reusable Object-Oriented Software》中提出的设计模式 目录 一、创建型模式&#xff08;Cre…...

Python实例题:Python实现中文错别字高亮系统

目录 Python实例题 题目 安装依赖库 代码实现 代码解释 运行思路 注意事项 Python实例题 题目 Python实现中文错别字高亮系统 安装依赖库 在开始之前&#xff0c;你需要安装 pycorrector 和 rich 库。可以使用以下命令进行安装&#xff1a; pip install pycorrecto…...

【第三十一周】ViT 论文阅读笔记

ViT 摘要Abstract文章信息引言方法Patch EmbeddingPatch Position EmbeddingTransformer EncoderMLP Head整体架构CNN的归纳偏置 代码实现实验结果总结 摘要 本篇博客介绍了Vision Transformer&#xff08;ViT&#xff09;&#xff0c;这是一种突破性的图像分类模型&#xff…...

射频(RF)静电放电防护方案

方案简介 射频&#xff08;RF&#xff09;是 Radio Frequency 的缩写&#xff0c;表示可以辐射到空间的电磁频率&#xff0c;频率 范围从 300kHz&#xff5e;300GHz 之间。射频就是射频电流&#xff0c;简称 RF&#xff0c;它是一种高频交流变化 电磁波的简称。射频天线是一…...

【redis进阶三】分布式系统之主从复制结构(1)

目录 一 为什么要有分布式系统&#xff1f; 二 分布式系统涉及到的非常关键的问题&#xff1a;单点问题 三 学习部署主从结构的redis (1)创建一个目录 (2)进入目录拷贝两份原有redis (3)使用vim修改几个选项 (4)启动两个从节点服务器 (5)建立复制&#xff0c;要想配…...

排序(1)

排序&#xff08;1&#xff09; 日常生活中&#xff0c;有很多场景都会用到排序。比如你买东西&#xff0c;在购物软件就有几种展现方式&#xff0c;按照评论数量给你排序出来&#xff0c;让你选&#xff0c;还是说按照价钱高低排序出来让你选。 排序其实是一种为了更好解决问…...

NR 5G中的N5接口

N5接口的定义: Reference point between the PCF and an AF or TSN AF. 即N5 PCF和AF之间的参考点。 AF Application Function 应用功能&#xff0c;指应用层的各种服务&#xff0c;可以是运营商内部的应用如Volte AF(类似4G的Volte As&#xff09;、也可以是第三方的AF&…...