大语言模型 LLM book 笔记(二)

news2024/9/21 14:49:06

第二部分 预训练

第四章 数据准备

4.1 数据来源

image.png

4.1.1 通用文本数据
  • 网页 + 书籍
4.1.2 专用文本数据
  • 多语文本 + 科学文本 + 代码

4.2 数据预处理

image.png

4.2.1 质量过滤
  • 基于启发式规则的方法
    • 基于语种的过滤:语言识别器筛选中英文,对于多语的维基百科由于数据规模小可直接训
    • 基于简单统计指标的过滤

image.png

  • 基于关键词的过滤

image.png

  • 基于分类器的方法
    • 轻量级模型:效率高,受限于模型能力,FastText
    • 可微调的预训练语言模型:可针对性微调,通用性和泛化性不足,BERT、BART、LLaMA
    • 闭源大语言模型API:能力较强,成本高,不够灵活,GPT-4、Claude 3
  • 可用方案:先用规则再用分类器,分类器可用多种集成
4.2.2 敏感内容过滤
  • 过滤有毒内容:毒性文本分类器
  • 过滤隐私内容:使用启发式方法,如关键字识别,用特定词元替换
4.2.3 数据去重
  • 计算粒度:首先针对数据集和文档级别进行去重,进一步在句子级别实现更为精细的去重
  • 用于去重的匹配方法
    • 精确匹配算法:后缀数组来匹配最小长度的完全相同子串
    • 近似匹配算法:局部敏感哈希(Locality-Sensitive Hashing, LSH),如最小哈希(MinHash)
4.2.4 数据对预训练效果的影响
  • 数据数量的影响:训练数据数量越大,模型性能越好,未达到极限
  • 数据质量的影响
    • 整体质量:质量不好导致不稳定不收敛,同数量下质量越高越好,能减少“幻想”
    • 重复数据:可能导致“双下降现象”(训练损失先经历下降然后出现升高再下降的现象),降低利用上下文信息的能力,如果要使用高质量数据重复训练,可以进行改写或针对性生成
    • 有偏、有毒、隐私内容:严重不良影响,容易被攻击和诱使生成
  • 数据集污染:也称为基准泄漏,尽量不要包含评估测试集
4.2.5 数据预处理实践
  • 质量过滤
    • 加载预训练好的FastText 语言分类器,为每个输入文本生成一个语言标签,不符合配置文件中语言类别的文本将被过滤。
from utils.evaluator import LangIdentifier

class FilterPassageByLangs():
    def __init__(self) -> None:
        # 使用LangIdentifier 模块加载已经训练好的fasttext 模型
        self.language_identifier = LangIdentifier(model_path="utils/models/fasttext/lid.176.bin")
        self.reject_threshold = 0.5
    def filter_single_text(self, text: str, accept_lang_list: list) -> bool:
        # 使用fasttext 模型给text 打分,每种语言生成一个置信分数
        labels, scores = self.language_identifier.evaluate_single_text(text)
        # 如果text 所有语言的分数均比reject_threshold 要低,则直接定义为未知语言
        if any(score < self.reject_threshold for score in scores):
            labels = ["uk"]
        accept_lang_list = [each.lower() for each in accept_lang_list]
        # 如果分数最高的语言标签不在配置文件期望的语言列表中,则丢弃该文本
        if labels[0] not in accept_lang_list:
            return True
        return False
  • 去重
    • 句子级去重:对文本包含的所有句子(每行对应一个句子)计算𝑛 元组,对于相邻的句子之间𝑛 元组的Jaccard 相似度超过设定阈值的都将会被过滤
import string
import re
from nltk.util import ngrams

