自然语言处理: N-Gram实战

news2025/1/21 3:02:33

自然语言处理: 第一章N-Gram



一. 理论

定义: 语言模型在wiki的定义是统计式的语言模型是一个几率分布,给定一个长度为 m 的字词所组成的字串 W1 , W2 ,··· ,Wn ,派几率的字符串P(S) = P(W1 , W2 ,··· ,Wn , )而其中由条件概率公式我们可以得到下图2的公式,然后我们再利用马尔可夫假设(每个词的出现的概率只与前面那个词有关) 得到下面的公式3

在这里插入图片描述



而N-gram的意思,就是每个词出现的概率只取决于前面n - 1个单词的,其中单词的概念可以是词组也可以是字,比如下图中的孙悟空这种单独拆开词无意义的可以看作一个单词。举个例子比如说是2-gram, 我们看到孙悟空这个词需要去预测下一个单词是三,我们看到三需要预测下一个单词是打。所以这种模型的输出完全取决于语料库的概念
在这里插入图片描述

优缺点:

  • 优点
    • 计算简单
  • 缺点
    • 无法捕捉长距离的词汇关系
    • 完全取决于语料库的丰富程度
    • 没有考虑词之间的相似度



代码实现

  1. 构建自己的语料库,下面定义了一个函数从txt的文件里读取语料并且去掉换行符

    def read_corpus_file(file):
        with open(file, 'r' , encoding= 'utf-8') as f:
            corpus = f.readlines()
        return [line.strip() for line in corpus]
    
  2. 定义分词函数

  3. 计算ngram词频 , 根据输入的n 在语料库中计算词频,其中前 n - 1长度的单词是输入, 第n个单词是输出, 语料库中每出现一个则计数器+1

    # 定义计算N-Gram词频的函数
    def count_ngrams(corpus, n):
        ngrams_count = defaultdict(Counter)  # 创建一个字典存储N-Gram计数
        for text in corpus:  # 遍历语料库中的每个文本
            tokens = tokenize(text)  # 对文本进行分词
            for i in range(len(tokens) - n + 1):  # 遍历分词结果生成N-Gram
                ngram = tuple(tokens[i:i+n])  # 创建一个N-Gram元组
                prefix = ngram[:-1]  # 获取N-Gram的前缀
                token = ngram[-1]  # 获取N-Gram的目标单字
                ngrams_count[prefix][token] += 1  # 更新N-Gram计数
    
        # 输出信息
        print(f"{n}gram词频:") # 打印Bigram词频
        for prefix, counts in ngrams_count.items():
            print("{}: {}".format("".join(prefix), dict(counts)))
        print('-'*100)
        return ngrams_count
    
  4. 根据词频计算概率, 根据上面的词频去计算每个prefix 生成中心词的概率

    # 定义计算Bigram概率的函数
    def ngram_probabilities(ngram_counts):
        ngram_probs = defaultdict(Counter)  # 创建一个字典存储Bigram概率
        for prefix, tokens_count in ngram_counts.items():  # 遍历Bigram计数
            total_count = sum(tokens_count.values())  # 计算当前前缀的总计数
            for token, count in tokens_count.items():  # 遍历每个Bigram计数
                ngram_probs[prefix][token] = \
                    count / total_count  # 计算每个Bigram概率
    
        print("gram概率:") # 打印Bigram概率
        for prefix, probs in ngram_probs.items():
            print("{}: {}".format("".join(prefix), dict(probs)))
        print('-'*100)
        return ngram_probs
    
  5. 定义生成下一个词的函数,如果前缀不在语料库中则返回None,如果在的话取几率最大的作为输出

    # 定义生成下一个词的函数
    def generate_next_token(prefix, bigram_probs):
        if not prefix in bigram_probs:  # 如果前缀不在Bigram概率中,返回None
            return None
        next_token_probs = bigram_probs[prefix]  # 获取当前前缀对应的下一个词的概率
        next_token = max(next_token_probs, 
                         key=next_token_probs.get)  # 选择概率最大的词作为下一个词
    
        return next_token
    
  6. 生成连续文本, 这里需要根据n 和随机输入一个prefix 从而得到不间断的生成新的文本,由于可能生成的长度很长,这里通过设置length进行截断

    def generate_text(prefix, tigram_probs, length=8 , n = 2): 
        '''n : gram'''
        tokens = list(prefix)  # 将前缀转换为字符列表
        for _ in range(length - len(prefix)):  # 根据指定长度生成文本 
            # 获取当前前缀对应的下一个词
            next_token = generate_next_token(tuple(tokens[-1 * (n - 1) : ]), tigram_probs) 
            if not next_token: # 如果下一个词为None,跳出循环
                break
            tokens.append(next_token) # 将下一个词添加到生成的文本中
        return "".join(tokens) # 将字符列表连接成字符串
    



