动手学深度学习——语言模型和数据集(代码详解)

文章目录

    • 语言模型与数据集
      • 1. 学习语言模型
      • 2. 马尔可夫模型与n元语法
      • 3. 自然语言统计
      • 4. 读取长序列数据
        • 4.1 随机采样
        • 4.2 顺序分区

语言模型与数据集

了解到如何将文本数据映射到词元,以及将这些词元视作一系列的离散观测,例如单词或字符。

给定一个文本序列的在这里插入图片描述,xt表示文本序列在时间步t的观测或标签,语言模型的目标是估计序列的联合概率
在这里插入图片描述

1. 学习语言模型

如何对一个文档或者是一个词元序列进行建模?
假设在单词级别对文本数据进行词元化,从基本概率规则开始:在这里插入图片描述
则包含四个单词的一个文本序列的概率为:
在这里插入图片描述
为了训练语言模型,需要计算单词的概率, 以及给定前面几个单词后出现某个单词的条件概率。

这些概率本质上就是语言模型的参数。

2. 马尔可夫模型与n元语法

马尔可夫模型是一种描述随机过程的数学模型,它基于马尔可夫性质,即未来的状态只依赖于当前的状态,而与过去的状态无关。

马尔可夫性质: 阶数越高,对应的依赖关系就越长。下面是序列建模的近似公式:

在这里插入图片描述

通常,涉及一个、两个和三个变量的概率公式分别被称为 一元语法、二元语法和三元语法模型。

3. 自然语言统计

根据时光机器数据集构建词表, 并打印前10个最常用的(频率最高的)单词。

import random
import torch
from d2l import torch as d2l

tokens = d2l.tokenize(d2l.read_time_machine())
# 因为每个文本行不一定是一个句子或一个段落,因此我们把所有文本行拼接到一起
corpus = [token for line in tokens for token in line]
vocab = d2l.Vocab(corpus)
vocab.token_freqs[:10]

在这里插入图片描述
最流行的词通常被称为停用词,画出词频图

# 最流行的词通常被称为停用词
# 词频图
freqs = [freq for token, freq in vocab.token_freqs]
d2l.plot(freqs, xlabel='token: x', ylabel='frequency: n(x)',
         xscale='log', yscale='log')

在这里插入图片描述
上图表示词频以一种明确的方式迅速衰减,接下来看二元语法的频率

# 二元语法的频率
bigram_tokens = [pair for pair in zip(corpus[:-1], corpus[1:])]
bigram_vocab = d2l.Vocab(bigram_tokens)
bigram_vocab.token_freqs[:10]

在这里插入图片描述
三元语法的频率

# 三元语法
# corpus词元索引列表
trigram_tokens = [triple for triple in zip(
    corpus[:-2], corpus[1:-1], corpus[2:])]
trigram_vocab = d2l.Vocab(trigram_tokens)
trigram_vocab.token_freqs[:10]

在这里插入图片描述
直观地对比三种模型中的词元频率:一元语法、二元语法和三元语法

# 直观地对比三种模型中的词元频率:一元语法、二元语法和三元语法。
bigram_freqs = [freq for token, freq in bigram_vocab.token_freqs]
trigram_freqs = [freq for token, freq in trigram_vocab.token_freqs]
d2l.plot([freqs, bigram_freqs, trigram_freqs], xlabel='token: x',
         ylabel='frequency: n(x)', xscale='log', yscale='log',
         legend=['unigram', 'bigram', 'trigram'])

在这里插入图片描述

4. 读取长序列数据

当序列变得太长而不能被模型一次性全部处理时, 我们可能希望拆分这样的序列方便模型读取。 任意长的序列可以被划分为具有相同时间步数的子序列。

4.1 随机采样

在随机采样中,每个样本都是在原始的长序列上任意捕获的子序列。 对于语言建模,目标是基于到目前为止我们看到的词元来预测下一个词元, 因此标签是移位了一个词元的原始序列。

def seq_data_iter_random(corpus, batch_size, num_steps):  #@save
    """使用随机抽样生成一个小批量子序列"""
    # 从随机偏移量开始对序列进行分区,随机范围包括num_steps-1
    corpus = corpus[random.randint(0, num_steps - 1):]
    # 减去1,是因为我们需要考虑标签
    num_subseqs = (len(corpus) - 1) // num_steps
    # 长度为num_steps的子序列的起始索引
    initial_indices = list(range(0, num_subseqs * num_steps, num_steps))
    # 在随机抽样的迭代过程中,
    # 来自两个相邻的、随机的、小批量中的子序列不一定在原始序列上相邻
    random.shuffle(initial_indices)

    def data(pos):
        # 返回从pos位置开始的长度为num_steps的序列
        return corpus[pos: pos + num_steps]

    num_batches = num_subseqs // batch_size
    for i in range(0, batch_size * num_batches, batch_size):
        # 在这里,initial_indices包含子序列的随机起始索引
        initial_indices_per_batch = initial_indices[i: i + batch_size]
        X = [data(j) for j in initial_indices_per_batch]
        Y = [data(j + 1) for j in initial_indices_per_batch]
        yield torch.tensor(X), torch.tensor(Y)

