news 2026/7/18 13:40:51

AI基本结构10-分词器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI基本结构10-分词器

接着看看课:https://www.bilibili.com/video/BV1cb421n78r

ps:这个示例让我想到re0

课程复现

import os os.environ["HF_ENDPOINT"] = "https://hf-mirror.com" from transformers import AutoTokenizer import matplotlib.pyplot as plt import huggingface_hub import transformers tokenizer_gpt2= AutoTokenizer.from_pretrained('gpt2') # 分词效果示例,三段文本表示的意思是相近的 text_fr = '''Évariste Galois (/ɡælˈwɑː/; français : [evaʁist ɡalwa] ; 25 octobre 1811 - 31 mai 1832) était un mathématicien français et un militant politique. Alors qu'il était encore adolescent, il parvint à déterminer une condition nécessaire et suffisante pour qu'un polynôme soit résoluble par des radicaux, résolvant ainsi un problème qui était resté ouvert pendant 350 ans. Son travail posa les fondements de la théorie de Galois et de la théorie des groupes, deux branches majeures de l'algèbre abstraite. Il était un fervent républicain et fut très impliqué dans les troubles politiques qui entourèrent la Révolution française de 1830. En raison de son activisme politique, il fut arrêté à plusieurs reprises, purgé une peine de plusieurs mois de prison. Pour des raisons restées obscures, peu de temps après sa libération de prison, il se battit en duel et décéda des blessures qu'il subit.''' text_en = '''Évariste Galois (/ɡælˈwɑː/; French: [evaʁist ɡalwa]; 25 October 1811 – 31 May 1832) was a French mathematician and political activist. While still in his teens, he was able to determine a necessary and sufficient condition for a polynomial to be solvable by radicals, thereby solving a problem that had been open for 350 years. His work laid the foundations for Galois theory and group theory, two major branches of abstract algebra. He was a staunch republican and was heavily involved in the political turmoil that surrounded the French Revolution of 1830. As a result of his political activism, he was arrested repeatedly, serving one jail sentence of several months. For reasons that remain obscure, shortly after his release from prison he fought in a duel and died of the wounds he suffered.''' text_zh = '''埃瓦里斯特·伽罗瓦(法语:Évariste Galois,1811年10月25日—1832年5月31日,法语发音: [evaʁist ɡalwa])是一位法国数学家和政治活动家。尽管还在十几岁时,他就能够确定多项式能够通过根式求解的充分必要条件,从而解决了一个悬而未决的问题,该问题已经存在了350年。他的工作奠定了Galois理论和群论的基础,这两个是抽象代数的重要分支。他是一位坚定的共和派,深度参与了1830年法国大革命期间的政治动荡。由于他的政治活动,他多次被逮捕,其中一次入狱数月。由于原因不明,他在刑满释放后不久,参与了一场决斗并因受伤而去世。''' texts = { 'fr': text_fr, 'en': text_en, 'zh': text_zh } def draw_bar(str_stats, token_stats): # 将统计结果可视化 fig = plt.figure(figsize=(6, 6), dpi=80) plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False plt.rcParams.update({'font.size': 13}) bar_width = 0.1 base = range(len(str_stats)) br_str = [x - bar_width for x in base] br_token = [x + bar_width for x in base] plt.bar(br_str, str_stats.values(), color='g', width=bar_width * 2, label='文本长度') plt.bar(br_token, token_stats.values(), color='b', width=bar_width * 2, label='分词后的长度') plt.xticks([r for r in base], str_stats.keys(), fontsize=18) plt.legend(shadow=True) return fig def get_token_stats(tokenizer): # 统计文本中的单词数量(如果是中文,则为文本的字数) str_stats = {} # 统计分词后的词元数量 token_stats = {} for (k, v) in texts.items(): text_len = len(v.split()) if k != 'zh' else len(list(v)) token_len = len(tokenizer.encode(v)) str_stats[k] = text_len token_stats[k] = token_len print(str_stats) print(token_stats) return draw_bar(str_stats, token_stats) # 使用gpt2分词器进行分词的效果 f = get_token_stats(tokenizer_gpt2) f.savefig('gpt2_tokenizer.png', dpi=200) for text in texts: # 英文分词效果展示 stringText='_'.join([tokenizer_gpt2.decode(i) for i in tokenizer_gpt2.encode(texts[text])]) print(stringText) from datasets import load_dataset # 使用中文语料训练分词器 raw_data = load_dataset('BelleGroup/train_0.5M_CN') def get_training_corpus(): # 为了减少运算时间,只选择较少的训练数据 data = raw_data['train'].select(range(10000)) for idx in range(0, len(data), 1000): samples = data[idx : idx + 1000] yield samples.get('instruction', []) + samples.get('output', []) # 为了减少运算时间,只将词汇表大小设置为1000,正常应该在5万左右 tokenizer_zh = tokenizer_gpt2.train_new_from_iterator(get_training_corpus(), 1000) # 展示新分词器的效果 f = get_token_stats(tokenizer_zh) f.savefig('zh_tokenizer.png', dpi=200) for text in texts: # 英文分词效果展示 stringText='_'.join([tokenizer_gpt2.decode(i) for i in tokenizer_gpt2.encode(texts[text])]) print(stringText)