最后生成的结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ndd9jZne-1686236125354)(image/ngram/1686236001438.png)]

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

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

相关文章

web audio音效播放器/音乐播放器

这是一个基于Web Audio API、HTML和CSS构建的高级网页音频播放器。它允许用户播放音频文件、控制播放、可视化音频,并应用音频效果和过滤器。 Github仓库: https://github.com/sonichen/Web-Based-Audio-Player 希望大家多多star 环境 操作系统&#…

Android逆向解析加壳与脱壳技术

加壳 加壳是指在 APK 文件中插入额外的代码或数据,使得原始代码难以被分析和反编译。通常加壳是为了保护软件的知识产权或者防止逆向工程。下面是 Android 加壳的一般流程: 选择加壳工具:选择合适的加壳工具进行加壳,比如市面上…

【SpringCloud-1】注册中心-Eureka

springcloud微服务,相对于dubbo这种SOA架构,提供了一站式的全套解决方案,什么意思呢?就是说springcloud不需要依赖其他组件,自己提供了全套的 常规项目需要使用的技术和解决问题的方案。 比如dubbo需要依赖zk作为注册…

一文读懂二叉树

大家好,我是三叔,很高兴这期又和大家见面了,一个奋斗在互联网的打工人。 什么是二叉树 二叉树是一种由节点(Node)组成的数据结构,每个节点最多有两个子节点。它具有良好的层次结构,便于搜索和…

chatgpt赋能python:Python如何将IP地址转换为整数

Python如何将IP地址转换为整数 在计算机网络中,IP地址是一个包含32位的二进制数字,通常由四个8位二进制数字(即“点分十进制”)表示。但在某些情况下,需要将IP地址转换为整数,例如在网络编程中检查网络连接…

C语言:编写代码,演示多个字符从两端移动,向中间汇聚

题目: 给出第一个字符串,如:"welcome to school!!!!!", 设置第二个字符串:"######################", 两字符串字符数相等。 从第二个字符串两端开始移动,向中间汇聚&#…

Python 中判定整数

