动手学深度学习 6.3 语言模型数据集(周杰伦专辑歌词)
前言
从零开始学习ai文章系列计划是个人在《动手学深度学习》和《磨菇书》两本书的学习中的个人笔记,文章也会以课本中的章节分开,即每个章节一片笔记。我会尽量的把主要内容以及遇到的难点进行记录与解决,如果哪里有错误的欢迎指正。或者不清晰的可以直接查看原文部分。
《动手学深度学习》原文(课本):https://tangshusen.me/Dive-into-DL-PyTorch/#/
《动手学深度学习》代码:https://github.com/ShusenTang/Dive-into-DL-PyTorch
(由于有时候公式太多,可能会直接贴图片)
本节将介绍如何预处理一个语言模型数据集,并将其转换成字符级循环神经网络所需要的输入格式。
为此,我们收集了周杰伦从第一张专辑《Jay》到第十张专辑《跨时代》中的歌词,并在后面几节里应用循环神经网络来训练一个语言模型。当模型训练好后,我们就可以用这个模型来创作歌词。
1. 读取数据集
1 | import torch |
这个数据集有6万多个字符。为了打印方便,我们把换行符替换成空格,然后仅使用前1万个字符来训练模型。
1 | corpus_chars = corpus_chars.replace('\n', ' ').replace('\r', ' ') |
2. 建立字符索引
我们将每个字符映射成一个从0开始的连续整数,又称索引,来方便之后的数据处理。为了得到索引,我们将数据集里所有不同字符取出来,然后将其逐一映射到索引来构造词典。接着,打印vocab_size,即词典中不同字符的个数,又称词典大小。
1 | idx_to_char = list(set(corpus_chars)) |

之后,将训练数据集中每个字符转化为索引,并打印前20个字符及其对应的索引。
1 | # corpus_indices是文本中每个字都转换成数字来表示的list |

3. 时序数据的采样
在训练中我们需要每次随机读取小批量样本和标签。与之前章节的实验数据不同的是,时序数据的一个样本通常包含连续的字符。
假设时间步数为5,样本序列为5个字符,即“想”“要”“有”“直”“升”。
我们有两种方式对时序数据进行采样,分别是 随机采样 和 相邻采样 。
3.1 随机采样
下面的代码每次从数据里随机采样一个小批量。其中批量大小
batch_size
指每个小批量的样本数,num_steps
为每个样本所包含的时间步数。
在随机采样中,每个样本是原始序列上任意截取的一段序列。相邻的两个随机小批量在原始序列上的位置不一定相毗邻(也就是后续代码中的X中每个batch中的文本段内容都不是相连的,是随机的)。因此,我们无法用一个小批量最终时间步的隐藏状态来初始化下一个小批量的隐藏状态。
在训练模型时,每次随机采样前都需要重新初始化隐藏状态。
1 |
|
这里简单说明Y。
语言模型训练的目标是根据输入序列预测下一个词(即“语言建模”)。
假设 corpus_indices = [0, 1, 2, 3, 4, 5, 6],num_steps = 3。
那么对于 j = 1(也就是第 1 段,从0算起):
• start = j * num_steps = 3
• X = _data(3) = corpus_indices[3:6] = [3, 4, 5]
• Y = _data(4) = corpus_indices[4:7] = [4, 5, 6]
因此代码中一开始需要减1。
让我们输入一个从0到29的连续整数的人工序列。
设批量大小和时间步数分别为2和6。打印随机采样每次读取的小批量样本的输入X和标签Y。可见,相邻的两个随机小批量在原始序列上的位置不一定相毗邻。
1 | my_seq = list(range(30)) |
下图中可以看到每轮的X/Y中存在2(batch_size)个数据

3.2 相邻采样
除对原始序列做随机采样之外,我们还可以令相邻的两个随机小批量在原始序列上的位置相毗邻。
1 | def data_iter_consecutive(corpus_indices, batch_size, num_steps, device=None): |

总之我们知道不论随机还是相邻函数,其结果都是每次输出内含batch_size个字符串的X/Y矩阵(batch_size,num_steps)。