按字符分词

# 使用gpt2分词器进行分词的效果 f = get_token_stats(tokenizer_gpt2) f.savefig('gpt2_tokenizer.png', dpi=200) for text in texts: # 英文分词效果展示 stringText='_'.join([tokenizer_gpt2.decode(i) for i in tokenizer_gpt2.encode(texts[text])]) print(stringText)

join函数:将列表推导式生成的字符串列表用下划线_拼接成一个字符串。例如,若解码结果为["hello", "world"],则输出为"hello_world"

中文分词的挑战

中文文本缺乏显式的词边界标记,需依赖上下文语义、词典或统计模型进行切分。而英文分词直接利用空格和标点符号,避免了歧义切分的复杂性,例如中文“结婚的和尚未结婚的”可能被错误切分为“结婚/的/和/尚未/结婚/的”

英文分词(字母文字)的优势

英文分词基于空格和标点符号进行切分,天然具有词边界标记。这种特性使得英文分词在技术上相对简单,多数情况下无需复杂的算法即可实现基本的分词功能

效率更高:英文分词算法复杂度低,处理速度快,无需依赖大规模词典或复杂的统计模型。
准确性稳定:词边界明确,歧义切分问题极少,错误率显著低于中文分词。
资源消耗少:不需要训练庞大的语言模型或维护高频词典,节省计算和存储资源。

基于训练的分词器

预训练与微调

微调(Fine-tuning)是在预训练模型的基础上,针对特定任务使用有标注数据进行参数调整的过程。其目的是使模型适应具体场景(如情感分类、医学图像分割)。

数据需求:需要任务相关的标注数据,但规模远小于预训练数据。

调整策略:可能仅优化顶层网络(如分类头)或全局微调所有参数。

效率优势:相比从头训练,微调能显著减少计算成本和数据需求。

训练分词器

from datasets import load_dataset # 使用中文语料训练分词器 raw_data = load_dataset('BelleGroup/train_0.5M_CN') def get_training_corpus(): # 为了减少运算时间,只选择较少的训练数据 data = raw_data['train'].select(range(10000)) for idx in range(0, len(data), 1000): samples = data[idx : idx + 1000] yield samples.get('instruction', []) + samples.get('output', []) # 为了减少运算时间,只将词汇表大小设置为1000,正常应该在5万左右 tokenizer_zh = tokenizer_gpt2.train_new_from_iterator(get_training_corpus(), 1000) # 展示新分词器的效果 f = get_token_stats(tokenizer_zh) f.savefig('zh_tokenizer.png', dpi=200) for text in texts: # 英文分词效果展示 stringText='_'.join([tokenizer_gpt2.decode(i) for i in tokenizer_gpt2.encode(texts[text])]) print(stringText)

从Hugging Face数据集加载中文语料,并基于GPT-2的分词器训练一个适配中文的新分词器。代码分为数据加载、迭代器构建、分词器训练和效果验证四个部分。

raw_data = load_dataset('BelleGroup/train_0.5M_CN')从Hugging Face数据集库加载名为"BelleGroup/train_0.5M_CN"的中文数据集,该数据集包含50万条中文训练样本。

get_training_corpus()函数定义了一个生成器,通过raw_data['train'].select(range(10000))选取前1万条训练数据,并以每1000条为批次进行迭代。每次迭代时,将样本中的'instruction'和'output'字段内容合并后生成训练语料片段,这种分批次生成方式可有效控制内存消耗。