直接数值判定,表达式判定。 (本笔记适合学会 Python 基本数据类型,可以“融会贯通”的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 python 完全自学教程》&#…

IGP协议对SR-MPLS的扩展

目录 OSPF对于SR-MPLS的扩展 OSPF对邻接SID做了细分 10类LSA定义的TLV类型 10类LSA定义的TLV的报文格式 ISIS对SR-MPLS的扩展 ISIS对邻接SID做了细分 ISIS定义的Sub-TLV的类型 ISIS定义的Sub-TLV的报文格式 OSPF对于SR-MPLS的扩展 OSPF为了支持SR-MPLS通过新…

Vue.js 3.x Composition APIs 及简单使用

文章目录 Vue 3.0 和 2.x 的区别源码组织方式packages 目录结构 不同构建版本Composition API 设计动机设计动机Options API Demo:Composition API Demo:对比: 性能提升响应式系统升级编译优化优化打包体积 ViteESModuleVite as Vue-CLIVite 特点 Composition APICo…

NLP学习笔记三-数据处理基础

NLP学习笔记三-数据处理基础 NLP设计的处理处理技术也比较多,我们简单介绍一部分: 1.Tokenization NLP当中的Tokenization,博主以前无论是在文章中还是在代码中都能经常看到,这在自然语言处理中也是比较常用的技术。 Tokenizati…

ASEMI代理英飞凌TLD2314EL参数,LED驱动器TLD2314EL

编辑-Z TLD2314EL参数描述: 型号:TLD2314EL 电源电压VS:40V 输出电压VOUTx:40V 状态电压VST:6V 输出电流IOUTx:130 mA 结温Tj:-40~ 150℃ 储存温度Tstg:-55~ 150℃ 正常工作…

要不是和阿里P7聊过,我也不知道自己是个棒槌

前几天和一个朋友聊面试,他说上个月同时拿到了测试开发岗位腾讯和阿里的offer,最后选择了阿里。 阿里内部将员工一共分为了14个等级,P6是资深工程师,P7是技术专家。 其中P6和P7就是一个分水岭了,P6是最接近P7的不持股…

# Windows 专业版安装 Hyper-V

Windows 专业版安装 Hyper-V 文章目录 Windows 专业版安装 Hyper-V检查要求硬件要求安装方式使用 PowerShell 启用 Hyper-V使用 CMD 和 DISM 启用 Hyper-V通过设置启用 Hyper-V 角色 创建虚拟机Hyper-v 管理器创建Hyper-V Quick Create 完整官网地址:Windows 10 上的…

SpringCloud-Gateway的详细讲解以及完整的示意图和代码-下

目录 二说Gateway 路由配置 创建com/springcloud/config/GateWayRoutesConfig.java 测试 动态路由 示意图 代码实现 测试 注意事项和细节 代码 Predicate/断言 基本介绍 Route Predicate Factories 解读 Route Predicate 实例 After Route Predicate 测试 B…

tamper脚本编写与mitmdump

tamper脚本编写与mitmdump 0x01 前提 ​ 注入点在登录框处,但是目标每次都会先校验验证码,而验证码会在返回包中以json格式出现。 0x02 编写tamper脚本 由于目标的验证码在response中回显出来了,所以我们可以利用tamper脚本去读取验证码&a…

Python:SVOREX

公式看懂了就写导数。写完导数撸码 Car数据集上对比: 在Car数据集上,SVOREX稍微胜出。 """ SVOREX author: Daniel He at CQUPT 2023-06-08 """ import xlwt import xlrd import numpy as np import pandas as pd import matplotlib.pylab a…

17.16按摩师

目录 一、题目 二、分析代码 一、题目 面试题 17.16. 按摩师 - 力扣&#xff08;LeetCode&#xff09; 二、分析代码 class Solution { public:int massage(vector<int>& nums) {int nnums.size();// vector<int>dp(n,0);// if(n<0)// return 0;// if(n1…

Docker部署ssh连接工具webssh2

Docker部署ssh连接工具webssh2 一、检查系统版本二、检查docker状态三、下载webssh2镜像四、创建webssh2容器1.创建webssh2容器2.查看webssh2状态3.查看容器运行日志 五、访问webssh21. 访问webssh22. 远程连接服务器3. 文件管理 一、检查系统版本 检查操作系统版本 [rootserve…

Python对普通文件的操作

目录 1. 常用函数语法 1.1. open_打开文件 1.2. read_读取文件 1.3. readlines_读取文件 1.4. csv.reader_读取csv文件 1.5. write_写入内容 2. 操作普通文件 2.1. 读取内容 ① 按大小读取 ② 按行数读取 ③ 按列数读取 ④ 读取大文件 ⑤ 条件过滤 2.2. 写入内容…

一文详解!JMeter该如何并发测试和持续性压测?

目录 前言&#xff1a; 概念 并发测试 持续性压测 查看报告 总结 试试其他 API 工具 知识扩展&#xff1a; 前言&#xff1a; JMeter 是一个 Java 编写的开源负载测试工具&#xff0c;基于模拟用户、线程和请求&#xff0c;结合测试计划和策略&#xff0c;可以模拟真实…