构建中文版的 nanoGPT - 中文版 nanoGPT 的分词(tokenization)

构建中文版的 nanoGPT - 中文版 nanoGPT 的分词(tokenization)

flyfish

参考网址

bash 复制代码
https://github.com/shaoshengsong/nanoGPT-cn
  1. tokenizer = 分词器(训练出来的模型/工具)
  2. tokenization = 分词(这个过程)
  3. token = 词元(分词后最小单元)
  4. tokenize = (动词)执行分词

token 是模型用来表示自然语言文本的基本单位,即是模型用来表示自然语言文本的的最小单位。可以直观的理解为字或词;通常 1 个中文词语、1 个英文单词、1 个数字或 1 个符号计为 1 个 token,不同的分词器有不同的分法,有的可能一个汉字为0点几个token。

支持中文的分词器

这里直接使用了ChatGLM3 ,我这里的分词器基于 SentencePiece 实现。

tokenizer.modelChatGLM3 官方训练好的二进制分词模型文件 ,相当于一本文本 ↔ 数字ID 的专属字典。文件大小是994 KB

python 复制代码
tokenizer = SPTokenizer("./chatglm3-6b/tokenizer.model")

文本统一编码:将训练语料转换为连续的 Token ID 序列

数据集划分:按照 nanoGPT 标准的 9:1 比例 划分训练集 / 验证集

二进制文件生成:输出 nanoGPT 唯一支持的 train.bin + val.bin 数据集文件

编码(encode):将任意文本(中文 / 英文 / 符号 / 数字)转换为模型可识别的 Token ID 数字序列

解码(decode):将 Token ID 序列无损还原为原始文本

源码如下

python 复制代码
import os
import numpy as np
from sentencepiece import SentencePieceProcessor

class SPTokenizer:
    def __init__(self, model_path: str):
        assert os.path.isfile(model_path)
        self.sp_model = SentencePieceProcessor(model_file=model_path)

        self.n_words = self.sp_model.vocab_size()
        self.bos_id = self.sp_model.bos_id()
        self.eos_id = self.sp_model.eos_id()
        self.pad_id = self.sp_model.unk_id()

        special_tokens = ["[MASK]", "[gMASK]", "[sMASK]", "sop", "eop"]
        self.special_tokens = {}
        for token in special_tokens:
            self.special_tokens[token] = self.n_words
            self.n_words += 1

    def encode(self, s: str, bos=False, eos=False):
        tokens = self.sp_model.encode(s)
        if bos:
            tokens = [self.bos_id] + tokens
        if eos:
            tokens = tokens + [self.eos_id]
        return tokens

    def decode(self, tokens):
        return self.sp_model.decode(tokens)

# 初始化分词器
tokenizer = SPTokenizer("./chatglm3-6b/tokenizer.model")
vocab_size = tokenizer.n_words

# 编解码函数
def encode(text):
    return tokenizer.encode(text, bos=False, eos=False)

def decode(ids):
    return tokenizer.decode(ids)

# 测试用例 + nanoGPT对接
if __name__ == "__main__":
    print("ChatGLM分词器测试")
    print("词表大小", vocab_size)

    # 测试1 基础中文
    text1 = "济南的冬天是响晴的"
    ids1 = encode(text1)
    print("基础中文测试")
    print("原文", text1)
    print("编码", ids1)
    print("解码", decode(ids1))

    # 测试2 纯英文
    text2 = "Hello world"
    ids2 = encode(text2)
    print("纯英文测试")
    print("原文", text2)
    print("解码", decode(ids2))

    # 测试3 中英混合
    text3 = "Life is a journey, 人生是一场旅程"
    ids3 = encode(text3)
    print("中英混合测试1")
    print("原文", text3)
    print("编码长度", len(ids3))
    print("解码", decode(ids3))

    # 测试4 中英混合
    text4 = "AI technology makes life better 科技让生活更美好"
    ids4 = encode(text4)
    print("中英混合测试2")
    print("原文", text4)
    print("解码", decode(ids4))

    # 测试5 长文本
    text5 = "在北平住惯的人,总以为冬天里要是不刮风,便觉得是奇迹"
    ids5 = encode(text5)
    print("长文本测试")
    print("原文长度", len(text5))
    print("Token数量", len(ids5))

    # 测试6 一致性验证
    text6 = "人工智能改变世界"
    result = decode(encode(text6))
    print("一致性验证")
    print("原文", text6)
    print("结果", result)
    print("验证通过", text6 == result)
    
    # 测试7 英文标点符号测试
    text7 = "Hello! How are you? I'm fine, thank you."
    ids7 = encode(text7)
    print("英文标点符号测试")
    print("原文", text7)
    print("解码", decode(ids7))

    # 测试8 中文标点符号测试
    text8 = "你好!请问今天天气怎么样?我很好,谢谢你。"
    ids8 = encode(text8)
    print("中文标点符号测试")
    print("原文", text8)
    print("解码", decode(ids8))

    # 测试9 中英混合符号+文本测试
    text9 = "Python is fun! 编程真有趣,我爱深度学习~"
    ids9 = encode(text9)
    print("中英混合符号测试")
    print("原文", text9)
    print("解码", decode(ids9))

    # 测试10 数字+特殊符号+中英文混合
    text10 = "价格: $99.99, 价格:99.99元,邮箱:test123@abc.com"
    ids10 = encode(text10)
    print("数字特殊符号混合测试")
    print("原文", text10)
    print("解码", decode(ids10))

    # --------------------------
    # nanoGPT 对接示例
    # --------------------------
    print("nanoGPT对接测试")
    # 模拟训练文本
    sample_text = "济南的冬天是响晴的。Life is a journey, 人生是一场旅程。AI技术改变世界。"
    
    # 1. 编码文本
    all_ids = encode(sample_text)
    print("总Token数", len(all_ids))

    # 2. 划分训练集/验证集 (9:1)
    split_idx = int(0.9 * len(all_ids))
    train_ids = all_ids[:split_idx]
    val_ids = all_ids[split_idx:]

    # 3. 保存为nanoGPT标准bin文件
    np.array(train_ids, dtype=np.uint16).tofile("train.bin")
    np.array(val_ids, dtype=np.uint16).tofile("val.bin")
    print("train.bin 和 val.bin 生成完成")

    # 4. 验证文件读取
    train_load = np.fromfile("train.bin", dtype=np.uint16)
    print("训练集读取验证长度", len(train_load))

    print("所有测试完成")