class CleanerDedupLineByNgram():
    def __init__(self):
        # 定义行分隔符和元组分隔符
        self.line_delimiter = list("\n")
        chinese_punctuation = ",。!?:;“”‘’()《》【】、|—"
        self.gram_delimiter = list(string.punctuation) + list(chinese_punctuation) + [' ']
    def clean_single_text(self, text: str, n: int = 5, thre_sim: float = 0.95) -> str:
        # 依靠行分隔符分割所有行
        lines = [each for each in re.split('|'.join(map(re.escape, self.line_delimiter)), text) if each != '']
        lineinfo, last = list(), {}
        for idx, line in enumerate(lines): # 计算每行的n 元组
            # 依靠元组分隔符分割所有N 元组,并将其暂时存储到lineinfo 里
            grams = [each for each in re.split('|'.join(map(re.escape, self.gram_delimiter)), line) if each != '']
            computed_ngrams = list(ngrams(grams, min(len(grams), n)))
            lineinfo.append({ "lineno": idx, "text": line, "n": min(len(grams), n), "ngrams": computed_ngrams, "keep": 0 })
        for idx, each in enumerate(lineinfo): # 过滤掉和相邻行之间n 元组的 Jaccard 相似度超过 thre_sim 的行
            if last == {}:
                each["keep"], last = 1, each
            else:
                # 计算相邻行间的Jaccard 相似度
                ngrams_last, ngrams_cur = set(last["ngrams"]), set(each["ngrams"])
                ngrams_intersection, ngrams_union =
                len(ngrams_last.intersection(ngrams_cur)),
                len(ngrams_last.union(ngrams_cur))
                jaccard_sim = ngrams_intersection / ngrams_union if ngrams_union != 0 else 0
                if jaccard_sim < thre_sim:
                    each["keep"], last = 1, each
        # 将所有未被过滤掉的N 元组重新拼接起来
        text = self.line_delimiter[0].join([each["text"] for each in lineinfo if each["keep"] == 1])
        return text
  • 隐私过滤
    • 去除身份证号:对每个输入的文本,下面使用正则替换的方式将匹配到的身份证号替换为特定字符串
from utils.rules.regex import REGEX_IDCARD
from utils.cleaner.cleaner_base import CleanerBase

class CleanerSubstitutePassageIDCard(CleanerBase):
    def __init__(self):
        super().__init__()
    def clean_single_text(self, text: str, repl_text: str = "**MASKED**IDCARD**") -> str:
        # 使用正则表达式REGEX_IDCARD 匹配身份证号,用repl_text 代替
        return self._sub_re(text=text, re_text=REGEX_IDCARD, repl_text=repl_text)

4.3 词元化(分词)

4.3.1 BPE 分词
  • 流程:从一组基本符号(例如字母和边界字符)开始,迭代地寻找语料库中的两个相邻词元,并将它们替换为新的词元,这一过程被称为合并
  • 合并的选择标准是计算两个连续词元的共现频率,也就是每次迭代中,最频繁出现的一对词元会被选择与合并。合并过程将一直持续达到预定义的词表大小。
import re
from collections import defaultdict
from collections import Counter


def extract_frequencies(sequence):
    """
    给定一个字符串,计算字符串中的单词出现的频率,并返回词表(一个词到频率的映射字典)。
    """
    token_counter = Counter()
    for item in sequence:
        tokens = ' '.join(list(item)) + ' </w>'
        token_counter[tokens] += 1
    return token_counter

def frequency_of_pairs(frequencies):
    """
    给定一个词频字典,返回一个从字符对到频率的映射字典。
    """
    pairs_count = Counter()
    for token, count in frequencies.items():
        chars = token.split()
        for i in range(len(chars) - 1):
            pair = (chars[i], chars[i+1])
            pairs_count[pair] += count
    return pairs_count

def merge_vocab(merge_pair, vocab):
    """
    给定一对相邻词元和一个词频字典,将相邻词元合并为新的词元,并返回新的词表。
    """
    re_pattern = re.escape(' '.join(merge_pair))
    pattern = re.compile(r'(?<!\S)' + re_pattern + r'(?!\S)')
    updated_tokens = {pattern.sub(''.join(merge_pair), token): freq for token, freq in vocab.items()}
    return updated_tokens

def encode_with_bpe(texts, iterations):
    """
    给定待分词的数据以及最大合并次数,返回合并后的词表。
    """
    vocab_map = extract_frequencies(texts)
    for _ in range(iterations):
        pair_freqs = frequency_of_pairs(vocab_map)
        if not pair_freqs:
            break
        most_common_pair = pair_freqs.most_common(1)[0][0]
        vocab_map = merge_vocab(most_common_pair, vocab_map) 
    return vocab_map
  
num_merges = 1000
bpe_pairs = encode_with_bpe(data, num_merges)
  • image.png
4.3.2 WordPiece 分词
  • 和BPE分词的想法非常相似,都是通过迭代合并连续的词元,但是合并的选择标准略有不同。
  • 提前训练语言模型进行评分,或使用以下计算方式计算得分image.png
4.3.3 Unigram 分词
  • 从语料库的一组足够大的字符串或词元初始集合开始,迭代地删除其中的词元,直到达到预期的词表大小
