【大模型基础】P1 N-Gram 模型

2024-09-08 04:20
文章标签 基础 模型 gram p1

本文主要是介绍【大模型基础】P1 N-Gram 模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • N-Gram 概述
  • N-Gram 构建过程
  • Token
  • N-Gram 实例
    • 第1步 构建实验语料库
    • 第2步 把句子分成 N 个 “Gram”
    • 第3步 计算每个 Bigram 在语料库中的词频
    • 第4步 计算出现的概率
    • 第5步 生成下一个词
    • 第6步:输入前缀,生成连续文本
  • 上述实例完整代码
  • N-Gram 的局限性

N-Gram 概述

N-Gram 诞生于统计学 NLP 初期,为解决词序列冗长导致的高复杂性概率计算。其通过分割文本为连续 N 个词的组合,来预测下一个词。

e . g . e.g. e.g. 我喜欢大模型
根据分词结果,文本中有三个词:“我”、“喜欢”、“大模型”

  • N=1,组合成一元组(Unigram):“我”、“喜欢”、“大模型”
  • N=2,组合成二元组(Bigram):“我喜欢”、“喜欢大模型”
  • N=3,组合成三元组(Trigram):“我喜欢大模型”

N-Gram 构建过程

第一步:分割文本为连续 N 个词的组合(N-Gram)

  • 以二元组(Bigram)为例,将语料库中文本进行分割。
  • e . g . e.g. e.g. 我爱吃香菜
    在这里插入图片描述

第二步:统计每个 N-Gram 在文本中出现的次数,即词频

  • 在语料库 ["我爱吃香菜", "我爱吃涮", "我爱吃汉堡", "我喜欢你", "我也爱吃水果"] 中,Bigram “我爱” 出现了 3 次。

第三步:计算下一个词出现的概率

  • 二元组 “我爱” 出现了 3 次,而其前缀 “我” 在语料库中出现了 5 次,则给定 “我” 为前缀时,下一个词为 “爱” 的概率为 60%

在这里插入图片描述

第四步:迭代上述过程,生成整段文本内容

在这里插入图片描述


Token

上述内容中,我们将文本 “我爱吃香菜” 分为了 4 个词。但是标准的说法,是分成了 4 个 Token。

在 NLP 中,

  • 英文分词方法通常使用 NLTK、spaCy 等自然语言处理库。
  • 中文分词则通常使用 jieba 库。
  • 在预训练模型在 BERT 中,使用 Tokenizer 库。

分词是预处理的一个重要环节,其他还包括文本清洗、去停用词、词干提取、词性标注等环节。


N-Gram 实例

整体流程一览图如下:

在这里插入图片描述

第1步 构建实验语料库

# 构建语料库
corpus = ["我喜欢吃苹果", "我喜欢吃香蕉", "她喜欢吃葡萄", "他不喜欢吃香蕉", "他喜欢吃苹果", "她喜欢吃草莓"]

第2步 把句子分成 N 个 “Gram”

import jiebadef generate_bigrams(corpus):bigram_list = []for sentence in corpus:# 使用jieba分词words = list(jieba.cut(sentence))bigrams = [(words[i] , words[i + 1]) for i in range(len(words) - 1)]bigram_list.extend(bigrams)return bigram_listbigrams = generate_bigrams(corpus)
print(bigrams)

结果:

[('我', '喜欢'), ('喜欢', '吃'), ('吃', '苹果'), ('我', '喜欢'), ('喜欢', '吃'), ('吃', '香蕉'), ('她', '喜欢'), ('喜欢', '吃'), ('吃', '葡萄'), ('他', '不'), ('不', '喜欢'), ('喜欢', '吃'), ('吃', '香蕉'), ('他', '喜欢'), ('喜欢', '吃'), ('吃', '苹果'), ('她', '喜欢'), ('喜欢', '吃'), ('吃', '草莓')]

第3步 计算每个 Bigram 在语料库中的词频

from collections import defaultdict, Counterdef count_bigrams(bigrams):# 创建字典存储biGram计数bigrams_count = defaultdict(Counter)for bigram in bigrams:prefix = bigram[:-1]token = bigram[-1]bigrams_count[prefix][token] += 1return bigrams_countbigrams_counts = count_bigrams(bigrams)
for prefix, counts in bigrams_counts.items():print("{}: {}".format("".join(prefix), dict(counts)))

结果:

: {'喜欢': 2}
喜欢: {'吃': 6}: {'苹果': 2, '香蕉': 2, '葡萄': 1, '草莓': 1}: {'喜欢': 2}: {'不': 1, '喜欢': 1}: {'喜欢': 1}

第4步 计算出现的概率

def bigram_probabilities(bigrams_count):bigrams_prob = defaultdict(Counter)for prefix, tokens_count in bigrams_count.items():total_count = sum(tokens_count.values())for token, count in tokens_count.items():bigrams_prob[prefix][token] = count / total_countreturn bigrams_probbigrams_prob = bigram_probabilities(bigrams_count)
for prefix, probs in bigrams_prob.items():print("{}: {}".format("".join(prefix), dict(probs)))