输出

bash 复制代码
ChatGLM分词器测试
词表大小 64794
基础中文测试
原文 济南的冬天是响晴的
编码 [30910, 34952, 54530, 35468, 54532, 55111, 56915, 54530]
解码 济南的冬天是响晴的
纯英文测试
原文 Hello world
解码 Hello world
中英混合测试1
原文 Life is a journey, 人生是一场旅程
编码长度 9
解码 Life is a journey, 人生是一场旅程
中英混合测试2
原文 AI technology makes life better 科技让生活更美好
解码 AI technology makes life better 科技让生活更美好
长文本测试
原文长度 26
Token数量 19
一致性验证
原文 人工智能改变世界
结果 人工智能改变世界
验证通过 True
英文标点符号测试
原文 Hello! How are you? I'm fine, thank you.
解码 Hello! How are you? I'm fine, thank you.
中文标点符号测试
原文 你好!请问今天天气怎么样?我很好,谢谢你。
解码 你好!请问今天天气怎么样?我很好,谢谢你。
中英混合符号测试
原文 Python is fun! 编程真有趣,我爱深度学习~
解码 Python is fun! 编程真有趣,我爱深度学习~
数字特殊符号混合测试
原文 价格: $99.99, 价格:99.99元,邮箱:test123@abc.com
解码 价格: $99.99, 价格:99.99元,邮箱:test123@abc.com
nanoGPT对接测试
总Token数 24
train.bin 和 val.bin 生成完成
训练集读取验证长度 21
所有测试完成
相关推荐
高洁0129 分钟前
AI智能体落地价值:从工具赋能到产业重构,解锁企业降本增效新逻辑
人工智能·深度学习·机器学习·transformer·知识图谱
GEO实战经验分享4 小时前
GEO王涛解码智能核心:详解Transformer与注意力机制的工作原理
人工智能·深度学习·transformer
天一生水water18 小时前
基于重构的无监督/单类时间序列异常检测
人工智能·深度学习·重构·transformer
不爱吃糖的程序媛1 天前
从 0 到 1:react-native-transformer-text-input 鸿蒙化适配实录
react native·transformer·harmonyos
空堂与归2 天前
迁移学习怎么落地?Transformers 库微调实战
人工智能·机器学习·自然语言处理·transformer·迁移学习
lucky_syq2 天前
小模型推理能力天花板:是Transformer架构锁死,还是参数规模不够?换架构能否实现推理飞跃?
深度学习·架构·transformer
问天_观心3 天前
大模型微调学习(二)
人工智能·python·深度学习·学习·语言模型·transformer
克里斯蒂亚诺更新3 天前
Transformer(注意力机制)不按顺序-全盘扫描
人工智能·深度学习·transformer
布吉岛的石头4 天前
Java 程序员第 48 阶段1:Transformer 架构总览与自注意力直觉,从 RNN 痛点理解注意力机制
java·架构·transformer
EW Frontier5 天前
拆解|多尺度复数卷积,把调制识别准确率又往上推了 3 个点【文末附代码链接】
transformer·调制识别·无人机信号识别·辐射源识别