4.3.4 分词器的选用
  • 无损重构:其分词结果能够准确无误地还原为原始输入文本
  • 高压缩率:在给定文本数据的情况下,经分词处理后的词元数量尽可能少,实现高效的文本编码和存储
  • 压缩率计算image.png

4.4 数据调度

image.png

4.4.1 数据混合
  • 典型数据分布:参考图4.1,典型的LLaMA 包括超过80%的网页数据、6.5%代码、4.5%的书籍以及2.5% 科学数据,可作为重要参考
  • 数据混合策略:增加数据源的多样性、优化数据混合、优化特定能力
  • 建议:从小模型上探索最优配比再迁移到大模型上
  • image.png
4.4.2 数据课程
  • 定义:按照特定顺序训练 / 不同阶段使用不同配比,工作集中在继续预训练(Continual Pre-training)
  • 实用方法:基于专门构建的评测基准监控大语言模型的关键能力的学习过程,然后在预训练期间动态调整数据的混合配比,基本技能→目标技能
  • 代码能力:2T 通用词元 → 500B 代码相关的词元 →100B Python 代码相关的词元
  • 数学能力:2T 通用词元 → 500B 代码相关的词元 →50∼200B 数学相关的词元
  • 长文本能力:2.5T 词元,4K 上下文窗口 → 20B 词元,16K 上下文窗口

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高阶数据结构——LRU Cache

1.什么是LRU Cache LRU是Least Recently Used的缩写&#xff0c;意思是最近最少使用&#xff0c;它是一种Cache替换算法。 什么是Cache&#xff1f;狭义的Cache指的是位于CPU和主存间的快速RAM&#xff0c; 通常它不像系统主存那样使用DRAM技术&#xff0c;而使用昂贵但较快速…

制约AI发展的关键在于人机环境系统智能的失配

人工智能&#xff08;AI&#xff09;发展的关键挑战之一就是人机环境系统之间的智能失配。这种失配指的是人工智能系统、其操作人员和应用环境之间的协调和适配问题&#xff0c;通常会影响系统的有效性和安全性。以下是一些具体方面&#xff0c;这些方面展示了人机环境系统智能…

《企业微服务实战 · 接口鉴权思路分享》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

ES JavaApi

1.RestClient操作索引库 2.RestClient操作文档 2.1查询 2.2更新 2.3删除 2.4批量新增&#xff08;bulk&#xff09; 3.DSL查询 对应的api 3.0解析响应 3.1全文检索 3.2精确查询 3.3复合查询-boolQuery 构建boolQuery 3.4排序和分页 3.5高亮

浙大数据结构慕课课后题(06-图2 Saving James Bond - Easy Version)(拯救007)

题目要求&#xff1a; This time let us consider the situation in the movie "Live and Let Die" in which James Bond, the worlds most famous spy, was captured by a group of drug dealers. He was sent to a small piece of land at the center of a lake fi…

C++打怪小游戏

这是一款用C代码写出来的打怪游戏。 上图片&#x1f447; ![](https://i-blog.csdnimg.cn/direct/6a4497c784ff4ba7a3332bc97d433789.png 一个11岁小朋友&#xff0c;爆肝532行&#xff0c;11小时完成代码&#xff0c;内部14个函数&#xff0c;5个结构体&#xff0c;三连…

ffmpeg使用x11录屏

version #define FFMPEG_VERSION "6.1.1" note x11视频采集结构:AVInputFormat ff_xcbgrab_demuxer code void CFfmpegOps::CaptureVideo(const char *outFileName) {const AVInputFormat *iFmt nullptr;size_t n 0;AVFormatContext *iFmtCtx nullptr;AVDict…

三十九、大数据技术之Kafka3.x(2)

&#x1f33b;&#x1f33b; 目录 一、Kafka 生产者1.1 生产者消息发送流程1.1.1 发送原理1.1.2 生产者重要参数列表 1.2 异步发送API1.2.1 普通异步发送1.2.2 带回调函数的异步发送 1.3 同步发送 API1.4 生产者分区1.4.1 分区好处1.4.2 生产者发送消息的分区策略1.4.3 自定义分…

使用Leaks定位iOS内存泄漏问题并解决

使用Leaks定位iOS内存泄漏问题并解决 前言 内存泄漏问题一直是程序开发中最令人头疼的问题&#xff0c;特别是C/C。虽然C/C在C11之后引入了许多新特性&#xff0c;包括智能指针&#xff0c;自动类型推导等&#xff0c;但C中动态内存的分配和释放仍然需要程序员来显式地进行。…

Linux线程thread详解(线程池)