结果:

: {'喜欢': 1.0}
喜欢: {'吃': 1.0}: {'苹果': 0.3333333333333333, '香蕉': 0.3333333333333333, '葡萄': 0.16666666666666666, '草莓': 0.16666666666666666}: {'喜欢': 1.0}: {'不': 0.5, '喜欢': 0.5}: {'喜欢': 1.0}

第5步 生成下一个词

def generate_token(prefix, bigram_probs):if not prefix in bigram_probs:return Nonenext_token_probs = bigram_probs[prefix]next_token = max(next_token_probs, key=next_token_probs.get)return next_token

第6步:输入前缀,生成连续文本

def generate_text(prefix, bigram_probs, length=6):tokens = list(prefix)for _ in range(length - len(prefix)):next_token = generate_token(tuple(tokens[-1:]), bigram_probs)if not next_token:breaktokens.append(next_token)return "".join(tokens)generate_text("我", bigram_probs)

结果:

'我喜欢吃苹果'

上述实例完整代码

import jieba
from collections import defaultdict, Counter# 构建语料库
corpus = ["我喜欢吃苹果", "我喜欢吃香蕉", "她喜欢吃葡萄", "他不喜欢吃香蕉", "他喜欢吃苹果", "她喜欢吃草莓"]# 二元组切词
def generate_bigrams(corpus):bigram_list = []for sentence in corpus:# 使用jieba分词words = list(jieba.cut(sentence))bigrams = [(words[i] , words[i + 1]) for i in range(len(words) - 1)]bigram_list.extend(bigrams)return bigram_list# 计算二元组词频
def count_bigrams(bigrams):# 创建字典存储biGram计数bigrams_count = defaultdict(Counter)for bigram in bigrams:prefix = bigram[:-1]token = bigram[-1]bigrams_count[prefix][token] += 1return bigrams_count# 计算二元组概率
def bigram_probabilities(bigrams_count):bigram_probs = defaultdict(Counter)for prefix, tokens_count in bigrams_count.items():total_count = sum(tokens_count.values())for token, count in tokens_count.items():bigram_probs[prefix][token] = count / total_countreturn bigram_probs# 生成内容
def generate_token(prefix, bigram_probs):if not prefix in bigram_probs:return Nonenext_token_probs = bigram_probs[prefix]next_token = max(next_token_probs, key=next_token_probs.get)return next_tokendef generate_text(prefix, bigram_probs, length=6):tokens = list(prefix)for _ in range(length - len(prefix)):next_token = generate_token(tuple(tokens[-1:]), bigram_probs)if not next_token:breaktokens.append(next_token)return "".join(tokens)if __name__ == '__main__':bigrams = generate_bigrams(corpus)print(bigrams)bigrams_count = count_bigrams(bigrams)for prefix, counts in bigrams_count.items():print("{}: {}".format("".join(prefix), dict(counts)))bigram_probs = bigram_probabilities(bigrams_count)for prefix, probs in bigram_probs.items():print("{}: {}".format("".join(prefix), dict(probs)))res = generate_text("我", bigram_probs)print(res)

N-Gram 的局限性

N-Gram 模型具有很大的启发意义和价值,我们只需要一个简单的语料库,结合二元组模型,即可生成一段话。

N-Gram 模型中,我们预测一个词出现的频率,只考虑其之前的 N-1 个词,其优点是计算简单,但是缺点也很明显,那就是它无法捕捉到距离较远的词之间的关系。

下一节,将介绍于 N-Gram 同时代产物,词袋模型(Bag-of-Words)。词袋模型不考虑哪个词和哪个词接近,而是通过把词看作一袋子元素的方式来把文本转换为能统计的特征。


2024.09.07

这篇关于【大模型基础】P1 N-Gram 模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1147097

相关文章

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

从基础到高阶详解Python多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式

MySQL数据类型与表操作全指南( 从基础到高级实践)

《MySQL数据类型与表操作全指南(从基础到高级实践)》本文详解MySQL数据类型分类(数值、日期/时间、字符串)及表操作(创建、修改、维护),涵盖优化技巧如数据类型选择、备份、分区,强调规范设计与... 目录mysql数据类型详解数值类型日期时间类型字符串类型表操作全解析创建表修改表结构添加列修改列删除列

Python 函数详解:从基础语法到高级使用技巧

《Python函数详解:从基础语法到高级使用技巧》本文基于实例代码,全面讲解Python函数的定义、参数传递、变量作用域及类型标注等知识点,帮助初学者快速掌握函数的使用技巧,感兴趣的朋友跟随小编一起... 目录一、函数的基本概念与作用二、函数的定义与调用1. 无参函数2. 带参函数3. 带返回值的函数4.

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

安装centos8设置基础软件仓库时出错的解决方案

《安装centos8设置基础软件仓库时出错的解决方案》:本文主要介绍安装centos8设置基础软件仓库时出错的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录安装Centos8设置基础软件仓库时出错版本 8版本 8.2.200android4版本 javas