【大模型基础】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

相关文章

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

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

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

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

详解如何使用Python从零开始构建文本统计模型

《详解如何使用Python从零开始构建文本统计模型》在自然语言处理领域,词汇表构建是文本预处理的关键环节,本文通过Python代码实践,演示如何从原始文本中提取多尺度特征,并通过动态调整机制构建更精确... 目录一、项目背景与核心思想二、核心代码解析1. 数据加载与预处理2. 多尺度字符统计3. 统计结果可

Linux基础命令@grep、wc、管道符的使用详解

《Linux基础命令@grep、wc、管道符的使用详解》:本文主要介绍Linux基础命令@grep、wc、管道符的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录grep概念语法作用演示一演示二演示三,带选项 -nwc概念语法作用wc,不带选项-c,统计字节数-

SpringBoot整合Sa-Token实现RBAC权限模型的过程解析

《SpringBoot整合Sa-Token实现RBAC权限模型的过程解析》:本文主要介绍SpringBoot整合Sa-Token实现RBAC权限模型的过程解析,本文给大家介绍的非常详细,对大家的学... 目录前言一、基础概念1.1 RBAC模型核心概念1.2 Sa-Token核心功能1.3 环境准备二、表结

python操作redis基础

《python操作redis基础》Redis(RemoteDictionaryServer)是一个开源的、基于内存的键值对(Key-Value)存储系统,它通常用作数据库、缓存和消息代理,这篇文章... 目录1. Redis 简介2. 前提条件3. 安装 python Redis 客户端库4. 连接到 Re

SpringBoot基础框架详解

《SpringBoot基础框架详解》SpringBoot开发目的是为了简化Spring应用的创建、运行、调试和部署等,使用SpringBoot可以不用或者只需要很少的Spring配置就可以让企业项目快... 目录SpringBoot基础 – 框架介绍1.SpringBoot介绍1.1 概述1.2 核心功能2

Spring Boot集成SLF4j从基础到高级实践(最新推荐)

《SpringBoot集成SLF4j从基础到高级实践(最新推荐)》SLF4j(SimpleLoggingFacadeforJava)是一个日志门面(Facade),不是具体的日志实现,这篇文章主要介... 目录一、日志框架概述与SLF4j简介1.1 为什么需要日志框架1.2 主流日志框架对比1.3 SLF4

Spring Boot集成Logback终极指南之从基础到高级配置实战指南

《SpringBoot集成Logback终极指南之从基础到高级配置实战指南》Logback是一个可靠、通用且快速的Java日志框架,作为Log4j的继承者,由Log4j创始人设计,:本文主要介绍... 目录一、Logback简介与Spring Boot集成基础1.1 Logback是什么?1.2 Sprin

MySQL复合查询从基础到多表关联与高级技巧全解析

《MySQL复合查询从基础到多表关联与高级技巧全解析》本文主要讲解了在MySQL中的复合查询,下面是关于本文章所需要数据的建表语句,感兴趣的朋友跟随小编一起看看吧... 目录前言:1.基本查询回顾:1.1.查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J1.2.按照部门