tokenizer_zh = tokenizer_gpt2.train_new_from_iterator(get_training_corpus(), 1000)调用GPT-2分词器的训练方法,基于中文语料迭代器训练新分词器。参数1000指定词汇表大小(实际应用应设置更大值如5万),该方法会分析语料中的字符/子词频率,构建适合中文的分词方案。

yield语句

在 Python 中,yield是用于定义生成器函数的关键字。生成器函数返回一个生成器对象,该对象可以迭代,每次迭代时函数会执行到yield语句处暂停,并将yield后的值返回给调用者。下次迭代时,函数会从上次暂停的位置继续执行。

调用生成器函数时,函数不会立即执行,而是返回一个生成器对象。

使用 next() 或迭代(如 for 循环)时,函数执行到第一个 yield 语句,返回 yield 后的值并暂停。

再次调用 next() 时,函数从上次暂停的位置继续执行,直到遇到下一个 yield 或函数结束。

# 手动实现迭代器 class Counter: def __init__(self, low, high): self.current = low self.high = high def __iter__(self): return self def __next__(self): if self.current > self.high: raise StopIteration else: self.current += 1 return self.current - 1 # 使用生成器实现相同功能 def counter_generator(low, high): current = low while current <= high: yield current current += 1

词嵌入

词嵌入(Embedding)是将离散的符号(如单词)映射到连续向量空间的技术,旨在用低维稠密向量表示文本,替代传统的高维稀疏表示(如独热编码)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/18 13:40:06

零基础学习C++(1)

前言&#xff1a;本篇是由C语言步入C的第一课&#xff0c;旨在学习一些C的入门语法&#xff0c;帮助后续学习。一.第一个C程序C兼容C语言&#xff0c;所以一些C语言代码在C中也可通过C拥有专属 IO 流cout与cinio提速方法只需要加上这些代码二.namespace的用法将变量、函数、结构…

作者头像 李华
网站建设 2026/7/18 13:38:14

OkHttp BOM模块解析与依赖管理实践

1. OkHttp BOM模块深度解析 作为一名长期使用OkHttp的开发者&#xff0c;我发现很多团队在使用OkHttp时都会遇到依赖版本混乱的问题。OkHttp官方提供的okhttp-bom&#xff08;Bill of Materials&#xff09;模块正是为了解决这一痛点而设计的。今天我们就来深入剖析这个看似简单…

作者头像 李华
网站建设 2026/7/18 13:38:05

即梦AI出图总糊?5个被90%用户忽略的参数设置,今天彻底解决

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;即梦AI出图模糊问题的底层归因分析 即梦AI生成图像出现模糊并非单一环节失效所致&#xff0c;而是由模型推理链路中多个关键组件协同作用下的系统性表现。其根本原因可追溯至潜在空间解码、分辨率适配策略、后…

作者头像 李华
网站建设 2026/7/18 13:38:04

Java学习心得

Java简介Java是一种强类型语言&#xff0c;每个变量都必须先定义才能使用&#xff0c;但是web前端开发中的html就是一种弱类型语言。例如&#xff1a;String a;System.out.println(a);其中&#xff0c;a没有初始化&#xff0c;会报错&#xff0c;应该改为&#xff1a;String a“…

作者头像 李华
网站建设 2026/7/18 13:38:01

Unity中世纪场景构建实战:从Stronghold Village资产到高效游戏开发

1. 项目概述&#xff1a;为什么Stronghold Village是构建中世纪世界的“瑞士军刀” 如果你正在开发一款中世纪题材的游戏&#xff0c;无论是RPG、策略、模拟经营还是动作冒险&#xff0c;最头疼的环节之一&#xff0c;可能就是场景搭建。从零开始建模一座城堡、一个村庄&#x…

作者头像 李华
网站建设 2026/7/18 13:37:41

阶段四:模拟微信 OAuth 登录

从零构建带AI流式对话的Vue2全栈应用-CSDN博客本文是对这篇文章阶段四的讲解 一、为什么不能只用一个“登录成功”按钮 真正的第三方登录不是前端自己决定登录成功。 需要经过&#xff1a; 你的前端 微信授权服务器 你的后端 基本流程&#xff1a; 用户点击微信登录↓ 跳…

作者头像 李华