在我们的进程虚拟地址的代码区&#xff0c;对于代码中的每个函数都有对应的地址&#xff0c;每个函数中的每行代码都有对应的代码&#xff0c;并且每个函数中的每行代码的地址都是连续的。既然代码是连续的&#xff0c;也就意味着我们可以将我们代码分块&#xff0c;分成不同的…

机器学习笔记:序列到序列学习[详细解释]

介绍 本节我们使用两个循环神经网络的编码器和解码器&#xff0c; 并将其应用于序列到序列&#xff08;sequence to sequence&#xff0c;seq2seq&#xff09;类的学习任务。遵循编码器&#xff0d;解码器架构的设计原则&#xff0c; 循环神经网络编码器使用长度可变的序列作为…

Jeecgboot3.6.3的vue3版本的一种flowable动态增加一个用户任务节点的方法(二)前端代码实现

因为这个项目license问题无法开源,更多技术支持与服务请加入我的知识星球。 这部分主要讲前端的功能实现 1、前端选择新增任务类型界面,点击新增节点 /*** 动态新增用户任务节点*/function handleAddTask(record: Recordable) {if (record.finishTime != null) {createMess…

在 .NET 8.0 中使用 xUnit 进行数据驱动测试

1. 前言 xUnit是一个功能强大且易于使用的单元测试框架。在.NET开发中&#xff0c;单元测试是非常重要的一部分&#xff0c;它可以帮助我们确保代码的正确性和可靠性。使用xUnit可以帮助我们编写更高效、更有效的单元测试&#xff0c;并提高代码质量和可维护性。 2. 特性 x…

Git-GitLab-Jenkins结合

目录 1.Git-GitLab-Jenkins结合2. 在pycharm配置git3. 实现提交代码后触发自动化测试&#xff08;1&#xff09;打开gitlab&#xff08;2&#xff09;Jenkins配置Git&#xff08;3&#xff09;选择需要的远程仓库 4.报告存在问题&#xff1a;5.也可以在Jenkins中设置定时触发&a…

OpenCV图像滤波(10)Laplacian函数的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 功能描述 计算图像的拉普拉斯值。 该函数通过使用 Sobel 运算符计算出的 x 和 y 的二阶导数之和来计算源图像的拉普拉斯值&#xff1a; dst Δ src ∂…

Elasticsearch:引入 Serverless 精简索引分片

作者&#xff1a;来自 Elastic Tanguy Leroux 在本文中&#xff0c;我们将介绍 Elasticsearch 的精简索引分片&#xff08;thin indexing shards&#xff09;&#xff0c;这是我们为 Elastic Cloud Serverless 开发的一种新型分片&#xff0c;允许将 Elasticsearch 索引存储在云…

大数据技术现场工程师特色实训室解决方案

一、引言 在大数据时代背景下&#xff0c;数据已成为新的生产要素&#xff0c;驱动着各行各业的创新发展。面对这一趋势&#xff0c;市场对于既掌握大数据理论知识又具备实战能力的大数据技术人才的需求急剧增加。为了应对这一挑战&#xff0c;唯众精心设计了一套全面的大数据…

国产 麒麟 ARM 环境编译 RocketMQ-Client-CPP

1.环境 系统版本&#xff1a;Linux 5.4.18-87.76-generic KYLINOS SMP Thu Aug 31 09:05:44 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux GCC: gcc (Ubuntu 9.3.0-10kylin2) 9.3.0 G: g (Ubuntu 9.3.0-10kylin2) 9.3.0 RocketMQ服务端版本&#xff1a;5.1.1 RocketMQ-cpp …

修改docker的/var/lib/docker/overlay2储存路径

目录 目录 1.准备新的存储位置 1.创建新的存储目录 2.修改目录权限 2. 配置 Docker 使用新的存储位置 1.停止 Docker 服务 2.编辑 Docker 配置文件 3.迁移现有 Docker 数据 1.将现有的 Docker 数据从系统盘移动到新目录 2.启动 Docker 服务 3. 验证更改 4. 清理旧的…

RAGFlow v0.9 重磅升级,支持 GraphRAG,开启下一代 RAG 之旅!

一、引言 前面我们介绍过很多的关于大模型和RAG相关的技术&#xff0c;通过其关注程度足以看到市场上对RAG框架和成熟产品的迫切需求&#xff0c;因为想要个人独立从0开始实现一个RAG产品并非易事&#xff0c;虽然有相当多的RAG或者知识库开源产品&#xff0c;大部分其实很难应…