生成一个从0到34的序列。 假设批量大小为2,时间步数为5,这意味着可以生成 [(35-1)/5]=6个“特征-标签”子序列对。 如果设置小批量大小为2,我们只能得到3个小批量。

my_seq = list(range(35))
for X, Y in seq_data_iter_random(my_seq, batch_size=2, num_steps=5):
    print('X: ', X, '\nY:', Y)

在这里插入图片描述

4.2 顺序分区

保证两个相邻的小批量中的子序列在原始序列上也是相邻的。 这种策略在基于小批量的迭代过程中保留了拆分的子序列的顺序,因此称为顺序分区。

"""
生成小批量子序列的函数,它使用顺序分区的方式将一个长序列划分为若干个长度相同的子序列:
- corpus:一个包含所有词元索引的列表
- batch_size:每个小批量中样本的数量
- num_steps:每个输入序列的时间步数
"""
def seq_data_iter_sequential(corpus, batch_size, num_steps):  #@save
    """使用顺序分区生成一个小批量子序列"""
    # 从随机偏移量开始划分序列
    offset = random.randint(0, num_steps)
    num_tokens = ((len(corpus) - offset - 1) // batch_size) * batch_size
    Xs = torch.tensor(corpus[offset: offset + num_tokens])
    Ys = torch.tensor(corpus[offset + 1: offset + 1 + num_tokens])
    # 将Xs和Ys的形状从原来的一维数组调整为一个二维数组,
    # 其中有batch_size行,而列数根据原数组的长度和batch_size的值自动计算得出
    Xs, Ys = Xs.reshape(batch_size, -1), Ys.reshape(batch_size, -1)
    num_batches = Xs.shape[1] // num_steps
    for i in range(0, num_steps * num_batches, num_steps):
        X = Xs[:, i: i + num_steps]
        Y = Ys[:, i: i + num_steps]
        yield X, Y

基于相同的设置,通过顺序分区读取每个小批量的子序列的特征X和标签Y

for X, Y in seq_data_iter_sequential(my_seq, batch_size=2, num_steps=5):
    print('X: ', X, '\nY:', Y)

在这里插入图片描述
将上面的两个采样函数包装到一个类中, 以便稍后可以将其用作数据迭代器

class SeqDataLoader:  #@save
    """加载序列数据的迭代器"""
    # 根据use_random_iter的值选择使用随机迭代器或顺序迭代器
    def __init__(self, batch_size, num_steps, use_random_iter, max_tokens):
        if use_random_iter:
            self.data_iter_fn = d2l.seq_data_iter_random
        else:
            self.data_iter_fn = d2l.seq_data_iter_sequential
        self.corpus, self.vocab = d2l.load_corpus_time_machine(max_tokens)
        self.batch_size, self.num_steps = batch_size, num_steps

    # 返回一个迭代器对象
    def __iter__(self):
        return self.data_iter_fn(self.corpus, self.batch_size, self.num_steps)

定义了一个函数load_data_time_machine, 它同时返回数据迭代器和词表

def load_data_time_machine(batch_size, num_steps,  #@save
                           use_random_iter=False, max_tokens=10000):
    """返回时光机器数据集的迭代器和词表"""
    data_iter = SeqDataLoader(
        batch_size, num_steps, use_random_iter, max_tokens)
    return data_iter, data_iter.vocab

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《洛谷深入浅出进阶篇》P3397 地毯————二维差分

上链接:P3397 地毯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P3397 上题干: 题目描述 在 nn 的格子上有 m 个地毯。 给出这些地毯的信息,问每个点被多少个地毯覆盖。 输入格式 第一行,两个…

配置sonarQube

1.新版本需要安装JDK11以上版本 2.修改解压(解压在一个路径不包含特殊符号、中文、空格的位置里)出来的sonar文件夹中conf下面的配置文件(sonar.properties) sonar.jdbc.usernameXXX sonar.jdbc.passwordXXXsonar.jdbc.urljdbc:sqlserver://172.168.1.…

小学生写作业用什么台灯好?专业的学生台灯推荐

说到台灯相信大家都不陌生,不管是办公族还是学生基本都会备上一台。而且现在的孩子很多都是存在视力问题的,主要的原因就是学习压力太大了,用眼时间过长导致的。所以很多家长选择给孩子使用更为专业的护眼台灯。 不过目前市面上的灯具也是良莠…

Qt Jom Parallel Builds 并行构造

1.Qt官网下载 Jom - Qt Wiki 下载jom源码 git clone git://code.qt.io/qt-labs/jom.git 2.生成makefile qmake -r 进入jom源码目录 执行qmake -r 3.编译 nmake jom编译成功 4.复制到qmake所在目录并运行

基于JAVA SpringBoot和HTML美食网站博客程序设计

摘要 美食网站是一个提供各种美食信息和食谱的网站,旨在帮助用户发现、学习和分享美食。旨在探讨美食网站在现代社会中的重要性和影响。随着互联网的普及,越来越多的人开始使用美食网站来获取各种美食信息和食谱。这些网站不仅提供了方便快捷的搜索功能&…

SAP删除自建、系统表数据的方法

1、输入前台事务码 SE16N 进入 常规表显示 2、输入自建表名称后,回车展示字段 在事务栏中输入 /H 启用编辑 敲击回车 (消息显示调试被激活) 然后点击执行 3、在右下角栏目中输入 GD-SAPEDIT 和 GD-EDIT 点击 小笔 启用编辑,将两…

哔哩哔哩自动引流软件的运行分享,以及涉及到技术与核心代码分享

先来看实操成果,↑↑需要的同学可看我名字↖↖↖↖↖,或评论888无偿分享 大家好,我是一名专注于自动引流软件研发的技术专家。今天,我将与大家分享自动引流软件涉及到的技术与核心代码,希望能为大家提供一些有价值的参…

【每日一题】2656. k个元素的最大和-2023.11.15

题目: 2656. K 个元素的最大和 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。你需要执行以下操作 恰好 k 次,最大化你的得分: 从 nums 中选择一个元素 m 。将选中的元素 m 从数组中删除。将新元素 m 1 添加到数组中。你的得分增…

冰点还原精灵Deep Freeze for mac:Mac用户的最佳系统保护选择

你是否曾在Mac上安装软件后,发现系统性能下降,或者某些应用程序无法正常运行?这些问题可能让你感到困扰,但幸运的是,有一个解决方案可以帮你解决这些问题——Faronics Deep Freeze for mac。 Deep Freeze for mac是一…

3.1 Linux 前置知识

1、硬件 我们知道,组成计算机的硬件主要有“主机”和“输入/输出设备”。 主机包括机箱、电源、主板、CPU(Central Processing Unit,中央处理器)、内存、显卡、声卡、网卡、 硬盘、光驱等。输入/输出设备包括显示器、键盘、鼠标…

dubbo服务超时导致的异常

今天服务器启动项目时,页面刷新报错: 查看日志时报错信息为: 解决: 在对应服务的配置文件中配置dubbo超时时间: 随后问题得到解决,特此记录

JimuReport积木报表 v1.6.5 版本发布—免费报表工具

项目介绍 一款免费的数据可视化报表,含报表和大屏设计,像搭建积木一样在线设计报表!功能涵盖,数据报表、打印设计、图表报表、大屏设计等! Web 版报表设计器,类似于excel操作风格,通过拖拽完成报…

虹科示波器 | 汽车免拆检修 | 2021款广汽丰田威兰达PHEV车发动机故障灯异常点亮

一、故障现象 一辆2021款广汽丰田威兰达PHEV车,搭载A25D-FXS发动机和动力蓄电池系统(额定电压为355.2V,额定容量为45.0Ah),累计行驶里程约为1万km。车主反映,高速行驶时发动机突然抖动,且发动机…

软件项目验收测试计划

验收测试计划 1.基本信息 2.项目成果及验收要求 2.1项目成果 2.2验收要求 1、满足业务风险控制法律法规要求。 3.验收组织 4.产品交付 5.产品安装 5.1环境要求 5.2数据库配置 5.3程序配置 6.验收测试方案 6.1测试 依据 6.2测试要求 6.3测试方法 6.4测试工作流程 6.5测试通过准则…

去掉 webstorm 白线

webstorm 编辑界面出现一条白线 ctrlshifta 打开设置窗口, 输入 “显示右边距” 英文版输入 “show right margin” 点击关闭即可

操作系统实验四 死锁问题

一、问题描述 看上图,有五位哲学家,面前都有一个盘子,盘子左边和右边都有一根筷子,他们在吃面之前需要先拿起左边的筷子再拿起右边的筷子,有了一双筷子就可以吃面了。 二、流程 先拿起左手的筷子然后拿起右手的筷子…

Outlook无法显示阅读窗格

Outlook无法显示阅读窗格 故障现象 Outlook主界面不显示阅读窗格 故障截图 故障原因 阅读窗格被关闭 解决方案 1、打开Outlook - 视图 – 阅读窗格 2、选择“靠右”或者“底部”,正常显示阅读窗格

linux之用户管理

一、是什么 Linux是一个多用户的系统,允许使用者在系统上通过规划不同类型、不同层级的用户,并公平地分配系统资源与工作环境 而与 Windows 系统最大的不同, Linux 允许不同的用户同时登录主机,同时使用主机的资源 既然是多用户…

洗眼镜手动清洗还是用超声波清洗机洗好?值得入手超声波清洗机

眼镜清洗的方法有很多,但是一定要选择合适的正确的清洗方式,使用错误清洗眼镜方法会非常容易缩短眼镜使用寿命。一副眼镜正常情况下是可以使用2~3年的,大家可千万要多注意清洗眼镜的手法!像最常见眼镜清洗的手法是用衣服擦拭一下或…

Linux之输入输出重定向和管道

一、是什么 linux中有三种标准输入输出,分别是STDIN,STDOUT,STDERR,对应的数字是0、1、2: STDIN 是标准输入,默认从键盘读取信息STDOUT 是标准输出,默认将输出结果输出至终端STDERR 是标准错误…